repo time

Dependencies:   mbed MAX14720 MAX30205 USBDevice

Files at this revision

API Documentation at this revision

Comitter:
darienf
Date:
Tue Apr 06 06:41:40 2021 +0000
Parent:
19:002c398f14cc
Commit message:
another repo

Changed in this revision

HspGuiSourceV301/EcgViewTest/EcgTest.cs Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/EcgViewTest/EcgViewTest.csproj Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/EcgViewTest/PaceTest.cs Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/EcgViewTest/Properties/AssemblyInfo.cs Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/EcgViewTest/RToRCalculatorTest.cs Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/EcgViewTest/RToRTest.cs Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/EcgViewTest/TemperatureTest.cs Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/EcgViewTest/packages.config Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/FirFilterTest/App.config Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/FirFilterTest/FirFilterTest.csproj Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/FirFilterTest/Program.cs Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/FirFilterTest/Properties/AssemblyInfo.cs Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/FirFilterTest/Properties/Resources.Designer.cs Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/FirFilterTest/Properties/Resources.resx Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/GuiDLLs/ChartHelper/ChartHelper/AutoScaleCalculator.cs Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/GuiDLLs/ChartHelper/ChartHelper/ChartHelper.csproj Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/GuiDLLs/ChartHelper/ChartHelper/IAutoScaleAxisCalculator.cs Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/GuiDLLs/ChartHelper/ChartHelper/Properties/AssemblyInfo.cs Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/GuiDLLs/ChartHelper/Maxim.Charting.ChartHelper.sln Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/GuiDLLs/FileLog/FileLog.sln Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/GuiDLLs/FileLog/FileLog/FileCsvReader.cs Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/GuiDLLs/FileLog/FileLog/FileLog.cs Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/GuiDLLs/FileLog/FileLog/FileLog.csproj Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/GuiDLLs/FileLog/FileLog/Properties/AssemblyInfo.cs Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/GuiDLLs/FileLog/FileLogExample/App.config Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/GuiDLLs/FileLog/FileLogExample/FileLogExample.csproj Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/GuiDLLs/FileLog/FileLogExample/Form1.Designer.cs Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/GuiDLLs/FileLog/FileLogExample/Form1.cs Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/GuiDLLs/FileLog/FileLogExample/Form1.resx Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/GuiDLLs/FileLog/FileLogExample/Program.cs Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/GuiDLLs/FileLog/FileLogExample/Properties/AssemblyInfo.cs Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/GuiDLLs/FileLog/FileLogExample/Properties/Resources.Designer.cs Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/GuiDLLs/FileLog/FileLogExample/Properties/Resources.resx Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/GuiDLLs/FileLog/FileLogExample/Properties/Settings.Designer.cs Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/GuiDLLs/FileLog/FileLogExample/TextCases.txt Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/GuiDLLs/MaximGlobal/App.config Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/GuiDLLs/MaximGlobal/ErrorEventArgs.cs Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/GuiDLLs/MaximGlobal/Maxim.Global.csproj Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/GuiDLLs/MaximStyle/MaximStyle.dll Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/GuiDLLs/RPCSupport/DataLogging/DataLogging.cs Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/GuiDLLs/RPCSupport/DataLogging/StreamDataLog.cs Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/GuiDLLs/RPCSupport/DeviceSupport/DeviceDetails.cs Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/GuiDLLs/RPCSupport/DeviceSupport/RegisterBitDescriptions.cs Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/GuiDLLs/RPCSupport/DeviceSupport/RegisterInfo.cs Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/GuiDLLs/RPCSupport/Devices/ClientDevice.cs Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/GuiDLLs/RPCSupport/Devices/I2cDevice.cs Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/GuiDLLs/RPCSupport/Devices/IRegisterDevice.cs Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/GuiDLLs/RPCSupport/Devices/LIS2HD.cs Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/GuiDLLs/RPCSupport/Devices/Led.cs Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/GuiDLLs/RPCSupport/Devices/MAX30001.cs Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/GuiDLLs/RPCSupport/Devices/MAX30101/MAX30101.cs Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/GuiDLLs/RPCSupport/Devices/MAX30205.cs Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/GuiDLLs/RPCSupport/Devices/S25FS512.cs Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/GuiDLLs/RPCSupport/Devices/SpiDevice.cs Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/GuiDLLs/RPCSupport/Devices/Testing.cs Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/GuiDLLs/RPCSupport/Dialogs/RpcLog.Designer.cs Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/GuiDLLs/RPCSupport/Dialogs/RpcLog.cs Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/GuiDLLs/RPCSupport/Dialogs/RpcLog.resx Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/GuiDLLs/RPCSupport/HidSupport/FileIODeclarations.cs Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/GuiDLLs/RPCSupport/HidSupport/HID.cs Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/GuiDLLs/RPCSupport/HidSupport/support.cs Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/GuiDLLs/RPCSupport/Logging/Logging.cs Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/GuiDLLs/RPCSupport/Pipelines/DataLogPipeline.cs Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/GuiDLLs/RPCSupport/Pipelines/HidPipeline.cs Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/GuiDLLs/RPCSupport/Pipelines/Pipeline.cs Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/GuiDLLs/RPCSupport/Pipelines/SerialPipeline.cs Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/GuiDLLs/RPCSupport/Pipelines/SerialWrapPipeline.cs Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/GuiDLLs/RPCSupport/Properties/AssemblyInfo.cs Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/GuiDLLs/RPCSupport/RPCClient.cs Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/GuiDLLs/RPCSupport/RPCSupport.csproj Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/GuiDLLs/RPCSupport/Streaming/Crc32.cs Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/GuiDLLs/RPCSupport/Streaming/PartialArrayIntAvailableEventArgs.cs Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/GuiDLLs/RPCSupport/Streaming/Streaming.cs Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/GuiDLLs/RPCSupport/Streaming/StreamingParameters.cs Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/GuiDLLs/SKA/SKA.dll Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/GuiDLLs/SerialWrap/App.config Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/GuiDLLs/SerialWrap/SerialPortTester.cs Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/GuiDLLs/SerialWrap/SerialWrap.csproj Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/GuiDLLs/SerialWrap/packages.config Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/GuiDLLs/SerialWrap/serialportio.cs Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/HSPApp.sln Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/HSPGui/Algorithm/InterfaceRedIRGreenLEDdataConsumer.cs Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/HSPGui/Algorithm/MaximAlgorithmClass.cs Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/HSPGui/Algorithm/MaximSKAlgorithmClass.cs Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/HSPGui/Algorithm/SKA.cs Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/HSPGui/AlgorithmMobileBU.cs Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/HSPGui/BioZChannel.cs Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/HSPGui/BioZLoad.cs Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/HSPGui/BioZMux.cs Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/HSPGui/CustomControls/DoubleBufferTableLayoutPanel.Designer.cs Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/HSPGui/CustomControls/DoubleBufferTableLayoutPanel.cs Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/HSPGui/CustomControls/EcgView.Designer.cs Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/HSPGui/CustomControls/EcgView.cs Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/HSPGui/CustomControls/EcgView.resx Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/HSPGui/CustomControls/IDataLoggingView.cs Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/HSPGui/CustomControls/IDeviceView.cs Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/HSPGui/CustomControls/IEcgView.cs Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/HSPGui/CustomControls/IFileLogView.cs Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/HSPGui/CustomControls/ITemperatureView.cs Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/HSPGui/CustomControls/InitArgs.cs Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/HSPGui/CustomControls/LoggingView.Designer.cs Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/HSPGui/CustomControls/LoggingView.cs Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/HSPGui/CustomControls/LoggingView.resx Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/HSPGui/CustomControls/OpticalView.Designer.cs Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/HSPGui/CustomControls/OpticalView.cs Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/HSPGui/CustomControls/OpticalView.resx Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/HSPGui/CustomControls/PrimitivesView.Designer.cs Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/HSPGui/CustomControls/PrimitivesView.cs Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/HSPGui/CustomControls/PrimitivesView.resx Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/HSPGui/CustomControls/RegisterExportView.Designer.cs Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/HSPGui/CustomControls/RegisterExportView.cs Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/HSPGui/CustomControls/RegisterExportView.resx Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/HSPGui/CustomControls/RegisterView.cs Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/HSPGui/CustomControls/RegisterView.designer.cs Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/HSPGui/CustomControls/RegisterView.resx Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/HSPGui/CustomControls/StreamingStartStopEventArgs.cs Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/HSPGui/CustomControls/TemperatureView.Designer.cs Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/HSPGui/CustomControls/TemperatureView.cs Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/HSPGui/CustomControls/TemperatureView.resx Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/HSPGui/DeviceDescriptions/AccelDevice.cs Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/HSPGui/DeviceDescriptions/Device.cs Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/HSPGui/DeviceDescriptions/DeviceController.cs Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/HSPGui/DeviceDescriptions/DeviceDetails.cs Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/HSPGui/DeviceDescriptions/LIS2DHInfo.cs Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/HSPGui/DeviceDescriptions/MAX14720Info.cs Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/HSPGui/DeviceDescriptions/MAX30001Info.cs Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/HSPGui/DeviceDescriptions/MAX30003Info.cs Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/HSPGui/DeviceDescriptions/MAX30101Info.cs Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/HSPGui/DeviceDescriptions/MAX30205Info.cs Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/HSPGui/DeviceDescriptions/RegisterBitDescriptions.cs Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/HSPGui/DeviceDescriptions/RegisterInfo.cs Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/HSPGui/ECGChannel.cs Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/HSPGui/ECGInputMux.cs Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/HSPGui/FirFilter.cs Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/HSPGui/Form1.Designer.cs Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/HSPGui/Form1.cs Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/HSPGui/Form1.resx Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/HSPGui/FormConnection.Designer.cs Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/HSPGui/FormConnection.cs Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/HSPGui/FormConnection.resx Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/HSPGui/HID.cs Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/HSPGui/HSPGui.csproj Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/HSPGui/IRegisterFieldView.cs Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/HSPGui/MI_icon.ico Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/HSPGui/MaximColor.cs Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/HSPGui/MaximStyle.dll Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/HSPGui/MedicalChartHelper.cs Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/HSPGui/Model/ACLeadOff.cs Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/HSPGui/Model/BioZEventArgs.cs Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/HSPGui/Model/DCLeadOff.cs Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/HSPGui/Model/DataLogModel.cs Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/HSPGui/Model/EcgEventArgs.cs Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/HSPGui/Model/FifoStruct.cs Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/HSPGui/Model/IDataLogModel.cs Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/HSPGui/Model/ITemperatureModel.cs Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/HSPGui/Model/MAX30001.cs Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/HSPGui/Model/MAX30205Model.cs Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/HSPGui/Model/PaceData.cs Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/HSPGui/Model/PaceEventArgs.cs Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/HSPGui/Model/RToREventArgs.cs Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/HSPGui/NimitzHID.cs Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/HSPGui/PaceChannel.cs Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/HSPGui/PartialArrayIntAvailableEventArgs.cs Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/HSPGui/Presenter/DataLogPresenter.cs Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/HSPGui/Presenter/EcgDelay.cs Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/HSPGui/Presenter/OpticalAlgorithmPresenter.cs Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/HSPGui/Presenter/OpticalFileLogPresenter.cs Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/HSPGui/Presenter/RToRCalculator.cs Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/HSPGui/Presenter/RawFileLogPresenter.cs Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/HSPGui/Presenter/RegisterExportPresenter.cs Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/HSPGui/Presenter/StreamPresenter.cs Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/HSPGui/Presenter/TemperaturePresenter.cs Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/HSPGui/Program.cs Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/HSPGui/Properties/AssemblyInfo.cs Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/HSPGui/Properties/Resources.Designer.cs Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/HSPGui/Properties/Resources.resx Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/HSPGui/Properties/Settings.Designer.cs Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/HSPGui/RegisterField.cs Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/HSPGui/Resources/bio-impedance_block.png Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/HSPGui/Resources/bioz_input_mux.png Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/HSPGui/Resources/bioz_input_mux1.png Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/HSPGui/Resources/bioz_input_muxcal1.png Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/HSPGui/Resources/bioz_input_muxcal2.png Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/HSPGui/Resources/bioz_input_muxlb1.png Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/HSPGui/Resources/bioz_input_muxlb2.png Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/HSPGui/Resources/bioz_input_muxloff1.png Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/HSPGui/Resources/bioz_input_muxloff2.png Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/HSPGui/Resources/bioz_input_muxlon.png Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/HSPGui/Resources/bioz_input_muxsw1.png Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/HSPGui/Resources/bioz_input_muxsw2.png Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/HSPGui/Resources/bioz_load.png Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/HSPGui/Resources/bioz_loadOLD.png Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/HSPGui/Resources/bioz_load_cal1.png Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/HSPGui/Resources/bioz_load_cal2.png Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/HSPGui/Resources/bioz_load_lb1.png Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/HSPGui/Resources/bioz_load_lb2.png Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/HSPGui/Resources/bioz_load_leadon.png Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/HSPGui/Resources/bioz_load_resload.png Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/HSPGui/Resources/bioz_load_sw1.png Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/HSPGui/Resources/bioz_load_sw2.png Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/HSPGui/Resources/bioz_loadloff1.png Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/HSPGui/Resources/bioz_loadloff2.png Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/HSPGui/Resources/bioz_loadrz.png Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/HSPGui/Resources/ecg_channel_block.png Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/HSPGui/Resources/ecg_lead_config.png Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/HSPGui/Resources/ecg_lead_config1.png Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/HSPGui/Resources/ecg_lead_config_closed_swOnly.png Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/HSPGui/Resources/open.png Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/HSPGui/Resources/pace_block_diagrams.png Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/HSPGui/Resources/pace_falling.png Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/HSPGui/Resources/pace_rising.png Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/HSPGui/Resources/sw1.png Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/HSPGui/Resources/sw10.png Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/HSPGui/Resources/sw11.png Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/HSPGui/Resources/sw12.png Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/HSPGui/Resources/sw13.png Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/HSPGui/Resources/sw14.png Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/HSPGui/Resources/sw1bmp.bmp Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/HSPGui/Resources/sw1rz.png Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/HSPGui/Resources/sw2.png Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/HSPGui/Resources/sw3.png Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/HSPGui/Resources/sw4.png Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/HSPGui/Resources/sw5.png Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/HSPGui/Resources/sw6.png Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/HSPGui/Resources/sw7.png Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/HSPGui/Resources/sw8.png Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/HSPGui/Resources/sw9.png Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/HSPGui/Resources/system_block_diagram.png Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/HSPGui/Resources/system_block_diagram_max30003.png Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/HSPGui/RpcClientExample.csproj Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/HSPGui/SKA.dll Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/HSPGui/SimpleHID.sln Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/HSPGui/SimpleHID.suo Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/HSPGui/SplashScreen.Designer.cs Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/HSPGui/SplashScreen.cs Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/HSPGui/SplashScreen.resx Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/HSPGui/Streaming.cs Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/HSPGui/StreamingParameters.cs Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/HSPGui/Temperature/TemperatureValue.cs Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/HSPGui/View/CompleteEventArgs.cs Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/HSPGui/View/DataFormatEventArgs.cs Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/HSPGui/View/EnableEventArgs.cs Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/HSPGui/View/FileLogView/FileLogHeader.cs Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/HSPGui/View/FileLogView/IRawFileLogView.cs Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/HSPGui/View/FileLogView/RawFileLogView.cs Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/HSPGui/View/IFormView.cs Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/HSPGui/View/IHspSetting.cs Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/HSPGui/View/IOpticalAlgorithmView.cs Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/HSPGui/View/IRegisterExportView.cs Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/HSPGui/View/RegisterExportForm.Designer.cs Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/HSPGui/View/RegisterExportForm.cs Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/HSPGui/View/RegisterExportForm.resx Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/HSPGui/View/StatusForm.Designer.cs Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/HSPGui/View/StatusForm.cs Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/HSPGui/View/StatusForm.resx Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/HSPGui/app.config Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/RPCSupportTest/ComPort.cs Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/RPCSupportTest/I2cTest.cs Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/RPCSupportTest/MAX30001Test.cs Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/RPCSupportTest/MAX30003Test.cs Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/RPCSupportTest/MAX30101Test.cs Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/RPCSupportTest/MAX30205Test.cs Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/RPCSupportTest/Properties/AssemblyInfo.cs Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/RPCSupportTest/RPCSupportTest.csproj Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/RPCSupportTest/StreamHelper.cs Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/RPCSupportTest/packages.config Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/Script/hsp_intassignment.py Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/Script/hsp_mission.py Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/Script/hsp_registerread.py Show annotated file Show diff for this revision Revisions of this file
HspGuiSourceV301/Script/hsp_streamstartstop.py Show annotated file Show diff for this revision Revisions of this file
MAX30205.lib Show annotated file Show diff for this revision Revisions of this file
e4a10ed6eb92/.gitignore Show annotated file Show diff for this revision Revisions of this file
e4a10ed6eb92/.hg_archival.txt Show annotated file Show diff for this revision Revisions of this file
e4a10ed6eb92/HSP/Devices/BMP280/BMP280/BMP280.cpp Show annotated file Show diff for this revision Revisions of this file
e4a10ed6eb92/HSP/Devices/BMP280/BMP280/BMP280.h Show annotated file Show diff for this revision Revisions of this file
e4a10ed6eb92/HSP/Devices/BMP280/BMP280_RPC.cpp Show annotated file Show diff for this revision Revisions of this file
e4a10ed6eb92/HSP/Devices/BMP280/BMP280_RPC.h Show annotated file Show diff for this revision Revisions of this file
e4a10ed6eb92/HSP/Devices/HspLed/HspLed/HspLed.cpp Show annotated file Show diff for this revision Revisions of this file
e4a10ed6eb92/HSP/Devices/HspLed/HspLed/HspLed.h Show annotated file Show diff for this revision Revisions of this file
e4a10ed6eb92/HSP/Devices/HspLed/HspLed_RPC.cpp Show annotated file Show diff for this revision Revisions of this file
e4a10ed6eb92/HSP/Devices/HspLed/HspLed_RPC.h Show annotated file Show diff for this revision Revisions of this file
e4a10ed6eb92/HSP/Devices/LIS2DH/LIS2DH/LIS2DH.cpp Show annotated file Show diff for this revision Revisions of this file
e4a10ed6eb92/HSP/Devices/LIS2DH/LIS2DH/LIS2DH.h Show annotated file Show diff for this revision Revisions of this file
e4a10ed6eb92/HSP/Devices/LIS2DH/LIS2DH_RPC.cpp Show annotated file Show diff for this revision Revisions of this file
e4a10ed6eb92/HSP/Devices/LIS2DH/LIS2DH_RPC.h Show annotated file Show diff for this revision Revisions of this file
e4a10ed6eb92/HSP/Devices/MAX30001/MAX30001/MAX30001.cpp Show annotated file Show diff for this revision Revisions of this file
e4a10ed6eb92/HSP/Devices/MAX30001/MAX30001/MAX30001.h Show annotated file Show diff for this revision Revisions of this file
e4a10ed6eb92/HSP/Devices/MAX30001/MAX30001_RPC.cpp Show annotated file Show diff for this revision Revisions of this file
e4a10ed6eb92/HSP/Devices/MAX30001/MAX30001_RPC.h Show annotated file Show diff for this revision Revisions of this file
e4a10ed6eb92/HSP/Devices/MAX30001/MAX30001_helper.cpp Show annotated file Show diff for this revision Revisions of this file
e4a10ed6eb92/HSP/Devices/MAX30001/MAX30001_helper.h Show annotated file Show diff for this revision Revisions of this file
e4a10ed6eb92/HSP/Devices/MAX30101/MAX30101/MAX30101.cpp Show annotated file Show diff for this revision Revisions of this file
e4a10ed6eb92/HSP/Devices/MAX30101/MAX30101/MAX30101.h Show annotated file Show diff for this revision Revisions of this file
e4a10ed6eb92/HSP/Devices/MAX30101/MAX30101_RPC.cpp Show annotated file Show diff for this revision Revisions of this file
e4a10ed6eb92/HSP/Devices/MAX30101/MAX30101_RPC.h Show annotated file Show diff for this revision Revisions of this file
e4a10ed6eb92/HSP/Devices/MAX30101/MAX30101_helper.cpp Show annotated file Show diff for this revision Revisions of this file
e4a10ed6eb92/HSP/Devices/MAX30101/MAX30101_helper.h Show annotated file Show diff for this revision Revisions of this file
e4a10ed6eb92/HSP/Devices/PushButton/PushButton.cpp Show annotated file Show diff for this revision Revisions of this file
e4a10ed6eb92/HSP/Devices/PushButton/PushButton.h Show annotated file Show diff for this revision Revisions of this file
e4a10ed6eb92/HSP/Devices/S25FS256/S25FS512.cpp Show annotated file Show diff for this revision Revisions of this file
e4a10ed6eb92/HSP/Devices/S25FS256/S25FS512.h Show annotated file Show diff for this revision Revisions of this file
e4a10ed6eb92/HSP/Devices/S25FS256/S25FS512_RPC.cpp Show annotated file Show diff for this revision Revisions of this file
e4a10ed6eb92/HSP/Devices/S25FS256/S25FS512_RPC.h Show annotated file Show diff for this revision Revisions of this file
e4a10ed6eb92/HSP/Hsp_BLE/BluetoothLE/BluetoothLE.cpp Show annotated file Show diff for this revision Revisions of this file
e4a10ed6eb92/HSP/Hsp_BLE/BluetoothLE/BluetoothLE.h Show annotated file Show diff for this revision Revisions of this file
e4a10ed6eb92/HSP/Hsp_BLE/BluetoothLE/Characteristic.cpp Show annotated file Show diff for this revision Revisions of this file
e4a10ed6eb92/HSP/Hsp_BLE/BluetoothLE/Characteristic.h Show annotated file Show diff for this revision Revisions of this file
e4a10ed6eb92/HSP/Hsp_BLE/HspBLE.cpp Show annotated file Show diff for this revision Revisions of this file
e4a10ed6eb92/HSP/Hsp_BLE/HspBLE.h Show annotated file Show diff for this revision Revisions of this file
e4a10ed6eb92/HSP/Interfaces/I2C_RPC.cpp Show annotated file Show diff for this revision Revisions of this file
e4a10ed6eb92/HSP/Interfaces/I2C_RPC.h Show annotated file Show diff for this revision Revisions of this file
e4a10ed6eb92/HSP/Interfaces/QuadSpiInterface.cpp Show annotated file Show diff for this revision Revisions of this file
e4a10ed6eb92/HSP/Interfaces/QuadSpiInterface.h Show annotated file Show diff for this revision Revisions of this file
e4a10ed6eb92/HSP/LoggingService/DataLoggingService.cpp Show annotated file Show diff for this revision Revisions of this file
e4a10ed6eb92/HSP/LoggingService/DataLoggingService.h Show annotated file Show diff for this revision Revisions of this file
e4a10ed6eb92/HSP/LoggingService/Device_Logging.cpp Show annotated file Show diff for this revision Revisions of this file
e4a10ed6eb92/HSP/LoggingService/Device_Logging.h Show annotated file Show diff for this revision Revisions of this file
e4a10ed6eb92/HSP/LoggingService/Logging.cpp Show annotated file Show diff for this revision Revisions of this file
e4a10ed6eb92/HSP/LoggingService/Logging.h Show annotated file Show diff for this revision Revisions of this file
e4a10ed6eb92/HSP/LoggingService/Logging_RPC.cpp Show annotated file Show diff for this revision Revisions of this file
e4a10ed6eb92/HSP/LoggingService/Logging_RPC.h Show annotated file Show diff for this revision Revisions of this file
e4a10ed6eb92/HSP/LoggingService/ServiceNonInterrupt.cpp Show annotated file Show diff for this revision Revisions of this file
e4a10ed6eb92/HSP/LoggingService/ServiceNonInterrupt.h Show annotated file Show diff for this revision Revisions of this file
e4a10ed6eb92/HSP/QuadSPI/QuadSpi.cpp Show annotated file Show diff for this revision Revisions of this file
e4a10ed6eb92/HSP/QuadSPI/QuadSpi.h Show annotated file Show diff for this revision Revisions of this file
e4a10ed6eb92/HSP/RpcServer/PacketFifo.cpp Show annotated file Show diff for this revision Revisions of this file
e4a10ed6eb92/HSP/RpcServer/PacketFifo.h Show annotated file Show diff for this revision Revisions of this file
e4a10ed6eb92/HSP/RpcServer/RpcDeclarations.h Show annotated file Show diff for this revision Revisions of this file
e4a10ed6eb92/HSP/RpcServer/RpcFifo.cpp Show annotated file Show diff for this revision Revisions of this file
e4a10ed6eb92/HSP/RpcServer/RpcFifo.h Show annotated file Show diff for this revision Revisions of this file
e4a10ed6eb92/HSP/RpcServer/RpcServer.cpp Show annotated file Show diff for this revision Revisions of this file
e4a10ed6eb92/HSP/RpcServer/RpcServer.h Show annotated file Show diff for this revision Revisions of this file
e4a10ed6eb92/HSP/RpcServer/Streaming.cpp Show annotated file Show diff for this revision Revisions of this file
e4a10ed6eb92/HSP/RpcServer/Streaming.h Show annotated file Show diff for this revision Revisions of this file
e4a10ed6eb92/HSP/RpcServer/StringHelper.cpp Show annotated file Show diff for this revision Revisions of this file
e4a10ed6eb92/HSP/RpcServer/StringHelper.h Show annotated file Show diff for this revision Revisions of this file
e4a10ed6eb92/HSP/RpcServer/StringInOut.cpp Show annotated file Show diff for this revision Revisions of this file
e4a10ed6eb92/HSP/RpcServer/StringInOut.h Show annotated file Show diff for this revision Revisions of this file
e4a10ed6eb92/HSP/System/Peripherals.cpp Show annotated file Show diff for this revision Revisions of this file
e4a10ed6eb92/HSP/System/Peripherals.h Show annotated file Show diff for this revision Revisions of this file
e4a10ed6eb92/HSP/System/System.cpp Show annotated file Show diff for this revision Revisions of this file
e4a10ed6eb92/HSP/System/System.h Show annotated file Show diff for this revision Revisions of this file
e4a10ed6eb92/HSP/Test/Test_BMP280.cpp Show annotated file Show diff for this revision Revisions of this file
e4a10ed6eb92/HSP/Test/Test_BMP280.h Show annotated file Show diff for this revision Revisions of this file
e4a10ed6eb92/HSP/Test/Test_LIS2DH.cpp Show annotated file Show diff for this revision Revisions of this file
e4a10ed6eb92/HSP/Test/Test_LIS2DH.h Show annotated file Show diff for this revision Revisions of this file
e4a10ed6eb92/HSP/Test/Test_MAX30001.cpp Show annotated file Show diff for this revision Revisions of this file
e4a10ed6eb92/HSP/Test/Test_MAX30001.h Show annotated file Show diff for this revision Revisions of this file
e4a10ed6eb92/HSP/Test/Test_MAX30101.cpp Show annotated file Show diff for this revision Revisions of this file
e4a10ed6eb92/HSP/Test/Test_MAX30101.h Show annotated file Show diff for this revision Revisions of this file
e4a10ed6eb92/HSP/Test/Test_MAX30205.cpp Show annotated file Show diff for this revision Revisions of this file
e4a10ed6eb92/HSP/Test/Test_MAX30205.h Show annotated file Show diff for this revision Revisions of this file
e4a10ed6eb92/HSP/Test/Test_S25FS512.cpp Show annotated file Show diff for this revision Revisions of this file
e4a10ed6eb92/HSP/Test/Test_S25FS512.h Show annotated file Show diff for this revision Revisions of this file
e4a10ed6eb92/HSP/Test/Test_Utilities.cpp Show annotated file Show diff for this revision Revisions of this file
e4a10ed6eb92/HSP/Test/Test_Utilities.h Show annotated file Show diff for this revision Revisions of this file
e4a10ed6eb92/HSP/Test/Testing_RPC.cpp Show annotated file Show diff for this revision Revisions of this file
e4a10ed6eb92/HSP/Test/Testing_RPC.h Show annotated file Show diff for this revision Revisions of this file
e4a10ed6eb92/HSP/main.cpp Show annotated file Show diff for this revision Revisions of this file
e4a10ed6eb92/USBDevice.lib Show annotated file Show diff for this revision Revisions of this file
e4a10ed6eb92/mbed-os.lib Show annotated file Show diff for this revision Revisions of this file
src/main/AndroidManifest.xml Show annotated file Show diff for this revision Revisions of this file
src/main/java/com/example/android/bluetoothlegatt/BluetoothLeService.java Show annotated file Show diff for this revision Revisions of this file
src/main/java/com/example/android/bluetoothlegatt/DeviceScanActivity.java Show annotated file Show diff for this revision Revisions of this file
src/main/java/com/example/android/bluetoothlegatt/GattAttributeLookupTable.java Show annotated file Show diff for this revision Revisions of this file
src/main/java/com/example/android/bluetoothlegatt/SensorActivity.java Show annotated file Show diff for this revision Revisions of this file
src/main/java/graphing/LineGraphing.java Show annotated file Show diff for this revision Revisions of this file
src/main/java/graphing/LinePoint.java Show annotated file Show diff for this revision Revisions of this file
src/main/java/graphing/LinePointCollection.java Show annotated file Show diff for this revision Revisions of this file
src/main/res/drawable-hdpi/accelerometer.png Show annotated file Show diff for this revision Revisions of this file
src/main/res/drawable-hdpi/accelerometer2.png Show annotated file Show diff for this revision Revisions of this file
src/main/res/drawable-hdpi/heart.png Show annotated file Show diff for this revision Revisions of this file
src/main/res/drawable-hdpi/ic_action_share.png Show annotated file Show diff for this revision Revisions of this file
src/main/res/drawable-hdpi/ic_bluetooth.png Show annotated file Show diff for this revision Revisions of this file
src/main/res/drawable-hdpi/ic_bluetooth_on.png Show annotated file Show diff for this revision Revisions of this file
src/main/res/drawable-hdpi/ic_device_ibeacon.png Show annotated file Show diff for this revision Revisions of this file
src/main/res/drawable-hdpi/ic_launcher.png Show annotated file Show diff for this revision Revisions of this file
src/main/res/drawable-hdpi/ic_settings_black_24dp.png Show annotated file Show diff for this revision Revisions of this file
src/main/res/drawable-hdpi/popup_blue.9.png Show annotated file Show diff for this revision Revisions of this file
src/main/res/drawable-hdpi/popup_green.9.png Show annotated file Show diff for this revision Revisions of this file
src/main/res/drawable-hdpi/popup_red.9.png Show annotated file Show diff for this revision Revisions of this file
src/main/res/drawable-hdpi/pressure.png Show annotated file Show diff for this revision Revisions of this file
src/main/res/drawable-hdpi/sliderscreen_max30001.png Show annotated file Show diff for this revision Revisions of this file
src/main/res/drawable-hdpi/sliderscreen_max30101.png Show annotated file Show diff for this revision Revisions of this file
src/main/res/drawable-hdpi/sliderscreen_max32620.png Show annotated file Show diff for this revision Revisions of this file
src/main/res/drawable-hdpi/sliderscreen_sensors.png Show annotated file Show diff for this revision Revisions of this file
src/main/res/drawable-hdpi/temperature.png Show annotated file Show diff for this revision Revisions of this file
src/main/res/drawable-hdpi/tile.9.png Show annotated file Show diff for this revision Revisions of this file
src/main/res/drawable-mdpi/ic_launcher.png Show annotated file Show diff for this revision Revisions of this file
src/main/res/drawable-xhdpi/ic_launcher.png Show annotated file Show diff for this revision Revisions of this file
src/main/res/drawable-xxhdpi/ic_launcher.png Show annotated file Show diff for this revision Revisions of this file
src/main/res/drawable-xxxhdpi/ic_launcher.png Show annotated file Show diff for this revision Revisions of this file
src/main/res/layout/actionbar_indeterminate_progress.xml Show annotated file Show diff for this revision Revisions of this file
src/main/res/layout/activity_sensor.xml Show annotated file Show diff for this revision Revisions of this file
src/main/res/layout/gatt_services_characteristics.xml Show annotated file Show diff for this revision Revisions of this file
src/main/res/layout/listitem_device.xml Show annotated file Show diff for this revision Revisions of this file
src/main/res/menu/gatt_services.xml Show annotated file Show diff for this revision Revisions of this file
src/main/res/menu/main.xml Show annotated file Show diff for this revision Revisions of this file
src/main/res/mipmap-hdpi/ic_launcher.png Show annotated file Show diff for this revision Revisions of this file
src/main/res/mipmap-mdpi/ic_launcher.png Show annotated file Show diff for this revision Revisions of this file
src/main/res/mipmap-xhdpi/ic_launcher.png Show annotated file Show diff for this revision Revisions of this file
src/main/res/mipmap-xxhdpi/ic_launcher.png Show annotated file Show diff for this revision Revisions of this file
src/main/res/mipmap-xxxhdpi/ic_launcher.png Show annotated file Show diff for this revision Revisions of this file
src/main/res/values-v21/styles.xml Show annotated file Show diff for this revision Revisions of this file
src/main/res/values-w820dp/dimens.xml Show annotated file Show diff for this revision Revisions of this file
src/main/res/values/colors.xml Show annotated file Show diff for this revision Revisions of this file
src/main/res/values/dimens.xml Show annotated file Show diff for this revision Revisions of this file
src/main/res/values/strings.xml Show annotated file Show diff for this revision Revisions of this file
src/main/res/values/styles.xml Show annotated file Show diff for this revision Revisions of this file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HspGuiSourceV301/EcgViewTest/EcgTest.cs	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,198 @@
+/*******************************************************************************
+* Copyright (C) 2016 Maxim Integrated Products, Inc., All rights Reserved.
+* 
+* This software is protected by copyright laws of the United States and
+* of foreign countries. This material may also be protected by patent laws
+* and technology transfer regulations of the United States and of foreign
+* countries. This software is furnished under a license agreement and/or a
+* nondisclosure agreement and may only be used or reproduced in accordance
+* with the terms of those agreements. Dissemination of this information to
+* any party or parties not specified in the license agreement and/or
+* nondisclosure agreement is expressly prohibited.
+*
+* The above copyright notice and this permission notice shall be included
+* in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+* OTHER DEALINGS IN THE SOFTWARE.
+*
+* Except as contained in this notice, the name of Maxim Integrated
+* Products, Inc. shall not be used except as stated in the Maxim Integrated
+* Products, Inc. Branding Policy.
+*
+* The mere transfer of this software does not imply any licenses
+* of trade secrets, proprietary technology, copyrights, patents,
+* trademarks, maskwork rights, or any other form of intellectual
+* property whatsoever. Maxim Integrated Products, Inc. retains all
+* ownership rights.
+*******************************************************************************
+*/
+
+using System;
+using NUnit.Framework;
+using HealthSensorPlatform.CustomControls;
+using RPCSupport.Streaming;
+using System.Windows.Forms;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+using HealthSensorPlatform.Presenter;
+
+namespace EcgViewTest
+{
+    [TestFixture]
+    public partial class EcgTest
+    {
+        /*
+        [Test]
+        public void CalculationTest()
+        {
+            double[] result;
+
+            Form form = new Form();
+            EcgView ecgView = new EcgView();
+            int[] ecgData = new int[] { 0, 1000 << 6, 226759, 159111, 8388544, 8388608};
+
+            form.Controls.Add(ecgView);
+            result = ecgView.UpdateChart(EcgView.StreamDataType.Ecg, ecgData);
+
+            // millivolts
+            Assert.AreEqual(0, result[0], 1e-3);
+            Assert.AreEqual(0.38147, result[1], 1e-3);
+            Assert.AreEqual(1.351547, result[2], 1e-3);
+            Assert.AreEqual(0.948334, result[3], 1e-2);
+            Assert.AreEqual(49.99962, result[4], 1e-2);
+            Assert.AreEqual(-50, result[5], 1e-2);
+        }
+
+        [Test]
+        public void CalculationTest1()
+        {
+            double[] result;
+
+            Form form = new Form();
+            EcgView ecgView = new EcgView();
+            int[] ecgData = new int[] { 226759, 159111, 8388544, 8388608 };
+
+            form.Controls.Add(ecgView);
+            result = ecgView.UpdateChart(EcgView.StreamDataType.Ecg, ecgData);
+
+            // milliovolts
+            Assert.AreEqual(1.351547, result[0], 1e-3);
+
+        }
+        */
+
+        [Test]
+        public void EcgCalculationTest()
+        {
+            EcgView ecgView = new EcgView();
+            StreamPresenter sp = new StreamPresenter(ecgView);
+            double[] result;
+            int[] ecgData = new int[] { 0 | 7, 1000 << 6 | 7, 226759, 159119 | 7, 8388547 | 7, 8388607 | 7 };
+
+            result = sp.ProcessEcg(ecgData);
+
+            // millivolts
+            Assert.AreEqual(0, result[0], 1e-3);
+            Assert.AreEqual(ecgEquation(ecgData[1] >> 6), result[1], 1e-3);
+            Assert.AreEqual(ecgEquation(ecgData[2] >> 6), result[2], 1e-3);
+            Assert.AreEqual(ecgEquation(ecgData[3] >> 6), result[3], 1e-2);
+            Assert.AreEqual(ecgEquation(ecgData[4] >> 6), result[4], 1e-2);
+            Assert.AreEqual(ecgEquation(ecgData[5] >> 6), result[5], 1e-2);
+        }
+
+        double ecgEquation(double data)
+        {
+            return 1000 * 7.62939453125e-6 * data / 20;
+        }
+
+        /*
+
+        [TestCase(0x80, 60)]
+        [TestCase(0xff, 30.118)]
+        [TestCase(0x01, 7680)]
+        [TestCase(0xaa, 45.176)]
+        public void RToRCalculationTest(int rToR, double bpm)
+        {
+            double result;
+
+            EcgView ecgView = new EcgView();
+            InitArgs.EcgInitStart ecgInit = new InitArgs.EcgInitStart();
+
+            ecgView.ecgArgs = ecgInit;
+
+            result = ecgView.RToRBeatsPerMinute(rToR);
+
+            Assert.AreEqual(bpm, result, 1e-2);
+        }
+
+        [TestCase(0x80, 58.594)]
+        [TestCase(0xff, 29.412)]
+        [TestCase(0x01, 7500)]
+        [TestCase(0xaa, 44.1176)]
+        public void RToRCalculationTest1(int rToR, double bpm)
+        {
+            double result;
+
+            EcgView ecgView = new EcgView();
+            InitArgs.EcgInitStart ecgInit = new InitArgs.EcgInitStart();
+
+            ecgView.ecgArgs = ecgInit;
+
+            ecgView.FrequencyMasterField = 1;
+
+            result = ecgView.RToRBeatsPerMinute(rToR);
+
+            Assert.AreEqual(bpm, result, 1e-2);
+        }
+
+        [TestCase(0x80, 58.594)]
+        [TestCase(0xff, 29.412)]
+        [TestCase(0x01, 7500)]
+        [TestCase(0xaa, 44.1176)]
+        public void RToRCalculationTest2(int rToR, double bpm)
+        {
+            double result;
+
+            EcgView ecgView = new EcgView();
+            InitArgs.EcgInitStart ecgInit = new InitArgs.EcgInitStart();
+
+            ecgView.ecgArgs = ecgInit;
+
+            ecgView.FrequencyMasterField = 2;
+
+            result = ecgView.RToRBeatsPerMinute(rToR);
+
+            Assert.AreEqual(bpm, result, 1e-2);
+        }
+
+        [TestCase(0x80, 58.535)]
+        [TestCase(0xff, 29.382)]
+        [TestCase(0x01, 7492.5)]
+        [TestCase(0xaa, 44.0735)]
+        public void RToRCalculationTest3(int rToR, double bpm)
+        {
+            double result;
+
+            EcgView ecgView = new EcgView();
+            InitArgs.EcgInitStart ecgInit = new InitArgs.EcgInitStart();
+
+            ecgView.ecgArgs = ecgInit;
+
+            ecgView.FrequencyMasterField = 3;
+
+            result = ecgView.RToRBeatsPerMinute(rToR);
+
+            Assert.AreEqual(bpm, result, 1e-2);
+        }
+        */
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HspGuiSourceV301/EcgViewTest/EcgViewTest.csproj	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,109 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <PropertyGroup>
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+    <ProjectGuid>{99AD6A39-F828-4C0B-A03F-C34C42083075}</ProjectGuid>
+    <OutputType>Library</OutputType>
+    <AppDesignerFolder>Properties</AppDesignerFolder>
+    <RootNamespace>EcgViewTest</RootNamespace>
+    <AssemblyName>EcgViewTest</AssemblyName>
+    <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
+    <FileAlignment>512</FileAlignment>
+    <ProjectTypeGuids>{3AC096D0-A1C2-E12C-1390-A8335801FDAB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
+    <VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">10.0</VisualStudioVersion>
+    <VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
+    <ReferencePath>$(ProgramFiles)\Common Files\microsoft shared\VSTT\$(VisualStudioVersion)\UITestExtensionPackages</ReferencePath>
+    <IsCodedUITest>False</IsCodedUITest>
+    <TestProjectType>UnitTest</TestProjectType>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+    <DebugSymbols>true</DebugSymbols>
+    <DebugType>full</DebugType>
+    <Optimize>false</Optimize>
+    <OutputPath>bin\Debug\</OutputPath>
+    <DefineConstants>DEBUG;TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+    <PlatformTarget>x86</PlatformTarget>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+    <DebugType>pdbonly</DebugType>
+    <Optimize>true</Optimize>
+    <OutputPath>bin\Release\</OutputPath>
+    <DefineConstants>TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+  </PropertyGroup>
+  <ItemGroup>
+    <Reference Include="nunit.framework, Version=2.6.4.14350, Culture=neutral, PublicKeyToken=96d09a1eb7f44a77, processorArchitecture=MSIL">
+      <SpecificVersion>False</SpecificVersion>
+      <HintPath>..\packages\NUnit.2.6.4\lib\nunit.framework.dll</HintPath>
+    </Reference>
+    <Reference Include="System" />
+    <Reference Include="System.Windows.Forms" />
+    <Reference Include="System.Windows.Forms.DataVisualization" />
+  </ItemGroup>
+  <Choose>
+    <When Condition="('$(VisualStudioVersion)' == '10.0' or '$(VisualStudioVersion)' == '') and '$(TargetFrameworkVersion)' == 'v3.5'">
+      <ItemGroup>
+        <Reference Include="Microsoft.VisualStudio.QualityTools.UnitTestFramework, Version=10.1.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL" />
+      </ItemGroup>
+    </When>
+    <Otherwise>
+      <ItemGroup>
+        <Reference Include="Microsoft.VisualStudio.QualityTools.UnitTestFramework" />
+      </ItemGroup>
+    </Otherwise>
+  </Choose>
+  <ItemGroup>
+    <Compile Include="EcgTest.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="PaceTest.cs" />
+    <Compile Include="Properties\AssemblyInfo.cs" />
+    <Compile Include="RToRCalculatorTest.cs" />
+    <Compile Include="RToRTest.cs" />
+    <Compile Include="TemperatureTest.cs" />
+  </ItemGroup>
+  <ItemGroup>
+    <ProjectReference Include="..\GuiDLLs\RPCSupport\RPCSupport.csproj">
+      <Project>{170a27f5-0680-485d-8b90-ea736719016e}</Project>
+      <Name>RPCSupport</Name>
+    </ProjectReference>
+    <ProjectReference Include="..\HSPGui\HSPGui.csproj">
+      <Project>{cef8731e-362f-407c-86a7-f65ace2a1acb}</Project>
+      <Name>HSPGui</Name>
+    </ProjectReference>
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="packages.config" />
+  </ItemGroup>
+  <Choose>
+    <When Condition="'$(VisualStudioVersion)' == '10.0' And '$(IsCodedUITest)' == 'True'">
+      <ItemGroup>
+        <Reference Include="Microsoft.VisualStudio.QualityTools.CodedUITestFramework, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
+          <Private>False</Private>
+        </Reference>
+        <Reference Include="Microsoft.VisualStudio.TestTools.UITest.Common, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
+          <Private>False</Private>
+        </Reference>
+        <Reference Include="Microsoft.VisualStudio.TestTools.UITest.Extension, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
+          <Private>False</Private>
+        </Reference>
+        <Reference Include="Microsoft.VisualStudio.TestTools.UITesting, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
+          <Private>False</Private>
+        </Reference>
+      </ItemGroup>
+    </When>
+  </Choose>
+  <Import Project="$(VSToolsPath)\TeamTest\Microsoft.TestTools.targets" Condition="Exists('$(VSToolsPath)\TeamTest\Microsoft.TestTools.targets')" />
+  <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+  <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 
+       Other similar extension points exist, see Microsoft.Common.targets.
+  <Target Name="BeforeBuild">
+  </Target>
+  <Target Name="AfterBuild">
+  </Target>
+  -->
+</Project>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HspGuiSourceV301/EcgViewTest/PaceTest.cs	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,370 @@
+/*******************************************************************************
+* Copyright (C) 2016 Maxim Integrated Products, Inc., All rights Reserved.
+* 
+* This software is protected by copyright laws of the United States and
+* of foreign countries. This material may also be protected by patent laws
+* and technology transfer regulations of the United States and of foreign
+* countries. This software is furnished under a license agreement and/or a
+* nondisclosure agreement and may only be used or reproduced in accordance
+* with the terms of those agreements. Dissemination of this information to
+* any party or parties not specified in the license agreement and/or
+* nondisclosure agreement is expressly prohibited.
+*
+* The above copyright notice and this permission notice shall be included
+* in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+* OTHER DEALINGS IN THE SOFTWARE.
+*
+* Except as contained in this notice, the name of Maxim Integrated
+* Products, Inc. shall not be used except as stated in the Maxim Integrated
+* Products, Inc. Branding Policy.
+*
+* The mere transfer of this software does not imply any licenses
+* of trade secrets, proprietary technology, copyrights, patents,
+* trademarks, maskwork rights, or any other form of intellectual
+* property whatsoever. Maxim Integrated Products, Inc. retains all
+* ownership rights.
+*******************************************************************************
+*/
+
+using System;
+using NUnit.Framework;
+using HealthSensorPlatform.CustomControls;
+using HealthSensorPlatform.Model;
+using RPCSupport.Streaming;
+using System.Windows.Forms;
+
+namespace EcgViewTest
+{
+    [TestFixture]
+    public partial class EcgTest
+    {
+        /*
+        [Test]
+        public void PaceDataTag0()
+        {
+            Form form = new Form();
+            EcgView ecgView = new EcgView();
+            PaceData result;
+            PartialArrayIntAvailableEventArgs args = new PartialArrayIntAvailableEventArgs();
+            PartialArrayIntAvailableEventArgs ecgArgs = new PartialArrayIntAvailableEventArgs();
+
+            ecgArgs = new PartialArrayIntAvailableEventArgs();
+            ecgArgs.reportID = PartialArrayIntAvailableEventArgs.PACKET_MAX30001_ECG;
+            args.sampleNumberOffset = 5;
+            args.array1 = new int[] {
+                7,
+                7,
+                0, // Tag 0 has pace data
+                7,
+                7
+            };
+
+            args.reportID = PartialArrayIntAvailableEventArgs.PACKET_MAX30001_PACE;
+            args.sampleNumberOffset = 18;
+            args.array1 = new int[] {
+                0 << 14 | 0 << 13 | 0 << 12 | 1 << 2 | 1 << 1 | 1, 123456, 123456, 
+                123456, 123456, 123456, 
+                123456, 123456, 123456, 
+                123456, 123456, 123456,
+                123456, 123456, 123456,
+                123456, 123456, 123456
+            };
+
+            form.Controls.Add(ecgView);
+            ecgView.On_AppendChart(this, args);
+            result = ecgView.paceData;
+
+            Assert.AreEqual(-1, result.PaceLength(0));
+        }
+
+        [Test]
+        public void PaceDataTag1()
+        {
+            Form form = new Form();
+            EcgView ecgView = new EcgView();
+            PaceData result;
+            PartialArrayIntAvailableEventArgs args = new PartialArrayIntAvailableEventArgs();
+            PartialArrayIntAvailableEventArgs ecgArgs = new PartialArrayIntAvailableEventArgs();
+
+            ecgArgs = new PartialArrayIntAvailableEventArgs();
+            ecgArgs.reportID = PartialArrayIntAvailableEventArgs.PACKET_MAX30001_ECG;
+            args.sampleNumberOffset = 5;
+            args.array1 = new int[] {
+                7,
+                7,
+                1, // Tag 0 has pace data
+                7,
+                7
+            };
+
+            args.reportID = PartialArrayIntAvailableEventArgs.PACKET_MAX30001_PACE;
+            args.sampleNumberOffset = 18;
+            args.array1 = new int[] {
+                123456, 123456, 123456, 
+                0 << 14 | 0 << 13 | 0 << 12 | 1 << 2 | 1 << 1 | 1, 123456, 123456,
+                123456, 123456, 123456, 
+                123456, 123456, 123456,
+                123456, 123456, 123456,
+                123456, 123456, 123456
+            };
+
+            form.Controls.Add(ecgView);
+            ecgView.On_AppendChart(this, args);
+            result = ecgView.paceData;
+
+            Assert.AreEqual(-1, result.PaceLength(1));
+        }
+
+        [Test]
+        public void PaceDataTag2()
+        {
+            Form form = new Form();
+            EcgView ecgView = new EcgView();
+            PaceData result;
+            PartialArrayIntAvailableEventArgs args = new PartialArrayIntAvailableEventArgs();
+            PartialArrayIntAvailableEventArgs ecgArgs = new PartialArrayIntAvailableEventArgs();
+
+            ecgArgs = new PartialArrayIntAvailableEventArgs();
+            ecgArgs.reportID = PartialArrayIntAvailableEventArgs.PACKET_MAX30001_ECG;
+            args.sampleNumberOffset = 5;
+            args.array1 = new int[] {
+                7,
+                7,
+                2, // Tag 0 has pace data
+                7,
+                7
+            };
+
+            args.reportID = PartialArrayIntAvailableEventArgs.PACKET_MAX30001_PACE;
+            args.sampleNumberOffset = 18;
+            args.array1 = new int[] {
+                123456, 123456, 123456, 
+                123456, 123456, 123456, 
+                0 << 14 | 0 << 13 | 0 << 12 | 1 << 2 | 1 << 1 | 1, 123456, 123456,
+                123456, 123456, 123456,
+                123456, 123456, 123456,
+                123456, 123456, 123456
+            };
+
+            form.Controls.Add(ecgView);
+            ecgView.On_AppendChart(this, args);
+            result = ecgView.paceData;
+
+            Assert.AreEqual(-1, result.PaceLength(2));
+        }
+
+        [Test]
+        public void PaceDataTag5()
+        {
+            Form form = new Form();
+            EcgView ecgView = new EcgView();
+            PaceData result;
+            PartialArrayIntAvailableEventArgs args = new PartialArrayIntAvailableEventArgs();
+            PartialArrayIntAvailableEventArgs ecgArgs = new PartialArrayIntAvailableEventArgs();
+
+            ecgArgs = new PartialArrayIntAvailableEventArgs();
+            ecgArgs.reportID = PartialArrayIntAvailableEventArgs.PACKET_MAX30001_ECG;
+            args.sampleNumberOffset = 5;
+            args.array1 = new int[] {
+                7,
+                7,
+                5, // Tag 0 has pace data
+                7,
+                7
+            };
+
+            args.reportID = PartialArrayIntAvailableEventArgs.PACKET_MAX30001_PACE;
+            args.sampleNumberOffset = 18;
+            args.array1 = new int[] {
+                123456, 123456, 123456, 
+                123456, 123456, 123456, 
+                123456, 123456, 123456,
+                123456, 123456, 123456,
+                123456, 123456, 123456,
+                0 << 14 | 0 << 13 | 0 << 12 | 1 << 2 | 1 << 1 | 1, 123456, 123456
+            }; 
+
+            form.Controls.Add(ecgView);
+            ecgView.On_AppendChart(this, args);
+            result = ecgView.paceData;
+
+            Assert.AreEqual(-1, result.PaceLength(5));
+        }
+
+        [Test]
+        public void PaceDataTag5Last()
+        {
+            Form form = new Form();
+            EcgView ecgView = new EcgView();
+            PaceData result;
+            PartialArrayIntAvailableEventArgs args = new PartialArrayIntAvailableEventArgs();
+            PartialArrayIntAvailableEventArgs ecgArgs = new PartialArrayIntAvailableEventArgs();
+
+            ecgArgs = new PartialArrayIntAvailableEventArgs();
+            ecgArgs.reportID = PartialArrayIntAvailableEventArgs.PACKET_MAX30001_ECG;
+            args.sampleNumberOffset = 5;
+            args.array1 = new int[] {
+                7,
+                7,
+                5, // Tag 0 has pace data
+                7,
+                7
+            };
+
+            args.reportID = PartialArrayIntAvailableEventArgs.PACKET_MAX30001_PACE;
+            args.sampleNumberOffset = 18;
+            args.array1 = new int[] {
+                123456, 123456, 123456, 
+                123456, 123456, 123456, 
+                123456, 123456, 123456,
+                123456, 123456, 123456,
+                123456, 123456, 123456,
+                0 << 14 | 0 << 13 | 0 << 12 | 1 << 2 | 1 << 1 | 0, 0, 1 << 2 | 1 << 1 | 1
+            };
+
+            form.Controls.Add(ecgView);
+            ecgView.On_AppendChart(this, args);
+            result = ecgView.paceData;
+
+            Assert.AreEqual(-1, result.PaceLength(5));
+        }
+
+        [Test]
+        public void PaceDataFalling()
+        {
+            Form form = new Form();
+            EcgView ecgView = new EcgView();
+            PaceData result;
+            PartialArrayIntAvailableEventArgs args = new PartialArrayIntAvailableEventArgs();
+            PartialArrayIntAvailableEventArgs ecgArgs = new PartialArrayIntAvailableEventArgs();
+
+            ecgArgs = new PartialArrayIntAvailableEventArgs();
+            ecgArgs.reportID = PartialArrayIntAvailableEventArgs.PACKET_MAX30001_ECG;
+            args.sampleNumberOffset = 5;
+            args.array1 = new int[] {
+                7,
+                7,
+                0, // Tag 0 has pace data
+                7,
+                7
+            };
+
+            args.reportID = PartialArrayIntAvailableEventArgs.PACKET_MAX30001_PACE;
+            args.sampleNumberOffset = 18;
+            args.array1 = new int[] {
+                0 << 14 | 0 << 13 | 0 << 12 | 1 << 2 | 0 << 1 | 1, 123456, 123456, 
+                123456, 123456, 123456, 
+                123456, 123456, 123456, 
+                123456, 123456, 123456,
+                123456, 123456, 123456,
+                123456, 123456, 123456
+            };
+
+
+            form.Controls.Add(ecgView);
+            ecgView.On_AppendChart(this, args);
+            result = ecgView.paceData;
+
+            Assert.AreEqual(-1, result.PaceLength(0));
+        }
+
+        [Test]
+        public void PaceDataRising()
+        {
+            Form form = new Form();
+            EcgView ecgView = new EcgView();
+            PaceData result;
+            PartialArrayIntAvailableEventArgs args = new PartialArrayIntAvailableEventArgs();
+            PartialArrayIntAvailableEventArgs ecgArgs = new PartialArrayIntAvailableEventArgs();
+
+            ecgArgs = new PartialArrayIntAvailableEventArgs();
+            ecgArgs.reportID = PartialArrayIntAvailableEventArgs.PACKET_MAX30001_ECG;
+            args.sampleNumberOffset = 5;
+            args.array1 = new int[] {
+                7,
+                7,
+                0, // Tag 0 has pace data
+                7,
+                7
+            };
+
+            args.reportID = PartialArrayIntAvailableEventArgs.PACKET_MAX30001_PACE;
+            args.sampleNumberOffset = 18;
+            args.array1 = new int[] {
+                0 << 14 | 1 << 13 | 0 << 12 | 1 << 2 | 0 << 1 | 1, 123456, 123456, 
+                //        Rising                      Falling
+                123456, 123456, 123456, 
+                123456, 123456, 123456, 
+                123456, 123456, 123456,
+                123456, 123456, 123456,
+                123456, 123456, 123456
+            };
+
+
+            form.Controls.Add(ecgView);
+            ecgView.On_AppendChart(this, args);
+            result = ecgView.paceData;
+
+            Assert.AreEqual(1, result.PaceLength(0));
+        }
+
+        [Test]
+        public void PaceDataMaxCode()
+        {
+            Form form = new Form();
+            EcgView ecgView = new EcgView();
+            PaceData result;
+            PartialArrayIntAvailableEventArgs args = new PartialArrayIntAvailableEventArgs();
+            PartialArrayIntAvailableEventArgs ecgArgs = new PartialArrayIntAvailableEventArgs();
+
+            ecgArgs = new PartialArrayIntAvailableEventArgs();
+            ecgArgs.reportID = PartialArrayIntAvailableEventArgs.PACKET_MAX30001_ECG;
+            args.sampleNumberOffset = 5;
+            args.array1 = new int[] {
+                7,
+                7,
+                0, // Tag 0 has pace data
+                7,
+                7
+            };
+
+            args.reportID = PartialArrayIntAvailableEventArgs.PACKET_MAX30001_PACE;
+            args.sampleNumberOffset = 18;
+            args.array1 = new int[] {
+                0 << 14 | 0 << 13 | 0 << 12 | 0x3FF << 2 | 1 << 1 | 1, 123456, 123456, 
+                123456, 123456, 123456, 
+                123456, 123456, 123456, 
+                123456, 123456, 123456,
+                123456, 123456, 123456,
+                123456, 123456, 123456
+            };
+
+
+            form.Controls.Add(ecgView);
+            ecgView.On_AppendChart(this, args);
+            result = ecgView.paceData;
+
+            Assert.AreEqual(-0x3FF, result.PaceLength(0));
+        }
+        */
+
+        [Test]
+        public void PaceDataParsing()
+        {
+            PaceData.PaceRegister register = new PaceData.PaceRegister(new int[] { 0x5865A6, 0x5E868C, 0x6E3FFF });
+
+            Assert.AreEqual(353, register.Edge[0].Data);
+            Assert.AreEqual(361, register.Edge[1].Data);
+            Assert.AreEqual(378, register.Edge[2].Data);
+            Assert.AreEqual(419, register.Edge[3].Data);
+            Assert.AreEqual(440, register.Edge[4].Data);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HspGuiSourceV301/EcgViewTest/Properties/AssemblyInfo.cs	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,36 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following 
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("EcgViewTest")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("Maxim Integrated Products")]
+[assembly: AssemblyProduct("EcgViewTest")]
+[assembly: AssemblyCopyright("Copyright © Maxim Integrated Products 2016")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible 
+// to COM components.  If you need to access a type in this assembly from 
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("780073aa-e9d1-4d5e-9b1b-90d74722b3ad")]
+
+// Version information for an assembly consists of the following four values:
+//
+//      Major Version
+//      Minor Version 
+//      Build Number
+//      Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers 
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HspGuiSourceV301/EcgViewTest/RToRCalculatorTest.cs	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,87 @@
+/*******************************************************************************
+* Copyright (C) 2016 Maxim Integrated Products, Inc., All rights Reserved.
+* 
+* This software is protected by copyright laws of the United States and
+* of foreign countries. This material may also be protected by patent laws
+* and technology transfer regulations of the United States and of foreign
+* countries. This software is furnished under a license agreement and/or a
+* nondisclosure agreement and may only be used or reproduced in accordance
+* with the terms of those agreements. Dissemination of this information to
+* any party or parties not specified in the license agreement and/or
+* nondisclosure agreement is expressly prohibited.
+*
+* The above copyright notice and this permission notice shall be included
+* in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+* OTHER DEALINGS IN THE SOFTWARE.
+*
+* Except as contained in this notice, the name of Maxim Integrated
+* Products, Inc. shall not be used except as stated in the Maxim Integrated
+* Products, Inc. Branding Policy.
+*
+* The mere transfer of this software does not imply any licenses
+* of trade secrets, proprietary technology, copyrights, patents,
+* trademarks, maskwork rights, or any other form of intellectual
+* property whatsoever. Maxim Integrated Products, Inc. retains all
+* ownership rights.
+*******************************************************************************
+*/
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+using NUnit.Framework;
+using HealthSensorPlatform.Presenter;
+using HealthSensorPlatform.Model;
+
+namespace EcgViewTest
+{
+    class RToRCalculatorTest
+    {
+        [TestCase(8746, 0)]
+        [TestCase(9002, 1)]
+        [TestCase(12586, 15)]
+        public void RToRCalculatorDetectionDelay(int expect, int rToRWndw)
+        {
+            RToRCalculator rToRCalc = new RToRCalculator(0, 0, 0, rToRWndw);
+
+            Assert.AreEqual(expect, rToRCalc.RToRDelay);
+        }
+
+        [TestCase(650, 0, 0, 0)]
+        [TestCase(1034, 0, 0, 1)]
+        [TestCase(1034, 0, 0, 2)]
+        [TestCase(1034, 0, 0, 3)]
+        [TestCase(2922, 0, 1, 0)]
+        [TestCase(3370, 0, 2, 0)]
+        [TestCase(3370, 0, 3, 0)]
+        [TestCase(1242, 2, 2, 0)]
+        [TestCase(1242, 3, 2, 0)]
+        [TestCase(1242, 3, 3, 0)]
+        [TestCase(2202, 3, 3, 1)]
+        public void RToRCalculatorEcgDecimationDelay(int expect, int masterClock, int rate, int lpf)
+        {
+            RToRCalculator rToRCalc = new RToRCalculator(masterClock, rate, lpf, 0);
+
+            Assert.AreEqual(expect, rToRCalc.EcgDecimationDelay);
+        }
+
+        [TestCase(100, 118)]
+        public void RToRCalcultorEcgPoints(int expect, int rToR)
+        {
+            RToRCalculator rToRCalc = new RToRCalculator(0, 3, 1, 3);
+
+            Assert.AreEqual(expect, rToRCalc.EcgPoints(rToR, true));
+        }
+
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HspGuiSourceV301/EcgViewTest/RToRTest.cs	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,168 @@
+/*******************************************************************************
+* Copyright (C) 2016 Maxim Integrated Products, Inc., All rights Reserved.
+* 
+* This software is protected by copyright laws of the United States and
+* of foreign countries. This material may also be protected by patent laws
+* and technology transfer regulations of the United States and of foreign
+* countries. This software is furnished under a license agreement and/or a
+* nondisclosure agreement and may only be used or reproduced in accordance
+* with the terms of those agreements. Dissemination of this information to
+* any party or parties not specified in the license agreement and/or
+* nondisclosure agreement is expressly prohibited.
+*
+* The above copyright notice and this permission notice shall be included
+* in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+* OTHER DEALINGS IN THE SOFTWARE.
+*
+* Except as contained in this notice, the name of Maxim Integrated
+* Products, Inc. shall not be used except as stated in the Maxim Integrated
+* Products, Inc. Branding Policy.
+*
+* The mere transfer of this software does not imply any licenses
+* of trade secrets, proprietary technology, copyrights, patents,
+* trademarks, maskwork rights, or any other form of intellectual
+* property whatsoever. Maxim Integrated Products, Inc. retains all
+* ownership rights.
+*******************************************************************************
+*/
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+using NUnit.Framework;
+using HealthSensorPlatform.CustomControls;
+using HealthSensorPlatform.Presenter;
+
+namespace EcgViewTest
+{
+    class RToRTest
+    {
+        [TestCase(8746, 0)]
+        [TestCase(9002, 1)]
+        [TestCase(12586, 15)]
+        public void RToRDetectionDelay(int expect, int rToRWndw)
+        {
+            EcgView view = new EcgView();
+
+            view.RToRWindowField = rToRWndw;
+
+            Assert.AreEqual(expect, view.RToRDelay);
+        }
+
+        [TestCase(650, 0, 0, 0)]
+        [TestCase(1034, 0, 0, 1)]
+        [TestCase(1034, 0, 0, 2)]
+        [TestCase(1034, 0, 0, 3)]
+        [TestCase(2922, 0, 1, 0)]
+        [TestCase(3370, 0, 2, 0)]
+        [TestCase(3370, 0, 3, 0)]
+        [TestCase(1242, 2, 2, 0)]
+        [TestCase(1242, 3, 2, 0)]
+        [TestCase(1242, 3, 3, 0)]
+        [TestCase(2202, 3, 3, 1)]
+        public void EcgDecimationDelay(int expect, int masterClock, int rate, int lpf)
+        {
+            EcgView view = new EcgView();
+            InitArgs.EcgInitStart ecgInit = new InitArgs.EcgInitStart();
+
+            ecgInit.Rate = rate;
+            ecgInit.Dlpf = lpf;
+
+            view.ecgArgs = ecgInit;
+            view.FrequencyMasterField = masterClock;
+
+            Assert.AreEqual(expect, view.EcgDecimationDelay);
+        }
+
+        /*
+        [TestCase(100, 118)]
+        public void RToRToEcgPoints(int expect, int rToR)
+        {
+            EcgView view = new EcgView();
+            InitArgs.EcgInitStart ecgInit = new InitArgs.EcgInitStart();
+
+            ecgInit.Rate = 3;
+            ecgInit.Dlpf = 1;
+
+            view.ecgArgs = ecgInit;
+            view.FrequencyMasterField = 0;
+            view.RToRWindowField = 3;
+
+            Assert.AreEqual(expect, view.RToREcgPoints(rToR, true));
+        }
+
+        [TestCase(205, 128, 1)]
+        [TestCase(205, 128, 2)]
+        [TestCase(204, 128, 3)]
+        [TestCase(205, 128, 4)]
+        [TestCase(205, 128, 5)]
+        [TestCase(205, 128, 6)]
+        [TestCase(205, 128, 7)]
+        [TestCase(204, 128, 8)]
+        [TestCase(205, 128, 9)]
+        [TestCase(205, 128, 10)]
+        [TestCase(205, 128, 11)]
+        [TestCase(205, 128, 12)]
+        [TestCase(204, 128, 13)]
+        public void RToREcgPointRoundingLoop(int expect, int rToR, int loop)
+        {
+            int result = 0;
+
+            EcgView view = new EcgView();
+            InitArgs.EcgInitStart ecgInit = new InitArgs.EcgInitStart();
+
+            ecgInit.Rate = 3;
+            ecgInit.Dlpf = 1;
+
+            view.SampleRateECG = 199.8;
+
+            view.ecgArgs = ecgInit;
+            view.FrequencyMasterField = 3;
+
+            for (int i = 0; i < loop; i++)
+            {
+                result = view.RToREcgPoints(rToR, false);
+            }
+
+            Assert.AreEqual(expect, result);
+        }
+         * */
+
+        [TestCase(205, 128, 1)]
+        [TestCase(205, 128, 2)]
+        [TestCase(204, 128, 3)]
+        [TestCase(205, 128, 4)]
+        [TestCase(205, 128, 5)]
+        [TestCase(205, 128, 6)]
+        [TestCase(205, 128, 7)]
+        [TestCase(204, 128, 8)]
+        [TestCase(205, 128, 9)]
+        [TestCase(205, 128, 10)]
+        [TestCase(205, 128, 11)]
+        [TestCase(205, 128, 12)]
+        [TestCase(204, 128, 13)]
+        public void RToRCalculatorRoundingLoop(int expect, int rToR, int loop)
+        {
+            int result = 0;
+
+            RToRCalculator rToRCalculator = new RToRCalculator(3, 3, 1, 0);
+
+            for (int i = 0; i < loop; i++)
+            {
+                result = rToRCalculator.EcgPoints(rToR, false);
+            }
+
+            Assert.AreEqual(expect, result);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HspGuiSourceV301/EcgViewTest/TemperatureTest.cs	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,84 @@
+/*******************************************************************************
+* Copyright (C) 2016 Maxim Integrated Products, Inc., All rights Reserved.
+* 
+* This software is protected by copyright laws of the United States and
+* of foreign countries. This material may also be protected by patent laws
+* and technology transfer regulations of the United States and of foreign
+* countries. This software is furnished under a license agreement and/or a
+* nondisclosure agreement and may only be used or reproduced in accordance
+* with the terms of those agreements. Dissemination of this information to
+* any party or parties not specified in the license agreement and/or
+* nondisclosure agreement is expressly prohibited.
+*
+* The above copyright notice and this permission notice shall be included
+* in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+* OTHER DEALINGS IN THE SOFTWARE.
+*
+* Except as contained in this notice, the name of Maxim Integrated
+* Products, Inc. shall not be used except as stated in the Maxim Integrated
+* Products, Inc. Branding Policy.
+*
+* The mere transfer of this software does not imply any licenses
+* of trade secrets, proprietary technology, copyrights, patents,
+* trademarks, maskwork rights, or any other form of intellectual
+* property whatsoever. Maxim Integrated Products, Inc. retains all
+* ownership rights.
+*******************************************************************************
+*/
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+using NUnit.Framework;
+using HealthSensorPlatform.CustomControls;
+
+namespace EcgViewTest
+{
+    class TemperatureTest
+    {
+        [TestCase(0x7fff, 128)]
+        [TestCase(0x7f00, 127)]
+        [TestCase(0x7d00, 125)]
+        [TestCase(0x4000, 64)]
+        [TestCase(0x1900, 25)]
+        [TestCase(0x0080, 0.5)]
+        [TestCase(0x0000, 0)]
+        [TestCase(0xff80, -0.5)]
+        [TestCase(0xe700, -25)]
+        [TestCase(0xc900, -55)]
+        public void TemperatureNormalFormat(int hex, double temperature)
+        {
+            TemperatureView view = new TemperatureView();
+
+            Assert.AreEqual(temperature, view.HexToTemperature(hex, false), 0.01);
+        }
+
+        [TestCase(0x5600, 150)]
+        [TestCase(0x4000, 128)]
+        [TestCase(0x3f00, 127)]
+        [TestCase(0x3d00, 125)]
+        [TestCase(0x0000, 64)]
+        [TestCase(0xD900, 25)]
+        [TestCase(0xC080, 0.5)]
+        [TestCase(0xC000, 0)]
+        [TestCase(0xBF80, -0.5)]
+        [TestCase(0xA700, -25)]
+        [TestCase(0x8900, -55)]
+        public void TemperatureExtendedFormat(int hex, double temperature)
+        {
+            TemperatureView view = new TemperatureView();
+
+            Assert.AreEqual(temperature, view.HexToTemperature(hex, true), 0.01);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HspGuiSourceV301/EcgViewTest/packages.config	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<packages>
+  <package id="NUnit" version="2.6.4" targetFramework="net45" />
+</packages>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HspGuiSourceV301/FirFilterTest/App.config	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<configuration>
+    <startup> 
+        <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
+    </startup>
+</configuration>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HspGuiSourceV301/FirFilterTest/FirFilterTest.csproj	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,75 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
+  <PropertyGroup>
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+    <ProjectGuid>{2BFA2046-7A2C-48FB-8E79-CEB2DE6CDD0F}</ProjectGuid>
+    <OutputType>Exe</OutputType>
+    <AppDesignerFolder>Properties</AppDesignerFolder>
+    <RootNamespace>FirFilterTest</RootNamespace>
+    <AssemblyName>FirFilterTest</AssemblyName>
+    <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
+    <FileAlignment>512</FileAlignment>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+    <PlatformTarget>x86</PlatformTarget>
+    <DebugSymbols>true</DebugSymbols>
+    <DebugType>full</DebugType>
+    <Optimize>false</Optimize>
+    <OutputPath>bin\Debug\</OutputPath>
+    <DefineConstants>DEBUG;TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+    <PlatformTarget>x86</PlatformTarget>
+    <DebugType>pdbonly</DebugType>
+    <Optimize>true</Optimize>
+    <OutputPath>bin\Release\</OutputPath>
+    <DefineConstants>TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+  </PropertyGroup>
+  <ItemGroup>
+    <Reference Include="System" />
+    <Reference Include="System.Core" />
+    <Reference Include="System.Xml.Linq" />
+    <Reference Include="System.Data.DataSetExtensions" />
+    <Reference Include="Microsoft.CSharp" />
+    <Reference Include="System.Data" />
+    <Reference Include="System.Xml" />
+  </ItemGroup>
+  <ItemGroup>
+    <Compile Include="Program.cs" />
+    <Compile Include="Properties\AssemblyInfo.cs" />
+    <Compile Include="Properties\Resources.Designer.cs">
+      <AutoGen>True</AutoGen>
+      <DesignTime>True</DesignTime>
+      <DependentUpon>Resources.resx</DependentUpon>
+    </Compile>
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="App.config" />
+  </ItemGroup>
+  <ItemGroup>
+    <ProjectReference Include="..\HSPGui\HSPGui.csproj">
+      <Project>{cef8731e-362f-407c-86a7-f65ace2a1acb}</Project>
+      <Name>HSPGui</Name>
+    </ProjectReference>
+  </ItemGroup>
+  <ItemGroup>
+    <EmbeddedResource Include="Properties\Resources.resx">
+      <Generator>ResXFileCodeGenerator</Generator>
+      <LastGenOutput>Resources.Designer.cs</LastGenOutput>
+    </EmbeddedResource>
+  </ItemGroup>
+  <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+  <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 
+       Other similar extension points exist, see Microsoft.Common.targets.
+  <Target Name="BeforeBuild">
+  </Target>
+  <Target Name="AfterBuild">
+  </Target>
+  -->
+</Project>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HspGuiSourceV301/FirFilterTest/Program.cs	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,76 @@
+/*******************************************************************************
+* Copyright (C) 2016 Maxim Integrated Products, Inc., All rights Reserved.
+* 
+* This software is protected by copyright laws of the United States and
+* of foreign countries. This material may also be protected by patent laws
+* and technology transfer regulations of the United States and of foreign
+* countries. This software is furnished under a license agreement and/or a
+* nondisclosure agreement and may only be used or reproduced in accordance
+* with the terms of those agreements. Dissemination of this information to
+* any party or parties not specified in the license agreement and/or
+* nondisclosure agreement is expressly prohibited.
+*
+* The above copyright notice and this permission notice shall be included
+* in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+* OTHER DEALINGS IN THE SOFTWARE.
+*
+* Except as contained in this notice, the name of Maxim Integrated
+* Products, Inc. shall not be used except as stated in the Maxim Integrated
+* Products, Inc. Branding Policy.
+*
+* The mere transfer of this software does not imply any licenses
+* of trade secrets, proprietary technology, copyrights, patents,
+* trademarks, maskwork rights, or any other form of intellectual
+* property whatsoever. Maxim Integrated Products, Inc. retains all
+* ownership rights.
+*******************************************************************************
+*/
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using HealthSensorPlatform;
+
+namespace FirFilterTest
+{
+    class Program
+    {
+
+        static void Main(string[] args)
+        {
+            FirFilter hpf = new FirFilter(new double[]{-0.008, 0.054, 0.443, 0.443, 0.064, -0.008});
+            int[] stepData = new int[]{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1};           
+            int[] rampData = new int[] {0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 10, 10, 10, 10, 10, 10, 10, 10};
+
+            double point;
+
+            System.Console.WriteLine("Input\tOutput");
+            hpf.Reset();
+            for(int i = 0; i < stepData.Length; i++)
+            {
+                point = hpf.Compute(stepData[i]);
+                System.Console.WriteLine("{0}\t{1}", stepData[i], point); 
+            }
+
+            System.Console.WriteLine("Input\tOutput");
+            hpf.Reset();
+            for (int i = 0; i < rampData.Length; i++)
+            {
+                point = hpf.Compute(rampData[i]);
+                System.Console.WriteLine("{0}\t{1}", rampData[i], point);
+
+            }
+
+            Console.Read();
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HspGuiSourceV301/FirFilterTest/Properties/AssemblyInfo.cs	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,36 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following 
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("FirFilterTest")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("Maxim Integrated Products")]
+[assembly: AssemblyProduct("FirFilterTest")]
+[assembly: AssemblyCopyright("Copyright © Maxim Integrated Products 2015")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible 
+// to COM components.  If you need to access a type in this assembly from 
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("a5c6c103-0f0c-4978-ba38-6a4fb9477dd2")]
+
+// Version information for an assembly consists of the following four values:
+//
+//      Major Version
+//      Minor Version 
+//      Build Number
+//      Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers 
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HspGuiSourceV301/FirFilterTest/Properties/Resources.Designer.cs	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,63 @@
+//------------------------------------------------------------------------------
+// <auto-generated>
+//     This code was generated by a tool.
+//     Runtime Version:4.0.30319.18444
+//
+//     Changes to this file may cause incorrect behavior and will be lost if
+//     the code is regenerated.
+// </auto-generated>
+//------------------------------------------------------------------------------
+
+namespace FirFilterTest.Properties {
+    using System;
+    
+    
+    /// <summary>
+    ///   A strongly-typed resource class, for looking up localized strings, etc.
+    /// </summary>
+    // This class was auto-generated by the StronglyTypedResourceBuilder
+    // class via a tool like ResGen or Visual Studio.
+    // To add or remove a member, edit your .ResX file then rerun ResGen
+    // with the /str option, or rebuild your VS project.
+    [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+    [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+    internal class Resources {
+        
+        private static global::System.Resources.ResourceManager resourceMan;
+        
+        private static global::System.Globalization.CultureInfo resourceCulture;
+        
+        [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
+        internal Resources() {
+        }
+        
+        /// <summary>
+        ///   Returns the cached ResourceManager instance used by this class.
+        /// </summary>
+        [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+        internal static global::System.Resources.ResourceManager ResourceManager {
+            get {
+                if (object.ReferenceEquals(resourceMan, null)) {
+                    global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("FirFilterTest.Properties.Resources", typeof(Resources).Assembly);
+                    resourceMan = temp;
+                }
+                return resourceMan;
+            }
+        }
+        
+        /// <summary>
+        ///   Overrides the current thread's CurrentUICulture property for all
+        ///   resource lookups using this strongly typed resource class.
+        /// </summary>
+        [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+        internal static global::System.Globalization.CultureInfo Culture {
+            get {
+                return resourceCulture;
+            }
+            set {
+                resourceCulture = value;
+            }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HspGuiSourceV301/FirFilterTest/Properties/Resources.resx	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,120 @@
+<?xml version="1.0" encoding="utf-8"?>
+<root>
+  <!-- 
+    Microsoft ResX Schema 
+    
+    Version 2.0
+    
+    The primary goals of this format is to allow a simple XML format 
+    that is mostly human readable. The generation and parsing of the 
+    various data types are done through the TypeConverter classes 
+    associated with the data types.
+    
+    Example:
+    
+    ... ado.net/XML headers & schema ...
+    <resheader name="resmimetype">text/microsoft-resx</resheader>
+    <resheader name="version">2.0</resheader>
+    <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+    <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+    <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
+    <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+    <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+        <value>[base64 mime encoded serialized .NET Framework object]</value>
+    </data>
+    <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+        <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
+        <comment>This is a comment</comment>
+    </data>
+                
+    There are any number of "resheader" rows that contain simple 
+    name/value pairs.
+    
+    Each data row contains a name, and value. The row also contains a 
+    type or mimetype. Type corresponds to a .NET class that support 
+    text/value conversion through the TypeConverter architecture. 
+    Classes that don't support this are serialized and stored with the 
+    mimetype set.
+    
+    The mimetype is used for serialized objects, and tells the 
+    ResXResourceReader how to depersist the object. This is currently not 
+    extensible. For a given mimetype the value must be set accordingly:
+    
+    Note - application/x-microsoft.net.object.binary.base64 is the format 
+    that the ResXResourceWriter will generate, however the reader can 
+    read any of the formats listed below.
+    
+    mimetype: application/x-microsoft.net.object.binary.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
+            : and then encoded with base64 encoding.
+    
+    mimetype: application/x-microsoft.net.object.soap.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+            : and then encoded with base64 encoding.
+
+    mimetype: application/x-microsoft.net.object.bytearray.base64
+    value   : The object must be serialized into a byte array 
+            : using a System.ComponentModel.TypeConverter
+            : and then encoded with base64 encoding.
+    -->
+  <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+    <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
+    <xsd:element name="root" msdata:IsDataSet="true">
+      <xsd:complexType>
+        <xsd:choice maxOccurs="unbounded">
+          <xsd:element name="metadata">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" />
+              </xsd:sequence>
+              <xsd:attribute name="name" use="required" type="xsd:string" />
+              <xsd:attribute name="type" type="xsd:string" />
+              <xsd:attribute name="mimetype" type="xsd:string" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="assembly">
+            <xsd:complexType>
+              <xsd:attribute name="alias" type="xsd:string" />
+              <xsd:attribute name="name" type="xsd:string" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="data">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+                <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
+              <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+              <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="resheader">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" />
+            </xsd:complexType>
+          </xsd:element>
+        </xsd:choice>
+      </xsd:complexType>
+    </xsd:element>
+  </xsd:schema>
+  <resheader name="resmimetype">
+    <value>text/microsoft-resx</value>
+  </resheader>
+  <resheader name="version">
+    <value>2.0</value>
+  </resheader>
+  <resheader name="reader">
+    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <resheader name="writer">
+    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+</root>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HspGuiSourceV301/GuiDLLs/ChartHelper/ChartHelper/AutoScaleCalculator.cs	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,270 @@
+/*******************************************************************************
+* Copyright (C) 2016 Maxim Integrated Products, Inc., All rights Reserved.
+* 
+* This software is protected by copyright laws of the United States and
+* of foreign countries. This material may also be protected by patent laws
+* and technology transfer regulations of the United States and of foreign
+* countries. This software is furnished under a license agreement and/or a
+* nondisclosure agreement and may only be used or reproduced in accordance
+* with the terms of those agreements. Dissemination of this information to
+* any party or parties not specified in the license agreement and/or
+* nondisclosure agreement is expressly prohibited.
+*
+* The above copyright notice and this permission notice shall be included
+* in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+* OTHER DEALINGS IN THE SOFTWARE.
+*
+* Except as contained in this notice, the name of Maxim Integrated
+* Products, Inc. shall not be used except as stated in the Maxim Integrated
+* Products, Inc. Branding Policy.
+*
+* The mere transfer of this software does not imply any licenses
+* of trade secrets, proprietary technology, copyrights, patents,
+* trademarks, maskwork rights, or any other form of intellectual
+* property whatsoever. Maxim Integrated Products, Inc. retains all
+* ownership rights.
+*******************************************************************************
+*/
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Maxim.Charting
+{
+    public class AutoScaleCalculator : IAutoScaleAxisCalculator
+    {
+        private const double Hystersis = 0.05;
+
+        private double lastMinimum;
+        private double lastMaximum;
+
+        private bool filterEnable = true;
+        MedianFilter filter;
+
+        public AutoScaleCalculator(double min, double max)
+        {
+            lastMinimum = min;
+            lastMaximum = max;
+
+            filter = new MedianFilter(8);
+        }
+
+        public bool Filter
+        {
+            get
+            {
+                return filterEnable;
+            }
+            set
+            {
+                filterEnable = value;
+            }
+        }
+
+        public double Maximum { get; set; }
+        public double Minimum { get; set; }
+
+        public int Intervals { get; set; }
+
+        public double LastMaximum
+        {
+            get
+            {
+                return lastMaximum;
+            }
+        }
+
+        public double LastMinimum
+        {
+            get
+            {
+                return lastMinimum;
+            }
+        }
+
+        public double MinimumRange { get; set; }
+
+        public double ScaleTrigger { get; set; }
+
+        public double RescaleTargetRange { get; set; }
+
+        public bool NeedsRescale(double minimum, double maximum)
+        {
+            double chartRange = lastMaximum - lastMinimum;
+            double dataRange = maximum - minimum;
+
+            return (minimum < lastMinimum + chartRange * (0.5 - ScaleTrigger / 2)  // If data moves close to edges of chart
+                || maximum > lastMaximum - chartRange * (0.5 - ScaleTrigger / 2)
+                || dataRange < chartRange * (0.5 - ScaleTrigger / 2)    // Rescale of AC value delta reaches close the chart range
+                || dataRange > chartRange * (0.5 + ScaleTrigger / 2));
+        }
+
+        public Tuple<double, double> Interval(double minimum, double maximum)
+        {
+            double chartRange;
+            double dataRange;
+            double roundedInterval, roundedIntervalFinal;
+
+            double intervalTarget, center;
+            double roundedCenter;
+
+            double roundMin, roundMax;
+
+            chartRange = lastMaximum - lastMinimum;
+            dataRange = maximum - minimum;
+
+            if (NeedsRescale(minimum, maximum))
+            {
+                intervalTarget = (dataRange / (RescaleTargetRange)) / Intervals;
+                center = minimum + (maximum - minimum) / 2;
+                roundedInterval = roundSignificantDigits(intervalTarget); // Keep MS-digit, drop LS-digits
+
+                /* Special Cases */
+                // Exceeds  Minimum and Maximum value
+                if (center - roundedInterval * Intervals / 2.0 < Minimum && center + roundedInterval * Intervals / 2.0 > Maximum)
+                {
+                    intervalTarget = (Maximum - Minimum) / (0.8 * Intervals);
+                    center = Minimum + (Maximum - Minimum) / 2;
+                }
+                else if (roundedInterval * Intervals > (Maximum - Minimum)) // Large Value change, cap to full scale
+                {
+                    intervalTarget = (maximum - minimum) / (0.8 * Intervals);
+                    center = (maximum + minimum) / 2;
+                }
+                else if (center - roundedInterval * Intervals / 2.0 < Minimum) // Below Minimum
+                {
+                    intervalTarget = (maximum - Minimum) / (0.8 * Intervals);
+                    center = Minimum + (maximum - Minimum) / 2;
+                }
+                else if (center + roundedInterval * Intervals / 2.0 > Maximum) // Above Maximum
+                {
+                    intervalTarget = (Maximum - minimum) / (0.8 * Intervals);
+                    center = minimum + (Maximum - minimum) / 2;
+                }
+
+                // Recalculate interval
+                roundedIntervalFinal = roundSignificantDigits(intervalTarget); // Keep MS-digit, drop LS-digits
+                if (roundedIntervalFinal < MinimumRange)
+                    roundedIntervalFinal = MinimumRange;
+
+                if (Filter == true)
+                    roundedIntervalFinal = filter.Filter((int)roundedIntervalFinal);
+
+                //roundedCenter = (((int)center + 100) / 200) * 200; // find center and try to round nicely
+                roundedCenter = (((int)center + 50) / 100) * 100;
+
+                roundMin = ((int)(roundedCenter - roundedIntervalFinal * (Intervals / 2.0)));
+                roundMax = ((int)(roundedCenter + roundedIntervalFinal * (Intervals / 2.0)));
+
+                lastMinimum = roundMin;
+                lastMaximum = roundMax;
+
+                return new Tuple<double, double>(roundMin, roundMax);
+            }
+            else
+            {
+                return new Tuple<double, double>(lastMinimum, lastMaximum);
+            }
+        }
+
+        public Tuple<double, double> Interval(double minimum, double maximum, double chartMinium, double chartMaximum)
+        {
+            throw new NotImplementedException();
+        }
+
+        private double roundSignificantDigits(double value)
+        {
+            double mag, magPower, magMostSigDigit;
+
+            mag = Math.Floor(Math.Log10(value));
+            magPower = Math.Pow(10, mag);
+
+            magMostSigDigit = (int)(value / (magPower) + 0.5);
+
+            if (magMostSigDigit >= 10.0)
+                magMostSigDigit = 10;
+            else if (magMostSigDigit >= 5.0)
+                magMostSigDigit = 5;
+            else if (magMostSigDigit >= 2.0)
+                magMostSigDigit = 2;
+            else
+                magMostSigDigit = 1;
+
+            return magMostSigDigit * magPower;
+        }
+    }
+
+    class MedianFilter
+    {
+        Queue<int> items;
+        int depth;
+
+        public MedianFilter(int depth)
+        {
+            items = new Queue<int>(depth + 1);
+            this.depth = depth;
+        }
+
+        public int Filter(int current)
+        {
+            int last;
+
+            items.Enqueue(current);
+            if (items.Count > depth)
+            {
+                items.Dequeue();
+            }
+
+            last = items.Peek();
+
+            if (items.Count < depth)
+            {
+                return current;
+            }
+            else
+            {
+                int count;
+                int[] arrayItems = items.ToArray();
+                int maxKey = 0;
+
+                Dictionary<int, int> valueOccurance = new Dictionary<int, int>();
+
+                for (int i = 0; i < arrayItems.Length; i++)
+                {
+                    bool exists = valueOccurance.TryGetValue(arrayItems[i], out count);
+                    if (exists)
+                    {
+                        count++;
+                        valueOccurance.Remove(arrayItems[i]);
+                        valueOccurance.Add(arrayItems[i], count);
+                    }
+                    else
+                    {
+                        valueOccurance.Add(arrayItems[i], 1);
+                    }
+                }
+
+                foreach (KeyValuePair<int, int> item in valueOccurance)
+                {
+                    if (item.Key > maxKey)
+                    {
+                        maxKey = item.Key;
+                    }
+                }
+
+                return maxKey;
+            }
+
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HspGuiSourceV301/GuiDLLs/ChartHelper/ChartHelper/ChartHelper.csproj	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,55 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
+  <PropertyGroup>
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+    <ProjectGuid>{3A90EBB9-82C1-4928-88AC-A79ABC7F1DE9}</ProjectGuid>
+    <OutputType>Library</OutputType>
+    <AppDesignerFolder>Properties</AppDesignerFolder>
+    <RootNamespace>Maxim.Charting</RootNamespace>
+    <AssemblyName>ChartHelper</AssemblyName>
+    <TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
+    <FileAlignment>512</FileAlignment>
+    <TargetFrameworkProfile />
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+    <DebugSymbols>true</DebugSymbols>
+    <DebugType>full</DebugType>
+    <Optimize>false</Optimize>
+    <OutputPath>bin\Debug\</OutputPath>
+    <DefineConstants>DEBUG;TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+    <DebugType>pdbonly</DebugType>
+    <Optimize>true</Optimize>
+    <OutputPath>bin\Release\</OutputPath>
+    <DefineConstants>TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+  </PropertyGroup>
+  <ItemGroup>
+    <Reference Include="System" />
+    <Reference Include="System.Core" />
+    <Reference Include="System.Xml.Linq" />
+    <Reference Include="System.Data.DataSetExtensions" />
+    <Reference Include="Microsoft.CSharp" />
+    <Reference Include="System.Data" />
+    <Reference Include="System.Xml" />
+  </ItemGroup>
+  <ItemGroup>
+    <Compile Include="AutoScaleCalculator.cs" />
+    <Compile Include="IAutoScaleAxisCalculator.cs" />
+    <Compile Include="Properties\AssemblyInfo.cs" />
+  </ItemGroup>
+  <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+  <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 
+       Other similar extension points exist, see Microsoft.Common.targets.
+  <Target Name="BeforeBuild">
+  </Target>
+  <Target Name="AfterBuild">
+  </Target>
+  -->
+</Project>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HspGuiSourceV301/GuiDLLs/ChartHelper/ChartHelper/IAutoScaleAxisCalculator.cs	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,102 @@
+/*******************************************************************************
+* Copyright (C) 2016 Maxim Integrated Products, Inc., All rights Reserved.
+* 
+* This software is protected by copyright laws of the United States and
+* of foreign countries. This material may also be protected by patent laws
+* and technology transfer regulations of the United States and of foreign
+* countries. This software is furnished under a license agreement and/or a
+* nondisclosure agreement and may only be used or reproduced in accordance
+* with the terms of those agreements. Dissemination of this information to
+* any party or parties not specified in the license agreement and/or
+* nondisclosure agreement is expressly prohibited.
+*
+* The above copyright notice and this permission notice shall be included
+* in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+* OTHER DEALINGS IN THE SOFTWARE.
+*
+* Except as contained in this notice, the name of Maxim Integrated
+* Products, Inc. shall not be used except as stated in the Maxim Integrated
+* Products, Inc. Branding Policy.
+*
+* The mere transfer of this software does not imply any licenses
+* of trade secrets, proprietary technology, copyrights, patents,
+* trademarks, maskwork rights, or any other form of intellectual
+* property whatsoever. Maxim Integrated Products, Inc. retains all
+* ownership rights.
+*******************************************************************************
+*/
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Maxim.Charting
+{
+    interface IAutoScaleAxisCalculator
+    {
+        /// <summary>
+        /// Maximum possible data point
+        /// </summary>
+        double Maximum { get; set; }
+        /// <summary>
+        /// Minimum possible data point
+        /// </summary>
+        double Minimum { get; set; }
+
+        /// <summary>
+        /// Number of y-axis chart interval grid lines
+        /// </summary>
+        int Intervals { get; set; }
+
+        /// <summary>
+        /// Previous maximum interval result
+        /// </summary>
+        double LastMaximum { get; }
+        /// <summary>
+        /// Previous minimum interval result
+        /// </summary>
+        double LastMinimum { get; }
+
+        /// <summary>
+        /// Full scale range should be larger than this value
+        /// </summary>
+        double MinimumRange { get; set; }
+
+        /// <summary>
+        /// Trigger rescale value when data exceeds fraction of full scale. For example, a value of 0.8 will rescale on 10% (0.5 - 0.8/2) and 90% (0.5 + 0.8/2) of full scale.
+        /// </summary>
+        double ScaleTrigger { get; set; }
+
+        /// <summary>
+        /// Rescale data to be within a certain fraction of full scale. For example, a value of 0.25 will rescale so that the data minimum and maximum occupy 25% of the full scale.
+        /// </summary>
+        double RescaleTargetRange { get; set; }
+
+        /// <summary>
+        /// Calculate the round axis minimum and maximum value. Maximum range needs to be larger than 1 for this to function.
+        /// </summary>
+        /// <param name="dataMinimum">minimum value of data set</param>
+        /// <param name="dataMaximum">maximum value of data set</param>
+        /// <returns>minimum value, maximum value</returns>
+        Tuple<double, double> Interval(double dataMinimum, double dataMaximum);
+        
+        /// <summary>
+        /// Calculate the round axis minimum and maximum value. Maximum range needs to be larger than 1 for this to function.
+        /// </summary>
+        /// <param name="dataMinimum">minimum value of data set</param>
+        /// <param name="dataMaximum">maximum value of data set</param>
+        /// <param name="chartMinimum">minimum value of current chart</param>
+        /// <param name="chartMaximum">maximum value of current chart</param>
+        /// <returns>minimum value, maximum value</returns>
+        Tuple<double, double> Interval(double dataMinimum, double dataMaximum, double chartMinimum, double chartMaximum);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HspGuiSourceV301/GuiDLLs/ChartHelper/ChartHelper/Properties/AssemblyInfo.cs	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,36 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following 
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("ChartHelper")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("Maxim Integrated Products")]
+[assembly: AssemblyProduct("ChartHelper")]
+[assembly: AssemblyCopyright("Copyright © Maxim Integrated Products 2016")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible 
+// to COM components.  If you need to access a type in this assembly from 
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("4e25f581-081e-467c-9f59-6d73ff8b8e93")]
+
+// Version information for an assembly consists of the following four values:
+//
+//      Major Version
+//      Minor Version 
+//      Build Number
+//      Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers 
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HspGuiSourceV301/GuiDLLs/ChartHelper/Maxim.Charting.ChartHelper.sln	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,22 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 2013
+VisualStudioVersion = 12.0.31101.0
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ChartHelper", "ChartHelper\ChartHelper.csproj", "{3A90EBB9-82C1-4928-88AC-A79ABC7F1DE9}"
+EndProject
+Global
+	GlobalSection(SolutionConfigurationPlatforms) = preSolution
+		Debug|Any CPU = Debug|Any CPU
+		Release|Any CPU = Release|Any CPU
+	EndGlobalSection
+	GlobalSection(ProjectConfigurationPlatforms) = postSolution
+		{3A90EBB9-82C1-4928-88AC-A79ABC7F1DE9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{3A90EBB9-82C1-4928-88AC-A79ABC7F1DE9}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{3A90EBB9-82C1-4928-88AC-A79ABC7F1DE9}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{3A90EBB9-82C1-4928-88AC-A79ABC7F1DE9}.Release|Any CPU.Build.0 = Release|Any CPU
+	EndGlobalSection
+	GlobalSection(SolutionProperties) = preSolution
+		HideSolutionNode = FALSE
+	EndGlobalSection
+EndGlobal
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HspGuiSourceV301/GuiDLLs/FileLog/FileLog.sln	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,28 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 2013
+VisualStudioVersion = 12.0.31101.0
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FileLog", "FileLog\FileLog.csproj", "{53B0D46E-43FD-425E-B316-98B8708D161F}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FileLogExample", "FileLogExample\FileLogExample.csproj", "{60A6930E-EA97-4317-BCC8-7BC7987669B3}"
+EndProject
+Global
+	GlobalSection(SolutionConfigurationPlatforms) = preSolution
+		Debug|Any CPU = Debug|Any CPU
+		Release|Any CPU = Release|Any CPU
+	EndGlobalSection
+	GlobalSection(ProjectConfigurationPlatforms) = postSolution
+		{53B0D46E-43FD-425E-B316-98B8708D161F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{53B0D46E-43FD-425E-B316-98B8708D161F}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{53B0D46E-43FD-425E-B316-98B8708D161F}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{53B0D46E-43FD-425E-B316-98B8708D161F}.Release|Any CPU.Build.0 = Release|Any CPU
+		{60A6930E-EA97-4317-BCC8-7BC7987669B3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{60A6930E-EA97-4317-BCC8-7BC7987669B3}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{60A6930E-EA97-4317-BCC8-7BC7987669B3}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{60A6930E-EA97-4317-BCC8-7BC7987669B3}.Release|Any CPU.Build.0 = Release|Any CPU
+	EndGlobalSection
+	GlobalSection(SolutionProperties) = preSolution
+		HideSolutionNode = FALSE
+	EndGlobalSection
+EndGlobal
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HspGuiSourceV301/GuiDLLs/FileLog/FileLog/FileCsvReader.cs	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,107 @@
+/*******************************************************************************
+* Copyright (C) 2016 Maxim Integrated Products, Inc., All rights Reserved.
+* 
+* This software is protected by copyright laws of the United States and
+* of foreign countries. This material may also be protected by patent laws
+* and technology transfer regulations of the United States and of foreign
+* countries. This software is furnished under a license agreement and/or a
+* nondisclosure agreement and may only be used or reproduced in accordance
+* with the terms of those agreements. Dissemination of this information to
+* any party or parties not specified in the license agreement and/or
+* nondisclosure agreement is expressly prohibited.
+*
+* The above copyright notice and this permission notice shall be included
+* in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+* OTHER DEALINGS IN THE SOFTWARE.
+*
+* Except as contained in this notice, the name of Maxim Integrated
+* Products, Inc. shall not be used except as stated in the Maxim Integrated
+* Products, Inc. Branding Policy.
+*
+* The mere transfer of this software does not imply any licenses
+* of trade secrets, proprietary technology, copyrights, patents,
+* trademarks, maskwork rights, or any other form of intellectual
+* property whatsoever. Maxim Integrated Products, Inc. retains all
+* ownership rights.
+*******************************************************************************
+*/
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.IO;
+using System.Windows.Forms;
+
+namespace Maxim.Utility
+{
+    public class FileCsvReader
+    {
+        StreamReader inputStream = null;
+        OpenFileDialog fileDialog = new OpenFileDialog();
+
+        string fileDirectory;
+
+        public FileCsvReader()
+        {
+            fileDirectory = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
+        }
+
+        public bool OpenCSVFile()
+        {
+            fileDialog.InitialDirectory = fileDirectory;
+            fileDialog.Filter = "CSV files (*.csv)|*.csv|All files (*.*)|*.*";
+            if (fileDialog.ShowDialog() == DialogResult.OK)
+            {
+                fileDirectory = Path.GetDirectoryName(fileDialog.FileName);
+                inputStream = new StreamReader(fileDialog.FileName);
+                return true;
+            }
+            else
+                return false;
+        }
+
+        public string FileDirectory
+        {
+            get
+            {
+                return fileDirectory;
+            }
+            set
+            {
+                fileDirectory = value;
+            }
+        }
+
+        public int Peek()
+        {
+            return inputStream.Peek();
+        }
+
+        public string ReadLine()
+        {
+            return inputStream.ReadLine();
+        }
+
+        public string[] ReadLineElements()
+        {
+            string str = ReadLine();
+
+            string[] items = str.Split(',');
+
+            return items;
+        }
+
+        public void Close()
+        {
+            inputStream.Close();
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HspGuiSourceV301/GuiDLLs/FileLog/FileLog/FileLog.cs	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,118 @@
+/*******************************************************************************
+* Copyright (C) 2016 Maxim Integrated Products, Inc., All rights Reserved.
+* 
+* This software is protected by copyright laws of the United States and
+* of foreign countries. This material may also be protected by patent laws
+* and technology transfer regulations of the United States and of foreign
+* countries. This software is furnished under a license agreement and/or a
+* nondisclosure agreement and may only be used or reproduced in accordance
+* with the terms of those agreements. Dissemination of this information to
+* any party or parties not specified in the license agreement and/or
+* nondisclosure agreement is expressly prohibited.
+*
+* The above copyright notice and this permission notice shall be included
+* in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+* OTHER DEALINGS IN THE SOFTWARE.
+*
+* Except as contained in this notice, the name of Maxim Integrated
+* Products, Inc. shall not be used except as stated in the Maxim Integrated
+* Products, Inc. Branding Policy.
+*
+* The mere transfer of this software does not imply any licenses
+* of trade secrets, proprietary technology, copyrights, patents,
+* trademarks, maskwork rights, or any other form of intellectual
+* property whatsoever. Maxim Integrated Products, Inc. retains all
+* ownership rights.
+*******************************************************************************
+*/
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.IO;
+using System.Windows.Forms;
+
+using Maxim.Global;
+
+namespace Maxim.Utility
+{
+    public class FileLog
+    {
+        StreamWriter outputStream = null;
+        SaveFileDialog fileDialog = new SaveFileDialog();
+        string fileDirectory = null;
+
+        public EventHandler<Maxim.Global.ErrorEventArgs> Error;
+
+        public FileLog()
+        {
+            fileDirectory = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
+            fileDialog.InitialDirectory = fileDirectory;
+        }
+
+        public string FileDirectory
+        {
+            get
+            {
+                return fileDirectory;
+            }
+            set
+            {
+                fileDirectory = value;
+            }
+        }
+        
+        public bool SelectCSVFile(string fileName)
+        {
+            fileDialog.FileName = fileName + "_" + string.Format("{0:yyyy-MM-dd_HH-mm-ss}", DateTime.Now) + ".csv";
+            fileDialog.Filter = "CSV files (*.csv)|*.csv|All files (*.*)|*.*";
+            fileDialog.InitialDirectory = fileDirectory;
+            if (fileDialog.ShowDialog() == DialogResult.OK)
+            {
+                fileDirectory = Path.GetDirectoryName(fileDialog.FileName);
+                outputStream = new StreamWriter(fileDialog.FileName, false, System.Text.Encoding.UTF8);
+                outputStream.AutoFlush = true;
+
+                return true;
+            }
+            else
+                return false;
+        }
+
+        public void Close()
+        {
+            if (outputStream != null)
+            {
+                try
+                {
+                    outputStream.Flush();
+                }
+                catch (System.ObjectDisposedException)
+                {
+                    // TODO
+                }
+                outputStream.Close();
+            }
+        }
+
+        public void Write(string value)
+        {
+            outputStream.Write(value);
+        }
+
+        public void WriteLine(string value)
+        {
+            //outputStream.WriteLine(string.Format("{0:HH-mm-ss}", DateTime.Now) + ", " + value);
+            outputStream.WriteLine(value);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HspGuiSourceV301/GuiDLLs/FileLog/FileLog/FileLog.csproj	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,62 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
+  <PropertyGroup>
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+    <ProjectGuid>{53B0D46E-43FD-425E-B316-98B8708D161F}</ProjectGuid>
+    <OutputType>Library</OutputType>
+    <AppDesignerFolder>Properties</AppDesignerFolder>
+    <RootNamespace>Maxim.Utility</RootNamespace>
+    <AssemblyName>FileLog</AssemblyName>
+    <TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
+    <FileAlignment>512</FileAlignment>
+    <TargetFrameworkProfile />
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+    <DebugSymbols>true</DebugSymbols>
+    <DebugType>full</DebugType>
+    <Optimize>false</Optimize>
+    <OutputPath>bin\Debug\</OutputPath>
+    <DefineConstants>DEBUG;TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+    <DebugType>pdbonly</DebugType>
+    <Optimize>true</Optimize>
+    <OutputPath>bin\Release\</OutputPath>
+    <DefineConstants>TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+  </PropertyGroup>
+  <ItemGroup>
+    <Reference Include="System" />
+    <Reference Include="System.Core" />
+    <Reference Include="System.Windows.Forms" />
+    <Reference Include="System.Xml.Linq" />
+    <Reference Include="System.Data.DataSetExtensions" />
+    <Reference Include="Microsoft.CSharp" />
+    <Reference Include="System.Data" />
+    <Reference Include="System.Xml" />
+  </ItemGroup>
+  <ItemGroup>
+    <Compile Include="FileCsvReader.cs" />
+    <Compile Include="FileLog.cs" />
+    <Compile Include="Properties\AssemblyInfo.cs" />
+  </ItemGroup>
+  <ItemGroup>
+    <ProjectReference Include="..\..\MaximGlobal\Maxim.Global.csproj">
+      <Project>{57e4e43c-871b-4113-950e-d649ac6d386a}</Project>
+      <Name>Maxim.Global</Name>
+    </ProjectReference>
+  </ItemGroup>
+  <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+  <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 
+       Other similar extension points exist, see Microsoft.Common.targets.
+  <Target Name="BeforeBuild">
+  </Target>
+  <Target Name="AfterBuild">
+  </Target>
+  -->
+</Project>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HspGuiSourceV301/GuiDLLs/FileLog/FileLog/Properties/AssemblyInfo.cs	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,36 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following 
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("FileLog")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("Maxim Integrated Products")]
+[assembly: AssemblyProduct("FileLog")]
+[assembly: AssemblyCopyright("Copyright © Maxim Integrated Products 2016")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible 
+// to COM components.  If you need to access a type in this assembly from 
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("aa319a5f-f524-426c-909c-54c6c0e2cbc3")]
+
+// Version information for an assembly consists of the following four values:
+//
+//      Major Version
+//      Minor Version 
+//      Build Number
+//      Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers 
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HspGuiSourceV301/GuiDLLs/FileLog/FileLogExample/App.config	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<configuration>
+    <startup> 
+        <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
+    </startup>
+</configuration>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HspGuiSourceV301/GuiDLLs/FileLog/FileLogExample/FileLogExample.csproj	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,97 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
+  <PropertyGroup>
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+    <ProjectGuid>{60A6930E-EA97-4317-BCC8-7BC7987669B3}</ProjectGuid>
+    <OutputType>WinExe</OutputType>
+    <AppDesignerFolder>Properties</AppDesignerFolder>
+    <RootNamespace>FileLogExample</RootNamespace>
+    <AssemblyName>FileLogExample</AssemblyName>
+    <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
+    <FileAlignment>512</FileAlignment>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+    <PlatformTarget>AnyCPU</PlatformTarget>
+    <DebugSymbols>true</DebugSymbols>
+    <DebugType>full</DebugType>
+    <Optimize>false</Optimize>
+    <OutputPath>bin\Debug\</OutputPath>
+    <DefineConstants>DEBUG;TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+    <PlatformTarget>AnyCPU</PlatformTarget>
+    <DebugType>pdbonly</DebugType>
+    <Optimize>true</Optimize>
+    <OutputPath>bin\Release\</OutputPath>
+    <DefineConstants>TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+  </PropertyGroup>
+  <ItemGroup>
+    <Reference Include="System" />
+    <Reference Include="System.Core" />
+    <Reference Include="System.Xml.Linq" />
+    <Reference Include="System.Data.DataSetExtensions" />
+    <Reference Include="Microsoft.CSharp" />
+    <Reference Include="System.Data" />
+    <Reference Include="System.Deployment" />
+    <Reference Include="System.Drawing" />
+    <Reference Include="System.Windows.Forms" />
+    <Reference Include="System.Xml" />
+  </ItemGroup>
+  <ItemGroup>
+    <Compile Include="Form1.cs">
+      <SubType>Form</SubType>
+    </Compile>
+    <Compile Include="Form1.Designer.cs">
+      <DependentUpon>Form1.cs</DependentUpon>
+    </Compile>
+    <Compile Include="Program.cs" />
+    <Compile Include="Properties\AssemblyInfo.cs" />
+    <EmbeddedResource Include="Form1.resx">
+      <DependentUpon>Form1.cs</DependentUpon>
+    </EmbeddedResource>
+    <EmbeddedResource Include="Properties\Resources.resx">
+      <Generator>ResXFileCodeGenerator</Generator>
+      <LastGenOutput>Resources.Designer.cs</LastGenOutput>
+      <SubType>Designer</SubType>
+    </EmbeddedResource>
+    <Compile Include="Properties\Resources.Designer.cs">
+      <AutoGen>True</AutoGen>
+      <DependentUpon>Resources.resx</DependentUpon>
+    </Compile>
+    <None Include="Properties\Settings.settings">
+      <Generator>SettingsSingleFileGenerator</Generator>
+      <LastGenOutput>Settings.Designer.cs</LastGenOutput>
+    </None>
+    <Compile Include="Properties\Settings.Designer.cs">
+      <AutoGen>True</AutoGen>
+      <DependentUpon>Settings.settings</DependentUpon>
+      <DesignTimeSharedInput>True</DesignTimeSharedInput>
+    </Compile>
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="App.config" />
+  </ItemGroup>
+  <ItemGroup>
+    <ProjectReference Include="..\FileLog\FileLog.csproj">
+      <Project>{53b0d46e-43fd-425e-b316-98b8708d161f}</Project>
+      <Name>FileLog</Name>
+    </ProjectReference>
+  </ItemGroup>
+  <ItemGroup>
+    <Content Include="TextCases.txt" />
+  </ItemGroup>
+  <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+  <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 
+       Other similar extension points exist, see Microsoft.Common.targets.
+  <Target Name="BeforeBuild">
+  </Target>
+  <Target Name="AfterBuild">
+  </Target>
+  -->
+</Project>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HspGuiSourceV301/GuiDLLs/FileLog/FileLogExample/Form1.Designer.cs	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,74 @@
+namespace FileLogExample
+{
+    partial class Form1
+    {
+        /// <summary>
+        /// Required designer variable.
+        /// </summary>
+        private System.ComponentModel.IContainer components = null;
+
+        /// <summary>
+        /// Clean up any resources being used.
+        /// </summary>
+        /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
+        protected override void Dispose(bool disposing)
+        {
+            if (disposing && (components != null))
+            {
+                components.Dispose();
+            }
+            base.Dispose(disposing);
+        }
+
+        #region Windows Form Designer generated code
+
+        /// <summary>
+        /// Required method for Designer support - do not modify
+        /// the contents of this method with the code editor.
+        /// </summary>
+        private void InitializeComponent()
+        {
+            this.button1 = new System.Windows.Forms.Button();
+            this.button2 = new System.Windows.Forms.Button();
+            this.SuspendLayout();
+            // 
+            // button1
+            // 
+            this.button1.Location = new System.Drawing.Point(42, 22);
+            this.button1.Name = "button1";
+            this.button1.Size = new System.Drawing.Size(75, 23);
+            this.button1.TabIndex = 0;
+            this.button1.Text = "Select File";
+            this.button1.UseVisualStyleBackColor = true;
+            this.button1.Click += new System.EventHandler(this.button1_Click);
+            // 
+            // button2
+            // 
+            this.button2.Location = new System.Drawing.Point(42, 60);
+            this.button2.Name = "button2";
+            this.button2.Size = new System.Drawing.Size(75, 23);
+            this.button2.TabIndex = 1;
+            this.button2.Text = "Save Data";
+            this.button2.UseVisualStyleBackColor = true;
+            this.button2.Click += new System.EventHandler(this.button2_Click);
+            // 
+            // Form1
+            // 
+            this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
+            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+            this.ClientSize = new System.Drawing.Size(284, 262);
+            this.Controls.Add(this.button2);
+            this.Controls.Add(this.button1);
+            this.Name = "Form1";
+            this.Text = "Form1";
+            this.ResumeLayout(false);
+
+        }
+
+        #endregion
+
+        private System.Windows.Forms.Button button1;
+        private System.Windows.Forms.Button button2;
+    }
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HspGuiSourceV301/GuiDLLs/FileLog/FileLogExample/Form1.cs	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,49 @@
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Data;
+using System.Drawing;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows.Forms;
+using Maxim.Utility;
+
+namespace FileLogExample
+{
+    public partial class Form1 : Form
+    {
+        FileLog fileLog = new FileLog();
+        bool fileSelected = false;
+        int count = 0;
+        
+        public Form1()
+        {
+            InitializeComponent();
+        }
+
+        private void button1_Click(object sender, EventArgs e)
+        {
+            try
+            {
+                fileSelected = fileLog.SelectCSVFile("fileLogExample");
+                if (fileSelected)
+                    MessageBox.Show("File Select successful");
+                else
+                    MessageBox.Show("File Select failed");
+            }
+            catch(System.IO.IOException ex)
+            {
+                MessageBox.Show(ex.Message, "File Select Failed");
+            }
+        }
+
+        private void button2_Click(object sender, EventArgs e)
+        {
+            if (fileSelected == true)
+            {
+                fileLog.WriteLine("Writing Line " + count++);
+            }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HspGuiSourceV301/GuiDLLs/FileLog/FileLogExample/Form1.resx	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,120 @@
+<?xml version="1.0" encoding="utf-8"?>
+<root>
+  <!-- 
+    Microsoft ResX Schema 
+    
+    Version 2.0
+    
+    The primary goals of this format is to allow a simple XML format 
+    that is mostly human readable. The generation and parsing of the 
+    various data types are done through the TypeConverter classes 
+    associated with the data types.
+    
+    Example:
+    
+    ... ado.net/XML headers & schema ...
+    <resheader name="resmimetype">text/microsoft-resx</resheader>
+    <resheader name="version">2.0</resheader>
+    <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+    <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+    <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
+    <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+    <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+        <value>[base64 mime encoded serialized .NET Framework object]</value>
+    </data>
+    <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+        <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
+        <comment>This is a comment</comment>
+    </data>
+                
+    There are any number of "resheader" rows that contain simple 
+    name/value pairs.
+    
+    Each data row contains a name, and value. The row also contains a 
+    type or mimetype. Type corresponds to a .NET class that support 
+    text/value conversion through the TypeConverter architecture. 
+    Classes that don't support this are serialized and stored with the 
+    mimetype set.
+    
+    The mimetype is used for serialized objects, and tells the 
+    ResXResourceReader how to depersist the object. This is currently not 
+    extensible. For a given mimetype the value must be set accordingly:
+    
+    Note - application/x-microsoft.net.object.binary.base64 is the format 
+    that the ResXResourceWriter will generate, however the reader can 
+    read any of the formats listed below.
+    
+    mimetype: application/x-microsoft.net.object.binary.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
+            : and then encoded with base64 encoding.
+    
+    mimetype: application/x-microsoft.net.object.soap.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+            : and then encoded with base64 encoding.
+
+    mimetype: application/x-microsoft.net.object.bytearray.base64
+    value   : The object must be serialized into a byte array 
+            : using a System.ComponentModel.TypeConverter
+            : and then encoded with base64 encoding.
+    -->
+  <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+    <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
+    <xsd:element name="root" msdata:IsDataSet="true">
+      <xsd:complexType>
+        <xsd:choice maxOccurs="unbounded">
+          <xsd:element name="metadata">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" />
+              </xsd:sequence>
+              <xsd:attribute name="name" use="required" type="xsd:string" />
+              <xsd:attribute name="type" type="xsd:string" />
+              <xsd:attribute name="mimetype" type="xsd:string" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="assembly">
+            <xsd:complexType>
+              <xsd:attribute name="alias" type="xsd:string" />
+              <xsd:attribute name="name" type="xsd:string" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="data">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+                <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
+              <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+              <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="resheader">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" />
+            </xsd:complexType>
+          </xsd:element>
+        </xsd:choice>
+      </xsd:complexType>
+    </xsd:element>
+  </xsd:schema>
+  <resheader name="resmimetype">
+    <value>text/microsoft-resx</value>
+  </resheader>
+  <resheader name="version">
+    <value>2.0</value>
+  </resheader>
+  <resheader name="reader">
+    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <resheader name="writer">
+    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+</root>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HspGuiSourceV301/GuiDLLs/FileLog/FileLogExample/Program.cs	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,22 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading.Tasks;
+using System.Windows.Forms;
+
+namespace FileLogExample
+{
+    static class Program
+    {
+        /// <summary>
+        /// The main entry point for the application.
+        /// </summary>
+        [STAThread]
+        static void Main()
+        {
+            Application.EnableVisualStyles();
+            Application.SetCompatibleTextRenderingDefault(false);
+            Application.Run(new Form1());
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HspGuiSourceV301/GuiDLLs/FileLog/FileLogExample/Properties/AssemblyInfo.cs	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,36 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following 
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("FileLogExample")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("Maxim Integrated Products")]
+[assembly: AssemblyProduct("FileLogExample")]
+[assembly: AssemblyCopyright("Copyright © Maxim Integrated Products 2016")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible 
+// to COM components.  If you need to access a type in this assembly from 
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("7a6ec139-3e1b-48b6-85b7-f1b03c287a8f")]
+
+// Version information for an assembly consists of the following four values:
+//
+//      Major Version
+//      Minor Version 
+//      Build Number
+//      Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers 
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HspGuiSourceV301/GuiDLLs/FileLog/FileLogExample/Properties/Resources.Designer.cs	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,71 @@
+//------------------------------------------------------------------------------
+// <auto-generated>
+//     This code was generated by a tool.
+//     Runtime Version:4.0.30319.18444
+//
+//     Changes to this file may cause incorrect behavior and will be lost if
+//     the code is regenerated.
+// </auto-generated>
+//------------------------------------------------------------------------------
+
+namespace FileLogExample.Properties
+{
+
+
+    /// <summary>
+    ///   A strongly-typed resource class, for looking up localized strings, etc.
+    /// </summary>
+    // This class was auto-generated by the StronglyTypedResourceBuilder
+    // class via a tool like ResGen or Visual Studio.
+    // To add or remove a member, edit your .ResX file then rerun ResGen
+    // with the /str option, or rebuild your VS project.
+    [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+    [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+    internal class Resources
+    {
+
+        private static global::System.Resources.ResourceManager resourceMan;
+
+        private static global::System.Globalization.CultureInfo resourceCulture;
+
+        [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
+        internal Resources()
+        {
+        }
+
+        /// <summary>
+        ///   Returns the cached ResourceManager instance used by this class.
+        /// </summary>
+        [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+        internal static global::System.Resources.ResourceManager ResourceManager
+        {
+            get
+            {
+                if ((resourceMan == null))
+                {
+                    global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("FileLogExample.Properties.Resources", typeof(Resources).Assembly);
+                    resourceMan = temp;
+                }
+                return resourceMan;
+            }
+        }
+
+        /// <summary>
+        ///   Overrides the current thread's CurrentUICulture property for all
+        ///   resource lookups using this strongly typed resource class.
+        /// </summary>
+        [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+        internal static global::System.Globalization.CultureInfo Culture
+        {
+            get
+            {
+                return resourceCulture;
+            }
+            set
+            {
+                resourceCulture = value;
+            }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HspGuiSourceV301/GuiDLLs/FileLog/FileLogExample/Properties/Resources.resx	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,117 @@
+<?xml version="1.0" encoding="utf-8"?>
+<root>
+  <!-- 
+    Microsoft ResX Schema 
+    
+    Version 2.0
+    
+    The primary goals of this format is to allow a simple XML format 
+    that is mostly human readable. The generation and parsing of the 
+    various data types are done through the TypeConverter classes 
+    associated with the data types.
+    
+    Example:
+    
+    ... ado.net/XML headers & schema ...
+    <resheader name="resmimetype">text/microsoft-resx</resheader>
+    <resheader name="version">2.0</resheader>
+    <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+    <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+    <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
+    <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+    <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+        <value>[base64 mime encoded serialized .NET Framework object]</value>
+    </data>
+    <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+        <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
+        <comment>This is a comment</comment>
+    </data>
+                
+    There are any number of "resheader" rows that contain simple 
+    name/value pairs.
+    
+    Each data row contains a name, and value. The row also contains a 
+    type or mimetype. Type corresponds to a .NET class that support 
+    text/value conversion through the TypeConverter architecture. 
+    Classes that don't support this are serialized and stored with the 
+    mimetype set.
+    
+    The mimetype is used for serialized objects, and tells the 
+    ResXResourceReader how to depersist the object. This is currently not 
+    extensible. For a given mimetype the value must be set accordingly:
+    
+    Note - application/x-microsoft.net.object.binary.base64 is the format 
+    that the ResXResourceWriter will generate, however the reader can 
+    read any of the formats listed below.
+    
+    mimetype: application/x-microsoft.net.object.binary.base64
+    value   : The object must be serialized with 
+            : System.Serialization.Formatters.Binary.BinaryFormatter
+            : and then encoded with base64 encoding.
+    
+    mimetype: application/x-microsoft.net.object.soap.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+            : and then encoded with base64 encoding.
+
+    mimetype: application/x-microsoft.net.object.bytearray.base64
+    value   : The object must be serialized into a byte array 
+            : using a System.ComponentModel.TypeConverter
+            : and then encoded with base64 encoding.
+    -->
+  <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+    <xsd:element name="root" msdata:IsDataSet="true">
+      <xsd:complexType>
+        <xsd:choice maxOccurs="unbounded">
+          <xsd:element name="metadata">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" />
+              <xsd:attribute name="type" type="xsd:string" />
+              <xsd:attribute name="mimetype" type="xsd:string" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="assembly">
+            <xsd:complexType>
+              <xsd:attribute name="alias" type="xsd:string" />
+              <xsd:attribute name="name" type="xsd:string" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="data">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+                <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" msdata:Ordinal="1" />
+              <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+              <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="resheader">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" />
+            </xsd:complexType>
+          </xsd:element>
+        </xsd:choice>
+      </xsd:complexType>
+    </xsd:element>
+  </xsd:schema>
+  <resheader name="resmimetype">
+    <value>text/microsoft-resx</value>
+  </resheader>
+  <resheader name="version">
+    <value>2.0</value>
+  </resheader>
+  <resheader name="reader">
+    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <resheader name="writer">
+    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+</root>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HspGuiSourceV301/GuiDLLs/FileLog/FileLogExample/Properties/Settings.Designer.cs	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,30 @@
+//------------------------------------------------------------------------------
+// <auto-generated>
+//     This code was generated by a tool.
+//     Runtime Version:4.0.30319.18444
+//
+//     Changes to this file may cause incorrect behavior and will be lost if
+//     the code is regenerated.
+// </auto-generated>
+//------------------------------------------------------------------------------
+
+namespace FileLogExample.Properties
+{
+
+
+    [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+    [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "11.0.0.0")]
+    internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase
+    {
+
+        private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
+
+        public static Settings Default
+        {
+            get
+            {
+                return defaultInstance;
+            }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HspGuiSourceV301/GuiDLLs/FileLog/FileLogExample/TextCases.txt	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,3 @@
+1. Save in My Documents Folder
+2. Save in folder which user has no permission to write in
+3. Save over existing opened file.
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HspGuiSourceV301/GuiDLLs/MaximGlobal/App.config	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<configuration>
+    <startup> 
+        <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0"/>
+    </startup>
+</configuration>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HspGuiSourceV301/GuiDLLs/MaximGlobal/ErrorEventArgs.cs	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,51 @@
+/*******************************************************************************
+* Copyright (C) 2016 Maxim Integrated Products, Inc., All rights Reserved.
+* 
+* This software is protected by copyright laws of the United States and
+* of foreign countries. This material may also be protected by patent laws
+* and technology transfer regulations of the United States and of foreign
+* countries. This software is furnished under a license agreement and/or a
+* nondisclosure agreement and may only be used or reproduced in accordance
+* with the terms of those agreements. Dissemination of this information to
+* any party or parties not specified in the license agreement and/or
+* nondisclosure agreement is expressly prohibited.
+*
+* The above copyright notice and this permission notice shall be included
+* in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+* OTHER DEALINGS IN THE SOFTWARE.
+*
+* Except as contained in this notice, the name of Maxim Integrated
+* Products, Inc. shall not be used except as stated in the Maxim Integrated
+* Products, Inc. Branding Policy.
+*
+* The mere transfer of this software does not imply any licenses
+* of trade secrets, proprietary technology, copyrights, patents,
+* trademarks, maskwork rights, or any other form of intellectual
+* property whatsoever. Maxim Integrated Products, Inc. retains all
+* ownership rights.
+*******************************************************************************
+*/
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Maxim.Global
+{
+    public class ErrorEventArgs : EventArgs
+    {
+        /// <summary>
+        /// error message
+        /// </summary>
+        public string messageString { get; set; }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HspGuiSourceV301/GuiDLLs/MaximGlobal/Maxim.Global.csproj	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,55 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
+  <PropertyGroup>
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+    <ProjectGuid>{57E4E43C-871B-4113-950E-D649AC6D386A}</ProjectGuid>
+    <OutputType>Library</OutputType>
+    <AppDesignerFolder>Properties</AppDesignerFolder>
+    <RootNamespace>MaximGlobal</RootNamespace>
+    <AssemblyName>MaximGlobal</AssemblyName>
+    <TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
+    <FileAlignment>512</FileAlignment>
+    <TargetFrameworkProfile />
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+    <PlatformTarget>AnyCPU</PlatformTarget>
+    <DebugSymbols>true</DebugSymbols>
+    <DebugType>full</DebugType>
+    <Optimize>false</Optimize>
+    <OutputPath>bin\Debug\</OutputPath>
+    <DefineConstants>DEBUG;TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+    <PlatformTarget>AnyCPU</PlatformTarget>
+    <DebugType>pdbonly</DebugType>
+    <Optimize>true</Optimize>
+    <OutputPath>bin\Release\</OutputPath>
+    <DefineConstants>TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+  </PropertyGroup>
+  <PropertyGroup>
+    <StartupObject />
+  </PropertyGroup>
+  <ItemGroup>
+    <None Include="App.config" />
+  </ItemGroup>
+  <ItemGroup>
+    <Compile Include="ErrorEventArgs.cs" />
+  </ItemGroup>
+  <ItemGroup>
+    <Reference Include="System" />
+  </ItemGroup>
+  <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+  <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 
+       Other similar extension points exist, see Microsoft.Common.targets.
+  <Target Name="BeforeBuild">
+  </Target>
+  <Target Name="AfterBuild">
+  </Target>
+  -->
+</Project>
\ No newline at end of file
Binary file HspGuiSourceV301/GuiDLLs/MaximStyle/MaximStyle.dll has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HspGuiSourceV301/GuiDLLs/RPCSupport/DataLogging/DataLogging.cs	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,1014 @@
+/*******************************************************************************
+* Copyright (C) 2016 Maxim Integrated Products, Inc., All rights Reserved.
+* 
+* This software is protected by copyright laws of the United States and
+* of foreign countries. This material may also be protected by patent laws
+* and technology transfer regulations of the United States and of foreign
+* countries. This software is furnished under a license agreement and/or a
+* nondisclosure agreement and may only be used or reproduced in accordance
+* with the terms of those agreements. Dissemination of this information to
+* any party or parties not specified in the license agreement and/or
+* nondisclosure agreement is expressly prohibited.
+*
+* The above copyright notice and this permission notice shall be included
+* in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+* OTHER DEALINGS IN THE SOFTWARE.
+*
+* Except as contained in this notice, the name of Maxim Integrated
+* Products, Inc. shall not be used except as stated in the Maxim Integrated
+* Products, Inc. Branding Policy.
+*
+* The mere transfer of this software does not imply any licenses
+* of trade secrets, proprietary technology, copyrights, patents,
+* trademarks, maskwork rights, or any other form of intellectual
+* property whatsoever. Maxim Integrated Products, Inc. retains all
+* ownership rights.
+*******************************************************************************
+*/
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using RPCSupport.Devices;
+using System.Globalization;
+using System.Runtime.Serialization.Formatters.Binary;
+using System.IO;
+using System.Threading;
+
+namespace RPCSupport.DataLogging
+{
+    public class DataLogging : ClientDevice
+    {
+
+        public class cParametersEcg : cDeviceMethodParameters
+        {
+            public cParametersEcg(String className, String methodName) : base(className, methodName) { }
+            public int En_ecg;
+            public int Openp;
+            public int Openn;
+            public int Pol;
+            public int Calp_sel;
+            public int Caln_sel;
+            public int E_fit;
+            public int Rate;
+            public int Gain;
+            public int Dhpf;
+            public int Dlpf;
+
+            public override void AssignByIntArray(int[] intArray)
+            {
+                int i = 0;
+                En_ecg = intArray[i++];
+                Openp = intArray[i++];
+                Openn = intArray[i++];
+                Pol = intArray[i++];
+                Calp_sel = intArray[i++];
+                Caln_sel = intArray[i++];
+                E_fit = intArray[i++];
+                Rate = intArray[i++];
+                Gain = intArray[i++];
+                Dhpf = intArray[i++];
+                Dlpf = intArray[i++];
+            }
+            public override int[] ToIntArray()
+            {
+                int i = 0;
+                List<int> intArray = new List<int>();
+                intArray.Add(En_ecg);
+                intArray.Add(Openp);
+                intArray.Add(Openn);
+                intArray.Add(Pol);
+                intArray.Add(Calp_sel);
+                intArray.Add(Caln_sel);
+                intArray.Add(E_fit);
+                intArray.Add(Rate);
+                intArray.Add(Gain);
+                intArray.Add(Dhpf);
+                intArray.Add(Dlpf);
+                return intArray.ToArray();
+            }
+
+            public void AssignByValue(
+                int En_ecg,
+                int Openp,
+                int Openn,
+                int Pol,
+                int Calp_sel,
+                int Caln_sel,
+                int E_fit,
+                int Rate,
+                int Gain,
+                int Dhpf,
+                int Dlpf)
+            {
+                this.En_ecg = En_ecg;
+                this.Openp = Openp;
+                this.Openn = Openn;
+                this.Pol = Pol;
+                this.Calp_sel = Calp_sel;
+                this.Caln_sel = Caln_sel;
+                this.E_fit = E_fit;
+                this.Rate = Rate;
+                this.Gain = Gain;
+                this.Dhpf = Dhpf;
+                this.Dlpf = Dlpf;
+            }
+        }
+//        public cParametersEcg ParametersMAX30001Ecg = new cParametersEcg();
+        
+        public class cParametersBioz : cDeviceMethodParameters
+        {
+            public cParametersBioz(String className, String methodName) : base(className, methodName) { }
+            public int En_bioz;
+            public int Openp;
+            public int Openn;
+            public int Calp_sel;
+            public int Caln_sel;
+            public int CG_mode;
+            public int B_fit;
+            public int Rate;
+            public int Ahpf;
+            public int Ext_rbias;
+            public int Gain;
+            public int Dhpf;
+            public int Dlpf;
+            public int Fcgen;
+            public int Cgmon;
+            public int Cgmag;
+            public int Phoff;
+            public override void AssignByIntArray(int[] intArray)
+            {
+                int i = 0;
+                En_bioz = intArray[i++];
+                Openp = intArray[i++];
+                Openn = intArray[i++];
+                Calp_sel = intArray[i++];
+                Caln_sel = intArray[i++];
+                CG_mode = intArray[i++];
+                B_fit = intArray[i++];
+                Rate = intArray[i++];
+                Ahpf = intArray[i++];
+                Ext_rbias = intArray[i++];
+                Gain = intArray[i++];
+                Dhpf = intArray[i++];
+                Dlpf = intArray[i++];
+                Fcgen = intArray[i++];
+                Cgmon = intArray[i++];
+                Cgmag = intArray[i++];
+                Phoff = intArray[i++];
+            }
+
+            public override int[] ToIntArray()
+            {
+                int i = 0;
+                List<int> intArray = new List<int>();
+                intArray.Add(En_bioz);
+                intArray.Add(Openp);
+                intArray.Add(Openn);
+                intArray.Add(Calp_sel);
+                intArray.Add(Caln_sel);
+                intArray.Add(CG_mode);
+                intArray.Add(B_fit);
+                intArray.Add(Rate);
+                intArray.Add(Ahpf);
+                intArray.Add(Ext_rbias);
+                intArray.Add(Gain);
+                intArray.Add(Dhpf);
+                intArray.Add(Dlpf);
+                intArray.Add(Fcgen);
+                intArray.Add(Cgmon);
+                intArray.Add(Cgmag);
+                intArray.Add(Phoff);
+                return intArray.ToArray();
+            }
+
+            public void AssignByValue(
+                int En_bioz,
+                int Openp,
+                int Openn,
+                int Calp_sel,
+                int Caln_sel,
+                int CG_mode,
+                int B_fit,
+                int Rate,
+                int Ahpf,
+                int Ext_rbias,
+                int Gain,
+                int Dhpf,
+                int Dlpf,
+                int Fcgen,
+                int Cgmon,
+                int Cgmag,
+                int Phoff)
+            {
+                this.En_bioz = En_bioz;
+                this.Openp = Openp;
+                this.Openn = Openn;
+                this.Calp_sel = Calp_sel;
+                this.Caln_sel = Caln_sel;
+                this.CG_mode = CG_mode;
+                this.B_fit = B_fit;
+                this.Rate = Rate;
+                this.Ahpf = Ahpf;
+                this.Ext_rbias = Ext_rbias;
+                this.Gain = Gain;
+                this.Dhpf = Dhpf;
+                this.Dlpf = Dlpf;
+                this.Fcgen = Fcgen;
+                this.Cgmon = Cgmon;
+                this.Cgmag = Cgmag;
+                this.Phoff = Phoff;
+            }
+        }
+        //public cParametersBioz ParametersMAX30001Bioz = new cParametersBioz();
+
+        public class cParametersRtoR : cDeviceMethodParameters
+        {
+            public cParametersRtoR(String className, String methodName) : base(className, methodName) { }
+            public int En_rtor;
+            public int Wndw;
+            public int Gain;
+            public int Pavg;
+            public int Ptsf;
+            public int Hoff;
+            public int Ravg;
+            public int Rhsf;
+            public int Clr_rrint;
+            public override void AssignByIntArray(int[] intArray)
+            {
+                int i = 0;
+                En_rtor = intArray[i++];
+                Wndw = intArray[i++];
+                Gain = intArray[i++];
+                Pavg = intArray[i++];
+                Ptsf = intArray[i++];
+                Hoff = intArray[i++];
+                Ravg = intArray[i++];
+                Rhsf = intArray[i++];
+                Clr_rrint = intArray[i++];
+            }
+
+            public override int[] ToIntArray()
+            {
+                int i = 0;
+                List<int> intArray = new List<int>();
+                intArray.Add(En_rtor);
+                intArray.Add(Wndw);
+                intArray.Add(Gain);
+                intArray.Add(Pavg);
+                intArray.Add(Ptsf);
+                intArray.Add(Hoff);
+                intArray.Add(Ravg);
+                intArray.Add(Rhsf);
+                intArray.Add(Clr_rrint);
+                return intArray.ToArray();
+            }
+
+            public void AssignByValue(
+                int En_rtor,
+                int Wndw,
+                int Gain,
+                int Pavg,
+                int Ptsf,
+                int Hoff,
+                int Ravg,
+                int Rhsf,
+                int Clr_rrint)
+            {
+                this.En_rtor = En_rtor;
+                this.Wndw = Wndw;
+                this.Gain = Gain;
+                this.Pavg = Pavg;
+                this.Ptsf = Ptsf;
+                this.Hoff = Hoff;
+                this.Ravg = Ravg;
+                this.Rhsf = Rhsf;
+                this.Clr_rrint = Clr_rrint;
+            }
+        }
+        //public cParametersRtoR ParametersMAX30001RtoR = new cParametersRtoR();
+
+        public class cParametersPace : cDeviceMethodParameters
+        {
+            public cParametersPace(String className, String methodName) : base(className, methodName) { }
+            public int En_pace;
+            public int Clr_pedge;
+            public int Pol;
+            public int Gn_diff_off;
+            public int Gain;
+            public int Aout_lbw;
+            public int Aout;
+            public int Dacp;
+            public int Dacn;
+            public override void AssignByIntArray(int[] intArray)
+            {
+                int i = 0;
+                En_pace = intArray[i++];
+                Clr_pedge = intArray[i++];
+                Pol = intArray[i++];
+                Gn_diff_off = intArray[i++];
+                Gain = intArray[i++];
+                Aout_lbw = intArray[i++];
+                Aout = intArray[i++];
+                Dacp = intArray[i++];
+                Dacn = intArray[i++];
+            }
+
+            public override int[] ToIntArray()
+            {
+                int i = 0;
+                List<int> intArray = new List<int>();
+                intArray.Add(En_pace);
+                intArray.Add(Clr_pedge);
+                intArray.Add(Pol);
+                intArray.Add(Gn_diff_off);
+                intArray.Add(Gain);
+                intArray.Add(Aout_lbw);
+                intArray.Add(Aout);
+                intArray.Add(Dacp);
+                intArray.Add(Dacn);
+                return intArray.ToArray();
+            }
+
+            public void AssignByValue(
+                int En_pace,
+                int Clr_pedge,
+                int Pol,
+                int Gn_diff_off,
+                int Gain,
+                int Aout_lbw,
+                int Aout,
+                int Dacp,
+                int Dacn)
+            {
+                this.En_pace = En_pace;
+                this.Clr_pedge = Clr_pedge;
+                this.Pol = Pol;
+                this.Gn_diff_off = Gn_diff_off;
+                this.Gain = Gain;
+                this.Aout = Aout;
+                this.Dacp = Dacp;
+                this.Dacn = Dacn;
+            }
+        }
+
+        public class cParametersCal : cDeviceMethodParameters
+        {
+            public cParametersCal(String className, String methodName) : base(className, methodName) { }
+            public int parameter1;
+            public int parameter2;
+            public int parameter3;
+            public int parameter4;
+            public int parameter5;
+            public int parameter6;
+            public override void AssignByIntArray(int[] intArray)
+            {
+                int i = 0;
+                parameter1 = intArray[i++];
+                parameter2 = intArray[i++];
+                parameter3 = intArray[i++];
+                parameter4 = intArray[i++];
+                parameter5 = intArray[i++];
+                parameter6 = intArray[i++];
+            }
+
+            public override int[] ToIntArray()
+            {
+                int i = 0;
+                List<int> intArray = new List<int>();
+                intArray.Add(parameter1);
+                intArray.Add(parameter2);
+                intArray.Add(parameter3);
+                intArray.Add(parameter4);
+                intArray.Add(parameter5);
+                intArray.Add(parameter6);
+                return intArray.ToArray();
+            }
+
+            public void AssignByValue(
+                int parameter1,
+                int parameter2,
+                int parameter3,
+                int parameter4,
+                int parameter5,
+                int parameter6
+                )
+
+            {
+                this.parameter1 = parameter1;
+                this.parameter2 = parameter2;
+                this.parameter3 = parameter3;
+                this.parameter4 = parameter4;
+                this.parameter5 = parameter5;
+                this.parameter6 = parameter6;
+            }
+        }
+       
+        //        public cParametersPace ParametersMAX30001Pace = new cParametersPace();
+        public class cParametersTemp : cDeviceMethodParameters
+        {
+            public cParametersTemp(String className, String methodName, int deviceNumber) : base(className, methodName) { this.deviceNumber = deviceNumber; }
+            public int sampleTime;  // seconds
+            private int deviceNumber;
+            public override void AssignByIntArray(int[] intArray)
+            {
+                int i = 0;
+                sampleTime = intArray[i++];
+            }
+
+            public override int[] ToIntArray()
+            {
+                int i = 0;
+                List<int> intArray = new List<int>();
+                intArray.Add(sampleTime);
+                return intArray.ToArray();
+            }
+        }
+//        public cParametersTemp1 ParametersMAX31725_1 = new cParametersTemp1();
+
+//        public cParametersTemp2 ParametersMAX31725_2 = new cParametersTemp2();
+
+        public class cParametersPressure : cDeviceMethodParameters
+        {
+            public cParametersPressure(String className, String methodName) : base(className, methodName) { }
+            public int sampleTime;  // seconds
+            public override void AssignByIntArray(int[] intArray)
+            {
+                int i = 0;
+                sampleTime = intArray[i++];
+            }
+
+            public override int[] ToIntArray()
+            {
+                int i = 0;
+                List<int> intArray = new List<int>();
+                intArray.Add(sampleTime);
+                return intArray.ToArray();
+            }
+        }
+//        public cParametersPressure ParametersBMP280 = new cParametersPressure();
+
+        public class cParametersAccel : cDeviceMethodParameters
+        {
+            public cParametersAccel(String className, String methodName) : base(className, methodName) { fifoDepth = 1; }
+            public int sampleRate;  // Hz
+            public int fifoDepth; 
+            public override void AssignByIntArray(int[] intArray)
+            {
+                int i = 0;
+                sampleRate = intArray[i++];
+                fifoDepth = intArray[i++];
+            }
+
+            public override int[] ToIntArray()
+            {
+                int i = 0;
+                List<int> intArray = new List<int>();
+                intArray.Add(sampleRate);
+                intArray.Add(fifoDepth);
+                return intArray.ToArray();
+            }
+        }
+//        public cParametersAccel ParametersLIS2DH = new cParametersAccel();
+
+        public class cParameterOpticalSpO2 : cDeviceMethodParameters
+        {
+            public cParameterOpticalSpO2(String className, String methodName) : base(className, methodName) { }
+            public int fifo_waterlevel_mark;
+            public int sample_avg;
+            public int sample_rate;
+            public int pulse_width;
+            public int red_led_current;
+            public int ir_led_current;
+            public override void AssignByIntArray(int[] intArray)
+            {
+                int i = 0;
+                fifo_waterlevel_mark = intArray[i++];
+                sample_avg = intArray[i++];
+                sample_rate = intArray[i++];
+                pulse_width = intArray[i++];
+                red_led_current = intArray[i++];
+                ir_led_current = intArray[i++];
+            }
+
+            public override int[] ToIntArray()
+            {
+                int i = 0;
+                List<int> intArray = new List<int>();
+                intArray.Add(fifo_waterlevel_mark);
+                intArray.Add(sample_avg);
+                intArray.Add(sample_rate);
+                intArray.Add(pulse_width);
+                intArray.Add(red_led_current);
+                intArray.Add(ir_led_current);
+                return intArray.ToArray();
+            }
+        }
+//        public cParameterOpticalSpO2 ParameterMAX30101SpO2 = new cParameterOpticalSpO2();
+
+        public class cParameterOpticalHR : cDeviceMethodParameters
+        {
+            public cParameterOpticalHR(String className, String methodName) : base(className, methodName) { }
+            public int fifo_waterlevel_mark;
+            public int sample_avg;
+            public int sample_rate;
+            public int pulse_width;
+            public int red_led_current;
+            public override void AssignByIntArray(int[] intArray)
+            {
+                int i = 0;
+                fifo_waterlevel_mark = intArray[i++];
+                sample_avg = intArray[i++];
+                sample_rate = intArray[i++];
+                pulse_width = intArray[i++];
+                red_led_current = intArray[i++];
+            }
+
+            public override int[] ToIntArray()
+            {
+                int i = 0;
+                List<int> intArray = new List<int>();
+                intArray.Add(fifo_waterlevel_mark);
+                intArray.Add(sample_avg);
+                intArray.Add(sample_rate);
+                intArray.Add(pulse_width);
+                intArray.Add(red_led_current);
+                return intArray.ToArray();
+            }
+        }
+//        public cParameterOpticalHR ParameterMAX30101HR = new cParameterOpticalHR();
+
+        public class cParameterOpticalMulti : cDeviceMethodParameters
+        {
+            public cParameterOpticalMulti(String className, String methodName) : base(className, methodName) { }
+            public int fifo_waterlevel_mark;
+            public int sample_avg;
+            public int sample_rate;
+            public int pulse_width;
+            public int red_led_current;
+            public int ir_led_current;
+            public int green_led_current;
+            public int slot_1;
+            public int slot_2;
+            public int slot_3;
+            public int slot_4;
+            public override void AssignByIntArray(int[] intArray)
+            {
+                int i = 0;
+                fifo_waterlevel_mark = intArray[i++];
+                sample_avg = intArray[i++];
+                sample_rate = intArray[i++];
+                pulse_width = intArray[i++];
+                red_led_current = intArray[i++];
+                ir_led_current = intArray[i++];
+                green_led_current = intArray[i++];
+                slot_1 = intArray[i++];
+                slot_2 = intArray[i++];
+                slot_3 = intArray[i++];
+                slot_4 = intArray[i++];
+            }
+
+            public override int[] ToIntArray()
+            {
+                int i = 0;
+                List<int> intArray = new List<int>();
+                intArray.Add(fifo_waterlevel_mark);
+                intArray.Add(sample_avg);
+                intArray.Add(sample_rate);
+                intArray.Add(pulse_width);
+                intArray.Add(red_led_current);
+                intArray.Add(ir_led_current);
+                intArray.Add(green_led_current);
+                intArray.Add(slot_1);
+                intArray.Add(slot_2);
+                intArray.Add(slot_3);
+                intArray.Add(slot_4);
+                return intArray.ToArray();
+            }
+        }
+
+        public class cParametersRbiasFmstr : cDeviceMethodParameters
+        {
+            public cParametersRbiasFmstr(String className, String methodName) : base(className, methodName) { }
+
+            public int en_rbias;
+            public int rbias;
+            public int rbiasp;
+            public int rbiasn;
+            public int fmstr;
+
+            public override void AssignByIntArray(int[] intArray)
+            {
+                int i = 0;
+                en_rbias = intArray[i++];
+                rbias = intArray[i++];
+                rbiasp = intArray[i++];
+                rbiasn = intArray[i++];
+                fmstr = intArray[i++];
+            }
+
+            public override int[] ToIntArray()
+            {
+                int i = 0;
+
+                List<int> intArray = new List<int>();
+                intArray.Add(en_rbias);
+                intArray.Add(rbias);
+                intArray.Add(rbiasp);
+                intArray.Add(rbiasn);
+                intArray.Add(fmstr);
+
+                return intArray.ToArray();
+            }
+
+        }
+
+        //PreCommand
+        public class cRawRPCCommand : cDeviceMethodParameters
+        {
+           public String cmdString;
+           public cRawRPCCommand(String className, String methodName) : base(className, methodName) { }
+           public void Define(String str)
+           {
+               String inStr = str.Trim();
+               if (inStr.CompareTo("null") == 0) str = "";
+               cmdString = str;
+           }
+           public override void AssignByIntArray(int[] intArray)
+            {
+                throw new NotImplementedException();
+            }
+
+            public override int[] ToIntArray()
+            {
+                throw new NotImplementedException();
+            }
+            public override String GenerateRpcCommandString()
+            {
+                String str = cmdString;
+                if (String.IsNullOrWhiteSpace(cmdString)) str = "null";
+                String cmd = String.Format("\"{0}\"", str);
+                //Console.WriteLine("cmd string  = '" + cmd + "'");
+                //Console.WriteLine("cmd string length = " + cmd.Length.ToString());
+                return cmd;
+            }
+        }
+        public cParametersEcg MAX30001_Ecg = new cParametersEcg("MAX30001", "ECG_InitStart");
+        public cParametersBioz MAX30001_Bioz = new cParametersBioz("MAX30001", "BIOZ_InitStart");
+        public cParametersRtoR MAX30001_RtoR = new cParametersRtoR("MAX30001", "RtoR_InitStart");
+        public cParametersPace MAX30001_Pace = new cParametersPace("MAX30001", "PACE_InitStart");
+        public cParametersCal MAX30001_Cal = new cParametersCal("MAX30001", "CAL_InitStart");
+        public cRawRPCCommand MAX30001_Rbias = new cRawRPCCommand("", "");
+        public cParametersRbiasFmstr MAX30001_Rbias_Fmstr = new cParametersRbiasFmstr("MAX30001", "Rbias_FMSTR_Init");
+        public cParametersTemp MAX31725_1 = new cParametersTemp("MAX30205_1", "InitStart", 1);
+        public cParametersTemp MAX31725_2 = new cParametersTemp("MAX30205_2", "InitStart", 2);
+        public cParametersPressure BMP280 = new cParametersPressure("BMP280", "InitStart");
+        public cParametersAccel LIS2DH = new cParametersAccel("LIS2DH", "InitStart");
+        public cParameterOpticalSpO2 MAX30101_SpO2 = new cParameterOpticalSpO2("MAX30101", "SpO2mode_InitStart");
+        public cParameterOpticalHR MAX30101_HR = new cParameterOpticalHR("MAX30101", "HRmode_InitStart");
+        public cParameterOpticalMulti MAX30101_Multi = new cParameterOpticalMulti("MAX30101", "Multimode_InitStart");
+        public cRawRPCCommand PreCommand = new cRawRPCCommand("", "");
+        public cRawRPCCommand PostCommand = new cRawRPCCommand("", "");
+
+        const string CLASSNAME = "Logging";
+        public DataLogging(RPCClient client)
+            : base(client)
+        {
+            InitRpcCommandList();
+        }
+        /*
+        public void StartLoggingUsb()
+        {
+            string reply;
+            reply = Call(CLASSNAME, "StartLoggingUsb");
+        }
+        */
+        private void InitStreaming()
+        {
+            client.pipeline.Discard();
+            client.streaming.Init(client.pipeline);
+            client.streaming.Start();
+            //Call(CLASSNAME, "StreamTest");
+            //CallNoReply(CLASSNAME, "StreamTest");
+        }
+
+        public void StartStreaming()
+        {
+            client.pipeline.Discard();
+            InitStreaming();
+            CallNoReply(CLASSNAME, "StartLoggingUsb");
+            //Call(CLASSNAME, "StartTest");
+        }
+
+        public void StopStreaming()
+        {
+            StopStreaming(true);
+        }
+
+        public void StopStreaming(bool connected)
+        {
+            //if (connected)
+                client.pipeline.SendSingleByte(' ');
+
+            client.streaming.Stop();
+
+            //if (connected)
+            {
+                client.pipeline.Discard();
+                Thread.Sleep(500);
+                client.pipeline.Discard();
+            }
+        }
+
+        public void MissionRead()
+        {
+            int val;
+            string reply;
+
+            reply = Call(CLASSNAME, "ReadMission");
+            reply = reply.Trim(new char[] { '\n', '\r', ' ', ':' });
+            String[] cmds = reply.Split(new char[] { ':' });
+            int i = 1;
+            foreach (String str in cmds)
+            {
+                String cmd = str.Trim();
+                if (!String.IsNullOrEmpty(cmd))
+                {
+                    Console.WriteLine(i.ToString() + ": " + cmd);
+                    i++;
+                }
+            }
+            //reply = Call(CLASSNAME, "ReadMission");
+            //reply = "/MAX30001/ECG_InitStart 01 01 01 00 02 03 1F 00 02 00 01\r\n/BMP280/InitStart 01\r\n";
+
+            // clear where it exists in mission flag
+            foreach (cDeviceMethodParameters cmd in rpcCommandList)
+            {
+                cmd.ClearExistsInDeviceMission();
+            }
+            PreCommand.ClearExistsInDeviceMission();
+            PostCommand.ClearExistsInDeviceMission();
+            //reply[0]
+            ParseRPCReadSequence(reply);
+        }
+
+        public string[] MissionStrings()
+        {
+            string reply;
+
+            reply = Call(CLASSNAME, "ReadMission");
+            reply = reply.Trim(new char[] { '\n', '\r', ' ', ':' });
+            string[] cmds = reply.Split(new string[] { ": " }, StringSplitOptions.RemoveEmptyEntries);
+
+            return cmds;
+        }
+
+        int debugMissionCmdCount;
+        public void MissionStartDefinition()
+        {
+            string reply;
+            reply = Call(CLASSNAME, "StartMissionDefine");
+            debugMissionCmdCount = 0;
+        }
+        public void MissionAppend(cDeviceMethodParameters device)
+        {
+            String cmd;
+            cmd = device.GenerateRpcCommandString();
+            Call(CLASSNAME, "AppendMissionCmd", cmd);
+            debugMissionCmdCount++;
+            Console.WriteLine(debugMissionCmdCount.ToString() + ": " + cmd);
+        }
+        public void MissionAppend(String cmdStr)
+        {
+            Call(CLASSNAME, "AppendMissionCmd", "\"" + cmdStr + "\"");
+            debugMissionCmdCount++;
+            Console.WriteLine(debugMissionCmdCount.ToString() + ": " + cmdStr);
+        }
+        public void MissionWrite()
+        {
+            int val;
+            string cmd;
+            string reply;
+            StringBuilder sbTest = new StringBuilder();
+
+            reply = Call(CLASSNAME, "EndMissionDefine");
+            reply = Call(CLASSNAME, "WriteMission");
+             //reply = Call(CLASSNAME, "ReadReg", addr.ToString("X2"));
+            //int.TryParse(reply, NumberStyles.HexNumber, CultureInfo.CurrentCulture, out val);
+//            Console.WriteLine(sbTest.ToString());
+        }
+
+        // "/MAX30001/ECG_InitStart 01 01 01 00 02 03 1F 00 02 00 01/r/n/BMP280/InitStart 01 01 01 00 02 03 1F 00 02 00 01/r/n"
+        private void ParseRPCReadSequence(String cmds)
+        {
+            int count = 0;
+            cmds = cmds.Trim(new char[] { '\n', '\r', ' ', ':' });
+            String[] cmdStrings = cmds.Split(new char[] { ':' });
+            int lastCount = cmdStrings.Length - 1;
+            foreach (String cmd in cmdStrings)
+            {
+                if (count == 0)
+                {
+                    PreCommand.Define(cmd);
+                    PreCommand.existsInDeviceMission = true;
+                }
+                else
+                    if (count == lastCount)
+                    {
+                        PostCommand.Define(cmd);
+                        PostCommand.existsInDeviceMission = true;
+                    }
+                    else
+                        ProcessRPCCmd(cmd);
+                count++;
+            }
+        }
+
+        List<cDeviceMethodParameters> rpcCommandList = new List<cDeviceMethodParameters>();
+
+        private void InitRpcCommandList()
+        {
+            rpcCommandList.Add(MAX30001_Ecg);
+            rpcCommandList.Add(MAX30001_Bioz);
+            rpcCommandList.Add(MAX30001_RtoR);
+            rpcCommandList.Add(MAX30001_Pace);
+            rpcCommandList.Add(MAX30001_Cal);
+            rpcCommandList.Add(MAX31725_1);
+            rpcCommandList.Add(MAX31725_2);
+            rpcCommandList.Add(BMP280);
+            rpcCommandList.Add(LIS2DH);
+            rpcCommandList.Add(MAX30101_SpO2);
+            rpcCommandList.Add(MAX30101_HR);
+            rpcCommandList.Add(MAX30101_Multi);
+            rpcCommandList.Add(MAX30001_Rbias_Fmstr);
+        }
+
+        private void ProcessRPCCmd(String str)
+        {
+            if (String.IsNullOrEmpty(str)) return;
+            String trimmed = str.Trim(new char[] { '\r', '\n', ' ' });
+            if (String.IsNullOrEmpty(trimmed)) return;
+            if (trimmed[0] != '/') return;
+            String trimmed2 = trimmed.Trim(new char[] { '\r', '\n', '/', ' ' });
+            String[] parts = trimmed2.Split(new char[] { '/' });
+            String className = parts[0];
+            String methodNameParameters = parts[1];
+            String methodName = methodNameParameters.Substring(0,methodNameParameters.IndexOf(' '));
+            String parameters = methodNameParameters.Substring(methodNameParameters.IndexOf(' ')).Trim();
+            foreach (cDeviceMethodParameters cmd in rpcCommandList)
+            {
+                if (cmd.AssignIfMatch(className, methodName, parameters) == true) break;
+            }
+        }
+
+        private int[] ParseHexString(String hexStr)
+        {
+            int val;
+            List<int> intList = new List<int>();
+            String[] strings = hexStr.Split(new char[] { ' ' });
+            foreach (String str in strings)
+            {
+                if (int.TryParse(str, NumberStyles.HexNumber, CultureInfo.CurrentCulture, out val))
+                {
+                    intList.Add(val);
+                }
+                else
+                {
+                    throw new Exception(String.Format("Error In hex string \"{0}\" in \"{1}\"", str, hexStr));
+                }
+            }
+            return intList.ToArray();
+        }
+
+        public void EraseMission()
+        {
+            int val;
+            string cmd;
+            string reply;
+
+            reply = Call(CLASSNAME, "EraseMission");
+        }
+
+        public void TestMission()
+        {
+            int val;
+            string cmd;
+            string reply;
+
+            reply = Call(CLASSNAME, "TestStartMission");
+        }
+
+        public void TestWriteLog()
+        {
+            throw new NotImplementedException();
+        }
+
+        public void TestReadLog()
+        {
+            throw new NotImplementedException();
+        }
+
+        public void TestBulkErase()
+        {
+            throw new NotImplementedException();
+        }
+
+        public void TestLogSectorsErase()
+        {
+            throw new NotImplementedException();
+        }
+
+        public string ReadPageToString(int page, out bool allOnes)
+        {
+            String returnStr = "";
+            returnStr = CallBinary("S25FS512", "ReadPagesBinary", out allOnes, new String[] { page.ToString("X2"), page.ToString("X2") });
+            return returnStr;
+        }
+
+        public void EraseWrittenSectors()
+        {
+            int val;
+            string cmd;
+            string reply;
+
+            reply = Call(CLASSNAME, "EraseWrittenSectors");
+        }
+    }
+
+    public abstract class cDeviceMethodParameters 
+    {
+        public String className;
+        public String methodName;
+        public abstract void AssignByIntArray(int[] intArray);
+        public abstract int[] ToIntArray();
+        public bool existsInDeviceMission;
+        public bool IsExistsInDeviceMission()
+        {
+            return existsInDeviceMission;
+        }
+        public void ClearExistsInDeviceMission()
+        {
+            existsInDeviceMission = false;
+        }
+        public String ParametersToString()
+        {
+            StringBuilder sb = new StringBuilder();
+            int[] intArray = ToIntArray();
+            foreach (int val in intArray)
+            {
+                sb.Append(val.ToString("X2") + " ");
+            }
+            return sb.ToString().Trim(new char[] { ' ', ',' });
+        }
+        public virtual String GenerateRpcCommandString()
+        {
+            String cmd = String.Format("\"/{0}/{1} {2}\"", className, methodName, ParametersToString());
+            //Console.WriteLine("cmd string  = '" + cmd + "'");
+            //Console.WriteLine("cmd string length = " + cmd.Length.ToString());
+            return cmd;
+        }
+        public cDeviceMethodParameters(String className, String methodName)
+            {
+                existsInDeviceMission = false;
+                this.className = className;
+                this.methodName = methodName;
+            }
+        public bool AssignIfMatch(String className, String methodName, String parameterStr)
+        {
+            bool match = false;
+            if (this.className.Equals(className) && this.methodName.Equals(methodName))
+            {
+                match = true;
+                existsInDeviceMission = true;
+                AssignByIntArray(ParseHexString(parameterStr));
+            }
+            return match;
+        }
+        private int[] ParseHexString(String hexStr)
+        {
+            int val;
+            List<int> intList = new List<int>();
+            String[] strings = hexStr.Split(new char[] { ' ' });
+            foreach (String str in strings)
+            {
+                if (int.TryParse(str, NumberStyles.HexNumber, CultureInfo.CurrentCulture, out val))
+                {
+                    intList.Add(val);
+                }
+                else
+                {
+                    throw new Exception(String.Format("Error In hex string \"{0}\" in \"{1}\"", str, hexStr));
+                }
+            }
+            return intList.ToArray();
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HspGuiSourceV301/GuiDLLs/RPCSupport/DataLogging/StreamDataLog.cs	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,79 @@
+/*******************************************************************************
+* Copyright (C) 2016 Maxim Integrated Products, Inc., All rights Reserved.
+* 
+* This software is protected by copyright laws of the United States and
+* of foreign countries. This material may also be protected by patent laws
+* and technology transfer regulations of the United States and of foreign
+* countries. This software is furnished under a license agreement and/or a
+* nondisclosure agreement and may only be used or reproduced in accordance
+* with the terms of those agreements. Dissemination of this information to
+* any party or parties not specified in the license agreement and/or
+* nondisclosure agreement is expressly prohibited.
+*
+* The above copyright notice and this permission notice shall be included
+* in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+* OTHER DEALINGS IN THE SOFTWARE.
+*
+* Except as contained in this notice, the name of Maxim Integrated
+* Products, Inc. shall not be used except as stated in the Maxim Integrated
+* Products, Inc. Branding Policy.
+*
+* The mere transfer of this software does not imply any licenses
+* of trade secrets, proprietary technology, copyrights, patents,
+* trademarks, maskwork rights, or any other form of intellectual
+* property whatsoever. Maxim Integrated Products, Inc. retains all
+* ownership rights.
+*******************************************************************************
+*/
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace RPCSupport.DataLogging
+{
+    public class StreamDataLog
+    {
+        RPCClient client;
+        bool isRunning = false;
+        DataLogPipeline datalogPipeline;
+
+        public StreamDataLog(RPCClient client)
+        {
+            this.client = client;
+            datalogPipeline = new DataLogPipeline();
+            datalogPipeline.SetProxyPipeline(client.Pipeline);
+        }
+
+        public void DataLogToFile(String filename) {
+        }
+
+        public void Start()
+        {
+            client.pipeline.Discard();
+            client.streaming.Init(datalogPipeline);
+            client.streaming.Start();
+            //Call(CLASSNAME, "StreamTest");
+            //CallNoReply(CLASSNAME, "StreamTest");
+            isRunning = true;
+        }
+
+        public void Stop()
+        {
+            isRunning = false;
+        }
+
+        public bool IsRunning()
+        {
+            return isRunning;
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HspGuiSourceV301/GuiDLLs/RPCSupport/DeviceSupport/DeviceDetails.cs	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,67 @@
+/*******************************************************************************
+* Copyright (C) 2016 Maxim Integrated Products, Inc., All rights Reserved.
+* 
+* This software is protected by copyright laws of the United States and
+* of foreign countries. This material may also be protected by patent laws
+* and technology transfer regulations of the United States and of foreign
+* countries. This software is furnished under a license agreement and/or a
+* nondisclosure agreement and may only be used or reproduced in accordance
+* with the terms of those agreements. Dissemination of this information to
+* any party or parties not specified in the license agreement and/or
+* nondisclosure agreement is expressly prohibited.
+*
+* The above copyright notice and this permission notice shall be included
+* in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+* OTHER DEALINGS IN THE SOFTWARE.
+*
+* Except as contained in this notice, the name of Maxim Integrated
+* Products, Inc. shall not be used except as stated in the Maxim Integrated
+* Products, Inc. Branding Policy.
+*
+* The mere transfer of this software does not imply any licenses
+* of trade secrets, proprietary technology, copyrights, patents,
+* trademarks, maskwork rights, or any other form of intellectual
+* property whatsoever. Maxim Integrated Products, Inc. retains all
+* ownership rights.
+*******************************************************************************
+*/
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace RPCSupport.DeviceSupport
+{
+    public class DeviceDetails
+    {
+        public enum eType
+        {
+            eSpi,
+            eI2c,
+            eMAX30001,
+            eMAX30205
+        }
+        public eType type;
+        public int i2cInstance;
+        public int i2cSlaveAddress;
+
+        public int spiCs;
+        public void InitSpi(int spiCs) {
+            type = eType.eSpi;
+            this.spiCs = spiCs;
+        }
+        public void InitI2c(int i2cInstance, int i2cSlaveAddress) {
+            type = eType.eI2c;
+            this.i2cInstance = i2cInstance;
+            this.i2cSlaveAddress = i2cSlaveAddress;
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HspGuiSourceV301/GuiDLLs/RPCSupport/DeviceSupport/RegisterBitDescriptions.cs	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,60 @@
+/*******************************************************************************
+* Copyright (C) 2016 Maxim Integrated Products, Inc., All rights Reserved.
+* 
+* This software is protected by copyright laws of the United States and
+* of foreign countries. This material may also be protected by patent laws
+* and technology transfer regulations of the United States and of foreign
+* countries. This software is furnished under a license agreement and/or a
+* nondisclosure agreement and may only be used or reproduced in accordance
+* with the terms of those agreements. Dissemination of this information to
+* any party or parties not specified in the license agreement and/or
+* nondisclosure agreement is expressly prohibited.
+*
+* The above copyright notice and this permission notice shall be included
+* in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+* OTHER DEALINGS IN THE SOFTWARE.
+*
+* Except as contained in this notice, the name of Maxim Integrated
+* Products, Inc. shall not be used except as stated in the Maxim Integrated
+* Products, Inc. Branding Policy.
+*
+* The mere transfer of this software does not imply any licenses
+* of trade secrets, proprietary technology, copyrights, patents,
+* trademarks, maskwork rights, or any other form of intellectual
+* property whatsoever. Maxim Integrated Products, Inc. retains all
+* ownership rights.
+*******************************************************************************
+*/
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace RPCSupport.DeviceSupport
+{
+    public class RegisterBitDescriptions
+    {
+        public List<RegisterBitDescription> list = new List<RegisterBitDescription>();
+        public class RegisterBitDescription
+        {
+            public string bit { get; set; }
+            public string name { get; set; }
+            public string description { get; set; }
+
+            public int Index;
+            public int Width;
+        }
+        public void Add(string _bit, string _name, string _description)
+        {
+            list.Add(new RegisterBitDescription() { bit = _bit, name = _name, description = _description });
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HspGuiSourceV301/GuiDLLs/RPCSupport/DeviceSupport/RegisterInfo.cs	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,120 @@
+/*******************************************************************************
+* Copyright (C) 2016 Maxim Integrated Products, Inc., All rights Reserved.
+* 
+* This software is protected by copyright laws of the United States and
+* of foreign countries. This material may also be protected by patent laws
+* and technology transfer regulations of the United States and of foreign
+* countries. This software is furnished under a license agreement and/or a
+* nondisclosure agreement and may only be used or reproduced in accordance
+* with the terms of those agreements. Dissemination of this information to
+* any party or parties not specified in the license agreement and/or
+* nondisclosure agreement is expressly prohibited.
+*
+* The above copyright notice and this permission notice shall be included
+* in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+* OTHER DEALINGS IN THE SOFTWARE.
+*
+* Except as contained in this notice, the name of Maxim Integrated
+* Products, Inc. shall not be used except as stated in the Maxim Integrated
+* Products, Inc. Branding Policy.
+*
+* The mere transfer of this software does not imply any licenses
+* of trade secrets, proprietary technology, copyrights, patents,
+* trademarks, maskwork rights, or any other form of intellectual
+* property whatsoever. Maxim Integrated Products, Inc. retains all
+* ownership rights.
+*******************************************************************************
+*/
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace RPCSupport.DeviceSupport
+{
+    public class RegisterInfo
+    {
+        public String name;
+        public int address;
+        public int[] data;
+        public int numBytes = 1;
+        public RegisterBitDescriptions description;
+        public RegisterType type;
+        public RegisterInfo(String name, int address, RegisterType type)
+        {
+            this.name = name;
+            this.address = address;
+            data = new int[numBytes];
+            description = new RegisterBitDescriptions();
+            this.type = type;
+        }
+
+        public RegisterInfo(String name, int address) : this (name, address, RegisterType.None)
+        {
+        }
+
+        public RegisterInfo(String name, int address, int numBytes, RegisterType type)
+        {
+            this.name = name;
+            this.address = address;
+            this.numBytes = numBytes;
+            data = new int[numBytes];
+            description = new RegisterBitDescriptions();
+            this.type = type;
+        }
+
+        public RegisterInfo(String name, int address, int numBytes) : this (name, address, numBytes, RegisterType.None)
+        {
+
+        }
+
+        public string detailedName
+        {
+            get
+            {
+                string longName = name;
+
+                if (type == RegisterType.ReadOnly)
+                    longName += " (Read Only)";
+                else if (type == RegisterType.WriteOnly)
+                    longName += " (Write Only)";
+
+                return longName;
+            }
+        }
+
+        public int dataField
+        {
+            get
+            {
+                int val = 0;
+                int temp;
+
+                // For Temperature Sensor and standard I2C device
+                for (int i = 0; i < numBytes; i++)
+                {
+                    temp = data[i] << ((numBytes - 1 - i) * 8);
+                    //temp = reg.data[i] << 8 * i;
+                    val |= temp;
+                }
+
+                return val;
+            }
+        }
+
+        public enum RegisterType
+        {
+            ReadOnly,
+            WriteOnly,
+            None
+        };
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HspGuiSourceV301/GuiDLLs/RPCSupport/Devices/ClientDevice.cs	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,101 @@
+/*******************************************************************************
+* Copyright (C) 2016 Maxim Integrated Products, Inc., All rights Reserved.
+* 
+* This software is protected by copyright laws of the United States and
+* of foreign countries. This material may also be protected by patent laws
+* and technology transfer regulations of the United States and of foreign
+* countries. This software is furnished under a license agreement and/or a
+* nondisclosure agreement and may only be used or reproduced in accordance
+* with the terms of those agreements. Dissemination of this information to
+* any party or parties not specified in the license agreement and/or
+* nondisclosure agreement is expressly prohibited.
+*
+* The above copyright notice and this permission notice shall be included
+* in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+* OTHER DEALINGS IN THE SOFTWARE.
+*
+* Except as contained in this notice, the name of Maxim Integrated
+* Products, Inc. shall not be used except as stated in the Maxim Integrated
+* Products, Inc. Branding Policy.
+*
+* The mere transfer of this software does not imply any licenses
+* of trade secrets, proprietary technology, copyrights, patents,
+* trademarks, maskwork rights, or any other form of intellectual
+* property whatsoever. Maxim Integrated Products, Inc. retains all
+* ownership rights.
+*******************************************************************************
+*/
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+
+namespace RPCSupport.Devices
+{
+    public class ClientDevice
+    {
+        internal RPCClient client;
+        public ClientDevice(RPCClient client)
+        {
+            this.client = client;
+        }
+
+        public void WriteRegSpi(byte address, byte data, int chipSelect)
+        {
+            client.Pipeline.Call("Spi", "WriteReg", address.ToString("X2"), chipSelect.ToString("X2"));
+        }
+
+        public byte ReadRegSpi(byte address, int chipSelect)
+        {
+            client.Pipeline.Call("Spi", "ReadReg", address.ToString("X2"), chipSelect.ToString("X2"));
+            return client.Pipeline.GetReturnValue_Byte();
+        }
+
+        public void WriteRegI2c(byte address, byte data, int chipSelect)
+        {
+            client.Pipeline.Call("I2c", "WriteReg", address.ToString("X2"), chipSelect.ToString("X2"));
+        }
+
+        public byte ReadRegI2c(byte address, int chipSelect)
+        {
+            client.Pipeline.Call("I2c", "ReadReg", address.ToString("X2"), chipSelect.ToString("X2"));
+            return client.Pipeline.GetReturnValue_Byte();
+        }
+
+        internal String Call(string name, string method, params string[] args)
+        {
+            return client.Pipeline.Call(name, method, args);
+        }
+
+        internal String CallBinary(string name, string method, out bool allOnes, params string[] args)
+        {
+            return client.Pipeline.CallBinary(name, method, out allOnes, args);
+        }
+
+        internal String CallNoReply(string name, string method, params string[] args)
+        {
+            return client.Pipeline.CallNoReply(name, method, args);
+        }
+
+        public byte GetReturnValue_Byte()
+        {
+            return client.Pipeline.GetReturnValue_Byte();
+        }
+
+        public string GetReturnValue()
+        {
+            return client.Pipeline.GetReturnValue();
+        }
+
+
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HspGuiSourceV301/GuiDLLs/RPCSupport/Devices/I2cDevice.cs	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,166 @@
+/*******************************************************************************
+* Copyright (C) 2016 Maxim Integrated Products, Inc., All rights Reserved.
+* 
+* This software is protected by copyright laws of the United States and
+* of foreign countries. This material may also be protected by patent laws
+* and technology transfer regulations of the United States and of foreign
+* countries. This software is furnished under a license agreement and/or a
+* nondisclosure agreement and may only be used or reproduced in accordance
+* with the terms of those agreements. Dissemination of this information to
+* any party or parties not specified in the license agreement and/or
+* nondisclosure agreement is expressly prohibited.
+*
+* The above copyright notice and this permission notice shall be included
+* in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+* OTHER DEALINGS IN THE SOFTWARE.
+*
+* Except as contained in this notice, the name of Maxim Integrated
+* Products, Inc. shall not be used except as stated in the Maxim Integrated
+* Products, Inc. Branding Policy.
+*
+* The mere transfer of this software does not imply any licenses
+* of trade secrets, proprietary technology, copyrights, patents,
+* trademarks, maskwork rights, or any other form of intellectual
+* property whatsoever. Maxim Integrated Products, Inc. retains all
+* ownership rights.
+*******************************************************************************
+*/
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace RPCSupport.Devices
+{
+    public class I2cDevice : ClientDevice
+    {
+        int i2cSpeed = 1; // default to 400kHz
+        const string CLASSNAME = "I2c";
+        public I2cDevice(RPCClient client)
+            : base(client)
+        {
+        }
+        public void SetI2cSpeed(int speed)
+        {
+            i2cSpeed = speed;
+        }
+        public byte ReadReg(byte instance, byte slaveAddress, byte addr)
+        {
+            byte[] dataToWrite = new byte[] { addr };
+            byte numberToRead = 1;
+            byte[] data = WriteRead(instance, slaveAddress, dataToWrite, numberToRead);
+            return data[0];
+            //string reply1 = Call(CLASSNAME, "Init", instance.ToString("X2"), i2cSpeed.ToString("X2"));
+            //string reply2 = Call(CLASSNAME, "Write", slaveAddress.ToString("X2"), "01", addr.ToString("X2"));
+            //string reply3 = Call(CLASSNAME, "Read", slaveAddress.ToString("X2"), "01");
+            //return client.pipeline.StringToByte(reply3);
+        }
+        public void WriteReg(byte instance, byte slaveAddress, byte addr, byte data)
+        {
+            byte[] dataToWrite = new byte[] { addr, data };
+            byte numberToRead = 0;
+            WriteRead(instance, slaveAddress, dataToWrite, numberToRead);
+            //Call(CLASSNAME, "WriteReg", instance.ToString("X2"), slaveAddress.ToString("X2"), addr.ToString("X2"), data.ToString("X2"));
+        }
+        public byte[] ReadMultiReg(byte instance, byte slaveAddress, byte addr, byte numBytes)
+        {
+            byte[] dataToWrite = new byte[] { addr };
+            byte numberToRead = (byte)numBytes;
+            byte[] data = WriteRead(instance, slaveAddress, dataToWrite, numberToRead);
+            return data;
+            //string reply = Call(CLASSNAME, "ReadMultiReg", instance.ToString("X2"), slaveAddress.ToString("X2"), addr.ToString("X2"), numBytes.ToString("X2"));
+            //return client.pipeline.StringToMultiBytes(reply, numBytes);
+        }
+
+        public void WriteMultiReg(byte instance, byte slaveAddress, byte addr, byte numberOf, byte[] data)
+        {
+            List<byte> dataToWrite = new List<byte>();
+            dataToWrite.Add(addr);
+            dataToWrite.AddRange(data);
+            WriteRead(instance, slaveAddress, dataToWrite.ToArray(), 0);
+            //StringBuilder sb = new StringBuilder();
+            //for (int i = 0; i < numberOf; i++)
+            //{
+            //    sb.Append(data[i].ToString("X2"));
+            //    if (i != numberOf - 1)
+            //    {
+            //        sb.Append(" ");
+            //    }
+            //}
+            //Call(CLASSNAME, "WriteMultiReg", instance.ToString("X2"), slaveAddress.ToString("X2"), addr.ToString("X2"), numberOf.ToString("X2"), sb.ToString());
+        }
+
+        public void ReadReg(DeviceSupport.DeviceDetails deviceDetails, DeviceSupport.RegisterInfo reg)
+        {
+            byte[] dataToWrite = new byte[] { (byte)reg.address };
+            byte numberToRead = (byte)reg.numBytes;
+            byte[] data = WriteRead((byte)deviceDetails.i2cInstance, (byte)deviceDetails.i2cSlaveAddress, dataToWrite, numberToRead);
+            for (int i = 0; i < data.Length; i++)
+            {
+                reg.data[i] = (int)data[i];
+            }            
+            //if (reg.numBytes == 1)
+            //{
+            //    byte data = ReadReg((byte)deviceDetails.i2cInstance, (byte)deviceDetails.i2cSlaveAddress, (byte)reg.address);
+            //    reg.data[0] = (int)data;
+            //}
+            //else
+            //{
+            //    byte[] data = ReadMultiReg((byte)deviceDetails.i2cInstance, (byte)deviceDetails.i2cSlaveAddress, (byte)reg.address, (byte)reg.numBytes);
+            //    for (int i = 0; i < data.Length; i++)
+            //    {
+            //        reg.data[i] = (int)data[i];
+            //    }
+            //}
+        }
+
+        internal void WriteReg(DeviceSupport.DeviceDetails deviceDetails, DeviceSupport.RegisterInfo reg)
+        {
+            byte[] dataToWrite;
+            byte numberToRead = 0;
+
+            dataToWrite = new byte[reg.numBytes + 1];
+            dataToWrite[0] = (byte)reg.address;
+            for (int i = 0; i < reg.numBytes; i++)
+            {
+                dataToWrite[i + 1] = (byte)(reg.data[i]);
+            }
+
+            WriteRead((byte)deviceDetails.i2cInstance, (byte)deviceDetails.i2cSlaveAddress, dataToWrite, numberToRead);
+            //if (reg.numBytes == 1)
+            //{
+            //    WriteReg((byte)deviceDetails.i2cInstance, (byte)deviceDetails.i2cSlaveAddress, (byte)reg.address, (byte)reg.data[0]);
+            //}
+            //else
+            //{
+            //    byte[] data = new byte[reg.numBytes];
+            //    for (int i = 0; i < data.Length; i++)
+            //    {
+            //        data[i] = (byte)reg.data[i];
+            //    }
+            //    WriteMultiReg((byte)deviceDetails.i2cInstance, (byte)deviceDetails.i2cSlaveAddress, (byte)reg.address, (byte)reg.numBytes, data);
+            //}
+        }
+
+        public byte[] WriteRead(byte instance, byte slaveAddress, byte[] dataToWrite, byte numberToRead)
+        {
+            string dataToWriteStr = "";
+            StringBuilder sb = new StringBuilder();
+            for (int i = 0; i < dataToWrite.Length; i++)
+            {
+                sb.Append(dataToWrite[i].ToString("X2") + " ");
+            }
+            dataToWriteStr = sb.ToString().Trim();
+            string reply = Call(CLASSNAME, "WriteRead", instance.ToString("X2"), slaveAddress.ToString("X2"), dataToWrite.Length.ToString("X2"),dataToWriteStr,  numberToRead.ToString("X2"));
+            return client.pipeline.StringToMultiBytes(reply, numberToRead);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HspGuiSourceV301/GuiDLLs/RPCSupport/Devices/IRegisterDevice.cs	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,53 @@
+/*******************************************************************************
+* Copyright (C) 2016 Maxim Integrated Products, Inc., All rights Reserved.
+* 
+* This software is protected by copyright laws of the United States and
+* of foreign countries. This material may also be protected by patent laws
+* and technology transfer regulations of the United States and of foreign
+* countries. This software is furnished under a license agreement and/or a
+* nondisclosure agreement and may only be used or reproduced in accordance
+* with the terms of those agreements. Dissemination of this information to
+* any party or parties not specified in the license agreement and/or
+* nondisclosure agreement is expressly prohibited.
+*
+* The above copyright notice and this permission notice shall be included
+* in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+* OTHER DEALINGS IN THE SOFTWARE.
+*
+* Except as contained in this notice, the name of Maxim Integrated
+* Products, Inc. shall not be used except as stated in the Maxim Integrated
+* Products, Inc. Branding Policy.
+*
+* The mere transfer of this software does not imply any licenses
+* of trade secrets, proprietary technology, copyrights, patents,
+* trademarks, maskwork rights, or any other form of intellectual
+* property whatsoever. Maxim Integrated Products, Inc. retains all
+* ownership rights.
+*******************************************************************************
+*/
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace RPCSupport.Devices
+{
+    /// <summary>
+    /// Interface for a device with registers which are addressed.
+    /// 
+    /// TODO: Modify the other devices to support this interface
+    /// </summary>
+    public interface IRegisterDevice
+    {
+        int ReadReg(byte addr);
+        void WriteReg(byte addr, int data);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HspGuiSourceV301/GuiDLLs/RPCSupport/Devices/LIS2HD.cs	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,63 @@
+/*******************************************************************************
+* Copyright (C) 2016 Maxim Integrated Products, Inc., All rights Reserved.
+* 
+* This software is protected by copyright laws of the United States and
+* of foreign countries. This material may also be protected by patent laws
+* and technology transfer regulations of the United States and of foreign
+* countries. This software is furnished under a license agreement and/or a
+* nondisclosure agreement and may only be used or reproduced in accordance
+* with the terms of those agreements. Dissemination of this information to
+* any party or parties not specified in the license agreement and/or
+* nondisclosure agreement is expressly prohibited.
+*
+* The above copyright notice and this permission notice shall be included
+* in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+* OTHER DEALINGS IN THE SOFTWARE.
+*
+* Except as contained in this notice, the name of Maxim Integrated
+* Products, Inc. shall not be used except as stated in the Maxim Integrated
+* Products, Inc. Branding Policy.
+*
+* The mere transfer of this software does not imply any licenses
+* of trade secrets, proprietary technology, copyrights, patents,
+* trademarks, maskwork rights, or any other form of intellectual
+* property whatsoever. Maxim Integrated Products, Inc. retains all
+* ownership rights.
+*******************************************************************************
+*/
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace RPCSupport.Devices
+{
+    public class LIS2HD : ClientDevice
+    {
+        //RPCClient client;
+        const string CLASSNAME = "LIS2HD";
+        int slaveAddress;
+        public LIS2HD(RPCClient client, int slaveAddress)
+            : base(client)  
+        {
+            this.slaveAddress = slaveAddress;
+        }
+        public byte ReadReg(byte addr)
+        {
+            Call(CLASSNAME, "ReadReg", slaveAddress.ToString("X2"), addr.ToString("X2"));
+            return GetReturnValue_Byte();
+        }
+        public void WriteReg(byte addr, byte data)
+        {
+            Call(CLASSNAME, "WriteReg", slaveAddress.ToString("X2"), addr.ToString("X2"), data.ToString("X2"));
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HspGuiSourceV301/GuiDLLs/RPCSupport/Devices/Led.cs	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,70 @@
+/*******************************************************************************
+* Copyright (C) 2016 Maxim Integrated Products, Inc., All rights Reserved.
+* 
+* This software is protected by copyright laws of the United States and
+* of foreign countries. This material may also be protected by patent laws
+* and technology transfer regulations of the United States and of foreign
+* countries. This software is furnished under a license agreement and/or a
+* nondisclosure agreement and may only be used or reproduced in accordance
+* with the terms of those agreements. Dissemination of this information to
+* any party or parties not specified in the license agreement and/or
+* nondisclosure agreement is expressly prohibited.
+*
+* The above copyright notice and this permission notice shall be included
+* in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+* OTHER DEALINGS IN THE SOFTWARE.
+*
+* Except as contained in this notice, the name of Maxim Integrated
+* Products, Inc. shall not be used except as stated in the Maxim Integrated
+* Products, Inc. Branding Policy.
+*
+* The mere transfer of this software does not imply any licenses
+* of trade secrets, proprietary technology, copyrights, patents,
+* trademarks, maskwork rights, or any other form of intellectual
+* property whatsoever. Maxim Integrated Products, Inc. retains all
+* ownership rights.
+*******************************************************************************
+*/
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace RPCSupport.Devices
+{
+    public class Led : ClientDevice
+    {
+        const string CLASSNAME = "Led";
+        public Led(RPCClient client)
+            : base(client)
+        {
+        }
+        public byte On()
+        {
+            Call(CLASSNAME, "On");
+            return GetReturnValue_Byte();
+        }
+        public byte Off()
+        {
+            Call(CLASSNAME, "Off");
+            return GetReturnValue_Byte();
+        }
+        public byte BlinkHz(byte hz)
+        {
+            Call(CLASSNAME, "BlinkHz", hz.ToString("X2"));
+            return GetReturnValue_Byte();
+        }
+        public void BlinkPattern(uint pattern)
+        {
+            Call(CLASSNAME, "BlinkPattern", pattern.ToString("X2"));
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HspGuiSourceV301/GuiDLLs/RPCSupport/Devices/MAX30001.cs	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,382 @@
+/*******************************************************************************
+* Copyright (C) 2016 Maxim Integrated Products, Inc., All rights Reserved.
+* 
+* This software is protected by copyright laws of the United States and
+* of foreign countries. This material may also be protected by patent laws
+* and technology transfer regulations of the United States and of foreign
+* countries. This software is furnished under a license agreement and/or a
+* nondisclosure agreement and may only be used or reproduced in accordance
+* with the terms of those agreements. Dissemination of this information to
+* any party or parties not specified in the license agreement and/or
+* nondisclosure agreement is expressly prohibited.
+*
+* The above copyright notice and this permission notice shall be included
+* in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+* OTHER DEALINGS IN THE SOFTWARE.
+*
+* Except as contained in this notice, the name of Maxim Integrated
+* Products, Inc. shall not be used except as stated in the Maxim Integrated
+* Products, Inc. Branding Policy.
+*
+* The mere transfer of this software does not imply any licenses
+* of trade secrets, proprietary technology, copyrights, patents,
+* trademarks, maskwork rights, or any other form of intellectual
+* property whatsoever. Maxim Integrated Products, Inc. retains all
+* ownership rights.
+*******************************************************************************
+*/
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Globalization;
+using System.Threading;
+
+namespace RPCSupport.Devices
+{
+    /* ECG */
+    public class MAX30001 : ClientDevice, IRegisterDevice
+    {
+
+        public enum max30001_intrpt_Location {
+            MAX30001_NO_INT  = 0,  // No interrupt
+            MAX30001_INT_B   = 1,  // INTB selected for interrupt
+            MAX30001_INT_2B  = 2,   // INT2B selected for interrupt
+            test1 = 3,
+            test2 = 4,
+            test3 = 5,
+            test4 = 6,
+            test5 = 7,
+            test6 = 8,
+            test7 = 9,
+            test8 = 10,
+            test9 = 11,
+            test10 = 12,
+            test11 = 13,
+            test12 = 14,
+            test13 = 15,
+            test14 = 16,
+            test15 = 17
+        };
+
+        public enum max30001_intrpt_type {
+	        MAX30001_INT_DISABLED = 0x00,
+	        MAX30001_INT_CMOS     = 0x01,
+	        MAX30001_INT_ODN      = 0x02,
+            MAX30001_INT_ODNR     = 0x03,
+	        test1     = 18,   
+	        test2     = 19
+        };
+
+        public const string CLASSNAME = "MAX30001";
+        public MAX30001(RPCClient client)
+            : base(client)
+        {
+        }
+        public int ReadReg(byte addr)
+        {
+            int val;
+            string reply = Call(CLASSNAME, "ReadReg", addr.ToString("X2"));
+            int.TryParse(reply, NumberStyles.HexNumber, CultureInfo.CurrentCulture, out val);
+            return val;
+            //return GetReturnValue_Byte();
+        }
+
+        public void WriteReg(byte addr, int data)
+        {
+            Call(CLASSNAME, "WriteReg", addr.ToString("X2"), data.ToString("X2"));
+        }
+        public void StartConv()
+        {
+            Call(CLASSNAME, "StartConv");
+        }
+
+        private void InitStreaming()
+        {
+            client.pipeline.Discard();
+            client.streaming.Init(client.pipeline);
+            client.streaming.Start();
+            //Call(CLASSNAME, "StreamTest");
+            //CallNoReply(CLASSNAME, "StreamTest");
+        }
+
+
+        public int Rbias_FMSTR_Init(
+            int En_rbias,
+            int Rbiasv,
+            int Rbiasp,
+            int Rbiasn,
+            int Fmstr)
+        {
+            Call(CLASSNAME, "Rbias_FMSTR_Init", En_rbias.ToString("X2"), Rbiasv.ToString("X2"), Rbiasp.ToString("X2"), Rbiasn.ToString("X2"), Fmstr.ToString("X2"));
+            return 0;
+        }
+
+
+        // old 12/15/15 for reference
+/*
+                        public int CAL_InitStart(
+                            int Vmode,
+                            int Vmag,
+                            int Fcal,
+                            int Thigh,
+                            int Fifty,
+                            int En_Vcal)
+                        {
+                            Call(CLASSNAME, "CAL_InitStart", Vmode.ToString("X2"), Vmag.ToString("X2"), Fcal.ToString("X2"), Thigh.ToString("X2"), Fifty.ToString("X2"), En_Vcal.ToString("X2"));
+                            return 0;
+                        }
+
+        */
+        public int CAL_InitStart(
+            int En_Vcal,
+            int Vmode,
+            int Vmag,
+            int Fcal,
+            int Thigh,
+            int Fifty
+            )
+        {
+            Call(CLASSNAME, "CAL_InitStart", En_Vcal.ToString("X2"), Vmode.ToString("X2"), Vmag.ToString("X2"), Fcal.ToString("X2"), Thigh.ToString("X2"), Fifty.ToString("X2"));
+            return 0;
+        }
+
+
+        // old 12/15/15 for reference
+/*        public int ECG_InitStart(
+            int Openp,
+            int Openn,
+            int Pol,
+            int Calp_sel,
+            int Caln_sel,
+            int En_ecg,
+            int E_fit,
+            int Clr_rrint,
+            int Rate,
+            int Gain,
+            int Dhpf,
+            int Dlpf)
+        {
+            Call(CLASSNAME, "ECG_InitStart", Openp.ToString("X2"), Openn.ToString("X2"), Pol.ToString("X2"), Calp_sel.ToString("X2"), Caln_sel.ToString("X2"), En_ecg.ToString("X2"), E_fit.ToString("X2"), Clr_rrint.ToString("X2"), Rate.ToString("X2"), Gain.ToString("X2"), Dhpf.ToString("X2"), Dlpf.ToString("X2"));
+            return 0;
+        }*/
+        public int ECG_InitStart(
+            int En_ecg,
+            int Openp,
+            int Openn,
+            int Pol,
+            int Calp_sel,
+            int Caln_sel,
+            int E_fit,
+            int Rate,
+            int Gain,
+            int Dhpf,
+            int Dlpf)
+        {
+            Call(CLASSNAME, "ECG_InitStart", En_ecg.ToString("X2"), Openp.ToString("X2"), Openn.ToString("X2"), Pol.ToString("X2"), Calp_sel.ToString("X2"), Caln_sel.ToString("X2"), 
+                E_fit.ToString("X2"), Rate.ToString("X2"), Gain.ToString("X2"), Dhpf.ToString("X2"), Dlpf.ToString("X2"));
+            return 0;
+        }
+
+
+        public int ECGFast_Init(
+            int Clr_Fast,
+            int Fast,
+            int Fast_Th)
+        {
+            Call(CLASSNAME, "ECGFast_Init", Clr_Fast.ToString("X2"), Fast.ToString("X2"), Fast_Th.ToString("X2"));
+            return 0;
+        }
+
+        public int PACE_InitStart(
+            int En_pace,
+            int Clr_pedge,
+            int Pol,
+            int Gn_diff_off,
+            int Gain,
+            int Aout_lbw,
+            int Aout,
+            int Dacp,
+            int Dacn)
+        {
+            Call(CLASSNAME, "PACE_InitStart", En_pace.ToString("X2"), Clr_pedge.ToString("X2"), Pol.ToString("X2"), Gn_diff_off.ToString("X2"), Gain.ToString("X2"), Aout_lbw.ToString("X2"), Aout.ToString("X2"), Dacp.ToString("X2"), Dacn.ToString("X2"));
+            return 0;
+        }
+
+        // old 12/15/15 for reference
+/*        public int BIOZ_InitStart(
+                    int Openp,
+                    int Openn,
+                    int Calp_sel,
+                    int Caln_sel,
+                    int CG_mode,
+                    int En_bioz,
+                    int B_fit,
+                    int Rate,
+                    int Ahpf,
+                    int Ext_rbias,
+                    int Gain,
+                    int Dhpf,
+                    int Dlpf,
+                    int Fcgen,
+                    int Cgmon,
+                    int Cgmag,
+                    int Phoff)
+                {
+                    Call(CLASSNAME, "BIOZ_InitStart", Openp.ToString("X2"), Openn.ToString("X2"), Calp_sel.ToString("X2"), Caln_sel.ToString("X2"), CG_mode.ToString("X2"),
+                        En_bioz.ToString("X2"), B_fit.ToString("X2"), Rate.ToString("X2"), Ahpf.ToString("X2"), Ext_rbias.ToString("X2"), Gain.ToString("X2"),
+                        Dhpf.ToString("X2"), Dlpf.ToString("X2"), Fcgen.ToString("X2"), Cgmon.ToString("X2"), Cgmag.ToString("X2"), Phoff.ToString("X2"));
+                    return 0;
+                }*/
+        public int BIOZ_InitStart(
+            int En_bioz,
+            int Openp,
+            int Openn,
+            int Calp_sel,
+            int Caln_sel,
+            int CG_mode,
+            int B_fit,
+            int Rate,
+            int Ahpf,
+            int Ext_rbias,
+            int Gain,
+            int Dhpf,
+            int Dlpf,
+            int Fcgen,
+            int Cgmon,
+            int Cgmag,
+            int Phoff)
+        {
+            Call(CLASSNAME, "BIOZ_InitStart", En_bioz.ToString("X2"), Openp.ToString("X2"), Openn.ToString("X2"), Calp_sel.ToString("X2"), Caln_sel.ToString("X2"), CG_mode.ToString("X2"),
+                B_fit.ToString("X2"), Rate.ToString("X2"), Ahpf.ToString("X2"), Ext_rbias.ToString("X2"), Gain.ToString("X2"),
+                Dhpf.ToString("X2"), Dlpf.ToString("X2"), Fcgen.ToString("X2"), Cgmon.ToString("X2"), Cgmag.ToString("X2"), Phoff.ToString("X2"));
+            return 0;
+        }
+
+        // old 12/15/15 for reference
+/*        public int RtoR_InitStart(
+                    int Wndw,
+                    int Gain,
+                    int En_rtor,
+                    int Pavg,
+                    int Ptsf,
+                    int Hoff,
+                    int Ravg,
+                    int Rhsf)
+                {
+                    Call(CLASSNAME, "RtoR_InitStart", Wndw.ToString("X2"), Gain.ToString("X2"), En_rtor.ToString("X2"), Pavg.ToString("X2"), Ptsf.ToString("X2"),
+                        Hoff.ToString("X2"), Ravg.ToString("X2"), Rhsf.ToString("X2"));
+                    return 0;
+                }*/
+        public int RtoR_InitStart(
+            int En_rtor,
+            int Wndw,
+            int Gain,
+            int Pavg,
+            int Ptsf,
+            int Hoff,
+            int Ravg,
+            int Rhsf,
+            int Clr_rrint)
+        {
+            Call(CLASSNAME, "RtoR_InitStart", En_rtor.ToString("X2"), Wndw.ToString("X2"), Gain.ToString("X2"), Pavg.ToString("X2"), Ptsf.ToString("X2"),
+                Hoff.ToString("X2"), Ravg.ToString("X2"), Rhsf.ToString("X2"), Clr_rrint.ToString("X2"));
+            return 0;
+        }
+
+        public int Stop_ECG()
+        {
+            Call(CLASSNAME, "Stop_ECG");
+            return 0;
+        }
+
+        public int Stop_PACE()
+        {
+            Call(CLASSNAME, "Stop_PACE");
+            return 0;
+        }
+
+        public int Stop_Cal()
+        {
+            //Call(CLASSNAME, "Stop_Cal");
+            return 0;
+        }
+
+        public int Stop_BIOZ()
+        {
+            Call(CLASSNAME, "Stop_BIOZ");
+            return 0;
+        }
+
+        public int Stop_RtoR()
+        {
+            Call(CLASSNAME, "Stop_RtoR");
+            return 0;
+        }
+
+        public void StartStreaming()
+        {
+            client.pipeline.Discard();
+            InitStreaming();
+            CallNoReply(CLASSNAME, "Start");
+            //Call(CLASSNAME, "StartTest");
+        }
+
+        public void StartTest()
+        {
+            client.pipeline.Discard();
+            InitStreaming();
+            CallNoReply(CLASSNAME, "StartTest");
+            //Call(CLASSNAME, "StartTest");
+        }
+
+        public void StopStreaming()
+        {
+            StopStreaming(true);                
+        }
+
+        public void StopStreaming(bool connected)
+        {
+            if (connected)
+                client.pipeline.SendSingleByte(' ');
+
+            client.streaming.Stop();
+
+            if (connected)
+            {
+                client.pipeline.Discard();
+                Thread.Sleep(500);
+                client.pipeline.Discard();
+            }
+        }
+
+        public void INT_assignment(
+            max30001_intrpt_Location max30001_intrpt_Location, max30001_intrpt_Location max30001_intrpt_Location_2, max30001_intrpt_Location max30001_intrpt_Location_3, 
+            max30001_intrpt_Location max30001_intrpt_Location_4, max30001_intrpt_Location max30001_intrpt_Location_5, max30001_intrpt_Location max30001_intrpt_Location_6, 
+            max30001_intrpt_Location max30001_intrpt_Location_7, max30001_intrpt_Location max30001_intrpt_Location_8, max30001_intrpt_Location max30001_intrpt_Location_9, 
+            max30001_intrpt_Location max30001_intrpt_Location_10, max30001_intrpt_Location max30001_intrpt_Location_11, max30001_intrpt_Location max30001_intrpt_Location_12, 
+            max30001_intrpt_Location max30001_intrpt_Location_13, max30001_intrpt_Location max30001_intrpt_Location_14, max30001_intrpt_Location max30001_intrpt_Location_15, 
+            max30001_intrpt_type max30001_intrpt_type, max30001_intrpt_type max30001_intrpt_type_2)
+        {
+            Call(CLASSNAME, "INT_assignment",
+                max30001_intrpt_Location.ToString("x") , max30001_intrpt_Location_2.ToString("x") , max30001_intrpt_Location_3.ToString("x") ,
+                max30001_intrpt_Location_4.ToString("x") , max30001_intrpt_Location_5.ToString("x") , max30001_intrpt_Location_6.ToString("x") ,
+                max30001_intrpt_Location_7.ToString("x") , max30001_intrpt_Location_8.ToString("x") , max30001_intrpt_Location_9.ToString("x") ,
+                max30001_intrpt_Location_10.ToString("x") , max30001_intrpt_Location_11.ToString("x") , max30001_intrpt_Location_12.ToString("x") ,
+                max30001_intrpt_Location_13.ToString("x") , max30001_intrpt_Location_14.ToString("x") , max30001_intrpt_Location_15.ToString("x") ,
+                max30001_intrpt_type.ToString("x") , max30001_intrpt_type_2.ToString("x") 
+                );
+        }
+    }
+}
+
+    
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HspGuiSourceV301/GuiDLLs/RPCSupport/Devices/MAX30101/MAX30101.cs	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,197 @@
+/*******************************************************************************
+* Copyright (C) 2016 Maxim Integrated Products, Inc., All rights Reserved.
+* 
+* This software is protected by copyright laws of the United States and
+* of foreign countries. This material may also be protected by patent laws
+* and technology transfer regulations of the United States and of foreign
+* countries. This software is furnished under a license agreement and/or a
+* nondisclosure agreement and may only be used or reproduced in accordance
+* with the terms of those agreements. Dissemination of this information to
+* any party or parties not specified in the license agreement and/or
+* nondisclosure agreement is expressly prohibited.
+*
+* The above copyright notice and this permission notice shall be included
+* in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+* OTHER DEALINGS IN THE SOFTWARE.
+*
+* Except as contained in this notice, the name of Maxim Integrated
+* Products, Inc. shall not be used except as stated in the Maxim Integrated
+* Products, Inc. Branding Policy.
+*
+* The mere transfer of this software does not imply any licenses
+* of trade secrets, proprietary technology, copyrights, patents,
+* trademarks, maskwork rights, or any other form of intellectual
+* property whatsoever. Maxim Integrated Products, Inc. retains all
+* ownership rights.
+*******************************************************************************
+*/
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading;
+
+namespace RPCSupport.Devices
+{
+    /* Optical */
+    public class MAX30101 : ClientDevice
+    {
+        public const string CLASSNAME = "MAX30101";
+        int slaveAddress;
+        public MAX30101(RPCClient client, int slaveAddress)
+            : base(client)
+        {
+            this.slaveAddress = slaveAddress;
+        }
+        public byte ReadReg(byte addr)
+        {
+            string reply = Call(CLASSNAME, "ReadReg", addr.ToString("X2"));
+            return client.pipeline.StringToByte(reply);
+        }
+        public void WriteReg(byte addr, byte data)
+        {
+            Call(CLASSNAME, "WriteReg", addr.ToString("X2"), data.ToString("X2"));
+        }
+
+        private void InitStreaming()
+        {
+            client.pipeline.Discard();
+            client.streaming.Init(client.pipeline);
+            client.streaming.Start();
+            //Call(CLASSNAME, "StreamTest");
+            //CallNoReply(CLASSNAME, "StreamTest");
+        }
+
+        public void StopStreaming()
+        {
+            StopStreaming(true);
+        }
+
+        public void StopStreaming(bool connected)
+        {
+            if (connected)
+                client.pipeline.SendSingleByte(' ');
+
+            client.streaming.Stop();
+
+            if (connected)
+            {
+                client.pipeline.Discard();
+                Thread.Sleep(500);
+                client.pipeline.Discard();
+            }
+        }
+
+        public void SpO2mode_init(byte fifo_waterlevel_mark, byte sample_avg, byte sample_rate, byte pulse_width,
+                                                                        byte red_led_current, byte ir_led_current, byte accelRateParameter)
+        {
+            InitStreaming();
+            CallNoReply(CLASSNAME, "SpO2mode_init", 
+                fifo_waterlevel_mark.ToString("X2"), 
+                sample_avg.ToString("X2"),
+                sample_rate.ToString("X2"),
+                pulse_width.ToString("X2"),
+                red_led_current.ToString("X2"),
+                ir_led_current.ToString("X2"),
+                accelRateParameter.ToString("X2")
+                );
+        }
+
+        public void HRmode_init(byte fifo_waterlevel_mark, byte sample_avg, byte sample_rate, byte pulse_width, 
+                                                                        byte red_led_current,byte accelRateParameter)
+        {
+            InitStreaming();
+            CallNoReply(CLASSNAME, "HRmode_init",
+                fifo_waterlevel_mark.ToString("X2"),
+                sample_avg.ToString("X2"),
+                sample_rate.ToString("X2"),
+                pulse_width.ToString("X2"),
+                red_led_current.ToString("X2"),
+                accelRateParameter.ToString("X2")
+                );
+        }
+
+        public void Multimode_init(byte fifo_waterlevel_mark, byte sample_avg, byte sample_rate, byte pulse_width,
+                                            byte red_led_current, byte ir_led_current, byte green_led_current,
+                                            byte slot_1, byte slot_2, byte slot_3, byte slot_4, byte accelRateParameter)
+        {
+            InitStreaming();
+            CallNoReply(CLASSNAME, "Multimode_init",
+                fifo_waterlevel_mark.ToString("X2"),
+                sample_avg.ToString("X2"),
+                sample_rate.ToString("X2"),
+                pulse_width.ToString("X2"),
+                red_led_current.ToString("X2"),
+                ir_led_current.ToString("X2"),
+                green_led_current.ToString("X2"),
+                slot_1.ToString("X2"),
+                slot_2.ToString("X2"),
+                slot_3.ToString("X2"),
+                slot_4.ToString("X2"),
+                accelRateParameter.ToString("X2")
+                );
+        }
+
+        public void SpO2mode_stop()
+        {
+            SpO2mode_stop(true);
+        }
+
+        public void SpO2mode_stop(bool connected)
+        {
+            StopStreaming(connected);
+
+            if (connected)
+            {
+                Call(CLASSNAME, "SpO2mode_stop");
+                System.Threading.Thread.Sleep(250);
+                client.pipeline.Discard();
+            }
+        }
+
+        public void HRmode_stop()
+        {
+            HRmode_stop(true);
+        }
+
+        public void HRmode_stop(bool connected)
+        {
+            StopStreaming(connected);
+
+            if (connected)
+            {
+                Call(CLASSNAME, "HRmode_stop");
+                System.Threading.Thread.Sleep(250);
+                client.pipeline.Discard();
+            }
+        }
+
+        public void Multimode_stop()
+        {
+            Multimode_stop(true);
+        }
+
+        public void Multimode_stop(bool connected)
+        {
+            StopStreaming(connected);
+
+            if (connected)
+            {
+                Call(CLASSNAME, "Multimode_stop");
+                System.Threading.Thread.Sleep(250);
+                client.pipeline.Discard();
+            }
+        }
+
+    }
+}
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HspGuiSourceV301/GuiDLLs/RPCSupport/Devices/MAX30205.cs	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,76 @@
+/*******************************************************************************
+* Copyright (C) 2016 Maxim Integrated Products, Inc., All rights Reserved.
+* 
+* This software is protected by copyright laws of the United States and
+* of foreign countries. This material may also be protected by patent laws
+* and technology transfer regulations of the United States and of foreign
+* countries. This software is furnished under a license agreement and/or a
+* nondisclosure agreement and may only be used or reproduced in accordance
+* with the terms of those agreements. Dissemination of this information to
+* any party or parties not specified in the license agreement and/or
+* nondisclosure agreement is expressly prohibited.
+*
+* The above copyright notice and this permission notice shall be included
+* in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+* OTHER DEALINGS IN THE SOFTWARE.
+*
+* Except as contained in this notice, the name of Maxim Integrated
+* Products, Inc. shall not be used except as stated in the Maxim Integrated
+* Products, Inc. Branding Policy.
+*
+* The mere transfer of this software does not imply any licenses
+* of trade secrets, proprietary technology, copyrights, patents,
+* trademarks, maskwork rights, or any other form of intellectual
+* property whatsoever. Maxim Integrated Products, Inc. retains all
+* ownership rights.
+*******************************************************************************
+*/
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace RPCSupport.Devices
+{
+    public class MAX30205 : ClientDevice
+    {
+        const string CLASSNAME = "MAX30205";
+        int slaveAddress;
+        public MAX30205(RPCClient client, int slaveAddress)
+            : base(client)
+        {
+            this.slaveAddress = slaveAddress;
+        }
+        public byte ReadReg(byte addr)
+        {
+            Call(CLASSNAME, "ReadReg", addr.ToString("X2"));
+            return GetReturnValue_Byte();
+        }
+        public void WriteReg(byte addr, byte data)
+        {
+            Call(CLASSNAME, "WriteReg", addr.ToString("X2"), data.ToString("X2"));
+        }
+        public void StartConv()
+        {
+            Call(CLASSNAME, "StartConv");
+        }
+        public float ReadTemp()
+        {
+            Call(CLASSNAME, "ReadTemp");
+            float val = (float)GetReturnValue_Byte();
+            return val;
+        }
+        public void Shutdown(bool state)
+        {
+            Call(CLASSNAME, "Shutdown", state ? "true": "false");
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HspGuiSourceV301/GuiDLLs/RPCSupport/Devices/S25FS512.cs	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,56 @@
+/*******************************************************************************
+* Copyright (C) 2016 Maxim Integrated Products, Inc., All rights Reserved.
+* 
+* This software is protected by copyright laws of the United States and
+* of foreign countries. This material may also be protected by patent laws
+* and technology transfer regulations of the United States and of foreign
+* countries. This software is furnished under a license agreement and/or a
+* nondisclosure agreement and may only be used or reproduced in accordance
+* with the terms of those agreements. Dissemination of this information to
+* any party or parties not specified in the license agreement and/or
+* nondisclosure agreement is expressly prohibited.
+*
+* The above copyright notice and this permission notice shall be included
+* in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+* OTHER DEALINGS IN THE SOFTWARE.
+*
+* Except as contained in this notice, the name of Maxim Integrated
+* Products, Inc. shall not be used except as stated in the Maxim Integrated
+* Products, Inc. Branding Policy.
+*
+* The mere transfer of this software does not imply any licenses
+* of trade secrets, proprietary technology, copyrights, patents,
+* trademarks, maskwork rights, or any other form of intellectual
+* property whatsoever. Maxim Integrated Products, Inc. retains all
+* ownership rights.
+*******************************************************************************
+*/
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace RPCSupport.Devices
+{
+    public class S25FS512 : ClientDevice
+    {
+        const string CLASSNAME = "S25FS512";
+        public S25FS512(RPCClient client)
+            : base(client)
+        {
+        }
+        public String ReadId()
+        {
+            String reply = Call(CLASSNAME, "ReadId");
+            return reply;
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HspGuiSourceV301/GuiDLLs/RPCSupport/Devices/SpiDevice.cs	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,67 @@
+/*******************************************************************************
+* Copyright (C) 2016 Maxim Integrated Products, Inc., All rights Reserved.
+* 
+* This software is protected by copyright laws of the United States and
+* of foreign countries. This material may also be protected by patent laws
+* and technology transfer regulations of the United States and of foreign
+* countries. This software is furnished under a license agreement and/or a
+* nondisclosure agreement and may only be used or reproduced in accordance
+* with the terms of those agreements. Dissemination of this information to
+* any party or parties not specified in the license agreement and/or
+* nondisclosure agreement is expressly prohibited.
+*
+* The above copyright notice and this permission notice shall be included
+* in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+* OTHER DEALINGS IN THE SOFTWARE.
+*
+* Except as contained in this notice, the name of Maxim Integrated
+* Products, Inc. shall not be used except as stated in the Maxim Integrated
+* Products, Inc. Branding Policy.
+*
+* The mere transfer of this software does not imply any licenses
+* of trade secrets, proprietary technology, copyrights, patents,
+* trademarks, maskwork rights, or any other form of intellectual
+* property whatsoever. Maxim Integrated Products, Inc. retains all
+* ownership rights.
+*******************************************************************************
+*/
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Globalization;
+
+namespace RPCSupport.Devices
+{
+    public class SpiDevice : ClientDevice
+    {
+        const string CLASSNAME = "Spi";
+        //int chipSelect;
+        public SpiDevice(RPCClient client)
+            : base(client)
+        {
+            //this.chipSelect = chipSelect;
+        }
+
+        public int ReadReg(DeviceSupport.DeviceDetails deviceDetails, DeviceSupport.RegisterInfo reg)
+        {
+            int val;
+            string reply = Call(CLASSNAME, "ReadReg", reg.address.ToString("X2"));
+            int.TryParse(reply, NumberStyles.HexNumber, CultureInfo.CurrentCulture, out val);
+            return val;
+        }
+
+        internal void WriteReg(DeviceSupport.DeviceDetails deviceDetails, DeviceSupport.RegisterInfo reg)
+        {
+            throw new NotImplementedException();
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HspGuiSourceV301/GuiDLLs/RPCSupport/Devices/Testing.cs	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,122 @@
+/*******************************************************************************
+* Copyright (C) 2016 Maxim Integrated Products, Inc., All rights Reserved.
+* 
+* This software is protected by copyright laws of the United States and
+* of foreign countries. This material may also be protected by patent laws
+* and technology transfer regulations of the United States and of foreign
+* countries. This software is furnished under a license agreement and/or a
+* nondisclosure agreement and may only be used or reproduced in accordance
+* with the terms of those agreements. Dissemination of this information to
+* any party or parties not specified in the license agreement and/or
+* nondisclosure agreement is expressly prohibited.
+*
+* The above copyright notice and this permission notice shall be included
+* in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+* OTHER DEALINGS IN THE SOFTWARE.
+*
+* Except as contained in this notice, the name of Maxim Integrated
+* Products, Inc. shall not be used except as stated in the Maxim Integrated
+* Products, Inc. Branding Policy.
+*
+* The mere transfer of this software does not imply any licenses
+* of trade secrets, proprietary technology, copyrights, patents,
+* trademarks, maskwork rights, or any other form of intellectual
+* property whatsoever. Maxim Integrated Products, Inc. retains all
+* ownership rights.
+*******************************************************************************
+*/
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace RPCSupport.Devices
+{
+    public class Testing : ClientDevice
+    {
+        const string CLASSNAME = "Testing";
+        public Testing(RPCClient client)
+            : base(client)
+        {
+        }
+        private String ProcessStrResult(String result)
+        {
+            String processed = result.Replace("|", "\r\n");
+            String processed2 = processed.Substring(0,processed.Length-4);
+            return processed2.Trim(new char[] { '\r', '\n', '|', ' ' });
+        }
+        private Boolean ProcessStrPassFail(String result)
+        {
+            Boolean bResult = false;
+            int index = result.IndexOf("Result: ");
+            String str = result.Substring(index + 8, 4).ToUpper();
+            if (str.CompareTo("PASS") == 0) return true; else return false;
+            return bResult;
+        }
+        public bool Test_S25FS512(out String strResult)
+        {
+            String testStr = "Testing S25FS512|ReadId: 23021F = Good|Format Sector 0 Test: Pass|Write Page 0 Test: Pass|Result: Pass";
+            //Boolean resultTest = ProcessStrPassFail(testStr);
+            //String processedStr = ProcessStrResult(testStr);
+            String result = Call(CLASSNAME, "Test_S25FS512");
+            strResult = ProcessStrResult(result);
+            return ProcessStrPassFail(result);
+        }
+        public bool Test_BMP280(out String strResult)
+        {
+            String result = Call(CLASSNAME, "Test_BMP280");
+            strResult = ProcessStrResult(result);
+            return ProcessStrPassFail(result);
+        }
+        public bool Test_LIS2DH(out String strResult)
+        {
+            String result = Call(CLASSNAME, "Test_LIS2DH");
+            strResult = ProcessStrResult(result);
+            return ProcessStrPassFail(result);
+        }
+        public bool Test_LSM6DS3(out String strResult)
+        {
+            String result = Call(CLASSNAME, "Test_LSM6DS3");
+            strResult = ProcessStrResult(result);
+            return ProcessStrPassFail(result);
+        }
+        public bool Test_MAX31725_1(out String strResult)
+        {
+            String result = Call(CLASSNAME, "Test_MAX31725_1");
+            strResult = ProcessStrResult(result);
+            return ProcessStrPassFail(result);
+        }
+        public bool Test_MAX31725_2(out String strResult)
+        {
+            String result = Call(CLASSNAME, "Test_MAX31725_2");
+            strResult = ProcessStrResult(result);
+            return ProcessStrPassFail(result);
+        }
+        public bool Test_MAX30101(out String strResult)
+        {
+            String result = Call(CLASSNAME, "Test_MAX30101");
+            strResult = ProcessStrResult(result);
+            return ProcessStrPassFail(result);
+        }
+        public bool Test_MAX30001(out String strResult)
+        {
+            String result = Call(CLASSNAME, "Test_MAX30001");
+            strResult = ProcessStrResult(result);
+            return ProcessStrPassFail(result);
+        }
+        public bool Test_EM9301(out String strResult)
+        {
+            String result = Call(CLASSNAME, "Test_EM9301");
+            strResult = ProcessStrResult(result);
+            return ProcessStrPassFail(result);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HspGuiSourceV301/GuiDLLs/RPCSupport/Dialogs/RpcLog.Designer.cs	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,126 @@
+namespace RPCSupport.Dialogs
+{
+    partial class RpcLog
+    {
+        /// <summary>
+        /// Required designer variable.
+        /// </summary>
+        private System.ComponentModel.IContainer components = null;
+
+        /// <summary>
+        /// Clean up any resources being used.
+        /// </summary>
+        /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
+        protected override void Dispose(bool disposing)
+        {
+            if (disposing && (components != null))
+            {
+                components.Dispose();
+            }
+            base.Dispose(disposing);
+        }
+
+        #region Windows Form Designer generated code
+
+        /// <summary>
+        /// Required method for Designer support - do not modify
+        /// the contents of this method with the code editor.
+        /// </summary>
+        private void InitializeComponent()
+        {
+            this.txt_Status = new System.Windows.Forms.TextBox();
+            this.label1 = new System.Windows.Forms.Label();
+            this.btn_Clear = new MaximStyle.MaximButton();
+            this.listBox1 = new System.Windows.Forms.ListBox();
+            this.btnSaveToFile = new MaximStyle.MaximButton();
+            this.SuspendLayout();
+            // 
+            // txt_Status
+            // 
+            this.txt_Status.Anchor = System.Windows.Forms.AnchorStyles.None;
+            this.txt_Status.BackColor = System.Drawing.Color.White;
+            this.txt_Status.Font = new System.Drawing.Font("Arial", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+            this.txt_Status.Location = new System.Drawing.Point(222, 12);
+            this.txt_Status.Multiline = true;
+            this.txt_Status.Name = "txt_Status";
+            this.txt_Status.ReadOnly = true;
+            this.txt_Status.ScrollBars = System.Windows.Forms.ScrollBars.Vertical;
+            this.txt_Status.Size = new System.Drawing.Size(60, 54);
+            this.txt_Status.TabIndex = 7;
+            this.txt_Status.TabStop = false;
+            this.txt_Status.Visible = false;
+            this.txt_Status.TextChanged += new System.EventHandler(this.txt_Status_TextChanged);
+            // 
+            // label1
+            // 
+            this.label1.AutoSize = true;
+            this.label1.Font = new System.Drawing.Font("Arial", 11.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+            this.label1.Location = new System.Drawing.Point(12, 17);
+            this.label1.Name = "label1";
+            this.label1.Size = new System.Drawing.Size(78, 17);
+            this.label1.TabIndex = 8;
+            this.label1.Text = "Status Log";
+            // 
+            // btn_Clear
+            // 
+            this.btn_Clear.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
+            this.btn_Clear.Location = new System.Drawing.Point(481, 12);
+            this.btn_Clear.Name = "btn_Clear";
+            this.btn_Clear.Size = new System.Drawing.Size(81, 22);
+            this.btn_Clear.TabIndex = 9;
+            this.btn_Clear.Text = "Clear Log";
+            this.btn_Clear.UseVisualStyleBackColor = true;
+            this.btn_Clear.Click += new System.EventHandler(this.btn_Clear_Click);
+            // 
+            // listBox1
+            // 
+            this.listBox1.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) 
+            | System.Windows.Forms.AnchorStyles.Left) 
+            | System.Windows.Forms.AnchorStyles.Right)));
+            this.listBox1.FormattingEnabled = true;
+            this.listBox1.Location = new System.Drawing.Point(15, 41);
+            this.listBox1.Name = "listBox1";
+            this.listBox1.Size = new System.Drawing.Size(547, 251);
+            this.listBox1.TabIndex = 10;
+            // 
+            // btnSaveToFile
+            // 
+            this.btnSaveToFile.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
+            this.btnSaveToFile.Location = new System.Drawing.Point(394, 13);
+            this.btnSaveToFile.Name = "btnSaveToFile";
+            this.btnSaveToFile.Size = new System.Drawing.Size(81, 22);
+            this.btnSaveToFile.TabIndex = 11;
+            this.btnSaveToFile.Text = "Save To File";
+            this.btnSaveToFile.UseVisualStyleBackColor = true;
+            this.btnSaveToFile.Click += new System.EventHandler(this.btnSaveToFile_Click);
+            // 
+            // RpcLog
+            // 
+            this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
+            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+            this.BackColor = System.Drawing.Color.White;
+            this.ClientSize = new System.Drawing.Size(574, 309);
+            this.Controls.Add(this.btnSaveToFile);
+            this.Controls.Add(this.listBox1);
+            this.Controls.Add(this.btn_Clear);
+            this.Controls.Add(this.txt_Status);
+            this.Controls.Add(this.label1);
+            this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.SizableToolWindow;
+            this.MaximizeBox = false;
+            this.MinimizeBox = false;
+            this.Name = "RpcLog";
+            this.Text = "RpcLog";
+            this.ResumeLayout(false);
+            this.PerformLayout();
+
+        }
+
+        #endregion
+
+        private System.Windows.Forms.TextBox txt_Status;
+        private System.Windows.Forms.Label label1;
+        private MaximStyle.MaximButton btn_Clear;
+        private System.Windows.Forms.ListBox listBox1;
+        private MaximStyle.MaximButton btnSaveToFile;
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HspGuiSourceV301/GuiDLLs/RPCSupport/Dialogs/RpcLog.cs	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,155 @@
+/*******************************************************************************
+* Copyright (C) 2016 Maxim Integrated Products, Inc., All rights Reserved.
+* 
+* This software is protected by copyright laws of the United States and
+* of foreign countries. This material may also be protected by patent laws
+* and technology transfer regulations of the United States and of foreign
+* countries. This software is furnished under a license agreement and/or a
+* nondisclosure agreement and may only be used or reproduced in accordance
+* with the terms of those agreements. Dissemination of this information to
+* any party or parties not specified in the license agreement and/or
+* nondisclosure agreement is expressly prohibited.
+*
+* The above copyright notice and this permission notice shall be included
+* in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+* OTHER DEALINGS IN THE SOFTWARE.
+*
+* Except as contained in this notice, the name of Maxim Integrated
+* Products, Inc. shall not be used except as stated in the Maxim Integrated
+* Products, Inc. Branding Policy.
+*
+* The mere transfer of this software does not imply any licenses
+* of trade secrets, proprietary technology, copyrights, patents,
+* trademarks, maskwork rights, or any other form of intellectual
+* property whatsoever. Maxim Integrated Products, Inc. retains all
+* ownership rights.
+*******************************************************************************
+*/
+
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Data;
+using System.Drawing;
+using System.Linq;
+using System.Text;
+using System.Windows.Forms;
+using System.IO;
+using System.Text.RegularExpressions;
+
+namespace RPCSupport.Dialogs
+{
+    public partial class RpcLog : Form
+    {
+        public RpcLog()
+        {
+            InitializeComponent();
+        }
+
+        private const int CP_NOCLOSE_BUTTON = 0x200;
+        protected override CreateParams CreateParams
+        {
+            get
+            {
+                CreateParams myCp = base.CreateParams;
+                myCp.ClassStyle = myCp.ClassStyle | CP_NOCLOSE_BUTTON;
+                return myCp;
+            }
+        }
+
+        internal void LogRpcRequest(string request)
+        {
+            //txt_Status.Text += request;
+            SetTextListBox(request + " ");
+        }
+
+        internal void LogRpcReply(string reply)
+        {
+            //txt_Status.Text += reply + "\r\n";
+            SetTextListBox(reply + " ");
+        }
+
+        delegate void SetTextCallback(string text);
+
+        private void SetText(string text)
+        {
+            // InvokeRequired required compares the thread ID of the
+            // calling thread to the thread ID of the creating thread.
+            // If these threads are different, it returns true.
+            if (this.txt_Status.InvokeRequired)
+            {
+                SetTextCallback d = new SetTextCallback(SetText);
+                this.Invoke(d, new object[] { text });
+            }
+            else
+            {
+                this.txt_Status.Text += text;
+                if (this.txt_Status.Text.Length > 2000) this.txt_Status.Text = "";
+            }
+        }
+
+        delegate void UpdateCCNetWindowDelegate(String msg);
+
+        private void SetTextListBox(String message)
+        {
+            // Check whether the caller must call an invoke method when making method calls to listBoxCCNetOutput because the caller is 
+            // on a different thread than the one the listBoxCCNetOutput control was created on.
+            if (listBox1.InvokeRequired)
+            {
+                UpdateCCNetWindowDelegate update = new UpdateCCNetWindowDelegate(SetTextListBox);
+                listBox1.Invoke(update, message);
+            }
+            else
+            {
+                listBox1.Items.Add(message);
+                if (listBox1.Items.Count > 10000)
+                {
+                    listBox1.Items.RemoveAt(0); // remove first line
+                }
+                // Make sure the last item is made visible
+                listBox1.SelectedIndex = listBox1.Items.Count - 1;
+                listBox1.ClearSelected();
+            }
+        }
+
+
+        internal void LogRpcStream(string stream)
+        {
+            //txt_Status.Text += stream + " ";
+            SetTextListBox(stream + " ");
+        }
+
+        private void btn_Clear_Click(object sender, EventArgs e)
+        {
+            //txt_Status.Text = "";
+            listBox1.Items.Clear();
+        }
+
+        private void txt_Status_TextChanged(object sender, EventArgs e)
+        {
+
+        }
+
+        private void btnSaveToFile_Click(object sender, EventArgs e)
+        {
+            SaveFileDialog saveFileDialog = new SaveFileDialog();
+            DialogResult result = saveFileDialog.ShowDialog();
+            if (result == System.Windows.Forms.DialogResult.OK)
+            {
+                StreamWriter sw = new StreamWriter(saveFileDialog.FileName); 
+                for (int i = 0; i < listBox1.Items.Count; i++)
+                {
+                    sw.WriteLine(Regex.Replace(listBox1.Items[i].ToString(), @"\r\n?|\n", ""));
+                }
+                sw.Close();
+            }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HspGuiSourceV301/GuiDLLs/RPCSupport/Dialogs/RpcLog.resx	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,120 @@
+<?xml version="1.0" encoding="utf-8"?>
+<root>
+  <!-- 
+    Microsoft ResX Schema 
+    
+    Version 2.0
+    
+    The primary goals of this format is to allow a simple XML format 
+    that is mostly human readable. The generation and parsing of the 
+    various data types are done through the TypeConverter classes 
+    associated with the data types.
+    
+    Example:
+    
+    ... ado.net/XML headers & schema ...
+    <resheader name="resmimetype">text/microsoft-resx</resheader>
+    <resheader name="version">2.0</resheader>
+    <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+    <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+    <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
+    <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+    <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+        <value>[base64 mime encoded serialized .NET Framework object]</value>
+    </data>
+    <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+        <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
+        <comment>This is a comment</comment>
+    </data>
+                
+    There are any number of "resheader" rows that contain simple 
+    name/value pairs.
+    
+    Each data row contains a name, and value. The row also contains a 
+    type or mimetype. Type corresponds to a .NET class that support 
+    text/value conversion through the TypeConverter architecture. 
+    Classes that don't support this are serialized and stored with the 
+    mimetype set.
+    
+    The mimetype is used for serialized objects, and tells the 
+    ResXResourceReader how to depersist the object. This is currently not 
+    extensible. For a given mimetype the value must be set accordingly:
+    
+    Note - application/x-microsoft.net.object.binary.base64 is the format 
+    that the ResXResourceWriter will generate, however the reader can 
+    read any of the formats listed below.
+    
+    mimetype: application/x-microsoft.net.object.binary.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
+            : and then encoded with base64 encoding.
+    
+    mimetype: application/x-microsoft.net.object.soap.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+            : and then encoded with base64 encoding.
+
+    mimetype: application/x-microsoft.net.object.bytearray.base64
+    value   : The object must be serialized into a byte array 
+            : using a System.ComponentModel.TypeConverter
+            : and then encoded with base64 encoding.
+    -->
+  <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+    <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
+    <xsd:element name="root" msdata:IsDataSet="true">
+      <xsd:complexType>
+        <xsd:choice maxOccurs="unbounded">
+          <xsd:element name="metadata">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" />
+              </xsd:sequence>
+              <xsd:attribute name="name" use="required" type="xsd:string" />
+              <xsd:attribute name="type" type="xsd:string" />
+              <xsd:attribute name="mimetype" type="xsd:string" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="assembly">
+            <xsd:complexType>
+              <xsd:attribute name="alias" type="xsd:string" />
+              <xsd:attribute name="name" type="xsd:string" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="data">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+                <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
+              <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+              <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="resheader">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" />
+            </xsd:complexType>
+          </xsd:element>
+        </xsd:choice>
+      </xsd:complexType>
+    </xsd:element>
+  </xsd:schema>
+  <resheader name="resmimetype">
+    <value>text/microsoft-resx</value>
+  </resheader>
+  <resheader name="version">
+    <value>2.0</value>
+  </resheader>
+  <resheader name="reader">
+    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <resheader name="writer">
+    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+</root>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HspGuiSourceV301/GuiDLLs/RPCSupport/HidSupport/FileIODeclarations.cs	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,113 @@
+/*******************************************************************************
+* Copyright (C) 2016 Maxim Integrated Products, Inc., All rights Reserved.
+* 
+* This software is protected by copyright laws of the United States and
+* of foreign countries. This material may also be protected by patent laws
+* and technology transfer regulations of the United States and of foreign
+* countries. This software is furnished under a license agreement and/or a
+* nondisclosure agreement and may only be used or reproduced in accordance
+* with the terms of those agreements. Dissemination of this information to
+* any party or parties not specified in the license agreement and/or
+* nondisclosure agreement is expressly prohibited.
+*
+* The above copyright notice and this permission notice shall be included
+* in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+* OTHER DEALINGS IN THE SOFTWARE.
+*
+* Except as contained in this notice, the name of Maxim Integrated
+* Products, Inc. shall not be used except as stated in the Maxim Integrated
+* Products, Inc. Branding Policy.
+*
+* The mere transfer of this software does not imply any licenses
+* of trade secrets, proprietary technology, copyrights, patents,
+* trademarks, maskwork rights, or any other form of intellectual
+* property whatsoever. Maxim Integrated Products, Inc. retains all
+* ownership rights.
+*******************************************************************************
+*/
+
+using System;
+using Microsoft.Win32.SafeHandles; 
+using System.Runtime.InteropServices;
+//using System.Threading;
+
+//----------------------------------------------------------------------
+// MSVC reports Warning: XML comment is not placed on a valid language element.
+// MSVC does not support attaching documentation to namespaces.
+// But doxygen does, so this isn't an issue.
+//----------------------------------------------------------------------
+// warning CS1587: XML comment is not placed on a valid language element
+#pragma warning disable 1587
+///  <summary>
+/// @file FileIODeclarations.cs
+/// @brief API declarations relating to file I/O.
+/// 
+/// 
+///  </summary>
+//----------------------------------------------------------------------
+#pragma warning restore 1587
+
+//------------------------------------------------------------------------------------------
+// OS24EVK-59 split into HeartRateApp EXE and MAX30101 DLL.
+// Moved all MAX30101 DLL classes into namespace Maxim.MAX30101GUI
+// Moved all HeartRateApp GUI classes into namespace Maxim.MAX30101
+// OS24EVK-59 Create separate project that builds Maxim.MAX30101GUI DLL library
+
+// OS24EVK-59 moved class FileIO into namespace Maxim.MAX30101 instead of namespace HeartRateApp
+namespace RPCSupport
+{   
+    internal sealed class FileIO 
+    {
+        internal const Int32 FILE_FLAG_OVERLAPPED = 0X40000000; 
+        internal const Int32 FILE_SHARE_READ = 1; 
+        internal const Int32 FILE_SHARE_WRITE = 2; 
+        internal const UInt32 GENERIC_READ = 0X80000000; 
+        internal const UInt32 GENERIC_WRITE = 0X40000000; 
+        internal const Int32 INVALID_HANDLE_VALUE = -1; 
+        internal const Int32 OPEN_EXISTING = 3; 
+        internal const Int32 WAIT_TIMEOUT = 0X102;
+		internal const Int32 WAIT_OBJECT_0 = 0;         
+    
+        [ StructLayout( LayoutKind.Sequential ) ]
+        internal class SECURITY_ATTRIBUTES  
+        { 
+            internal Int32 nLength; 
+            internal Int32 lpSecurityDescriptor; 
+            internal Int32 bInheritHandle; 
+        }    
+        
+        [ DllImport( "kernel32.dll", SetLastError=true ) ]
+		internal static extern bool CancelIo(SafeFileHandle hFile);        
+        
+        [ DllImport( "kernel32.dll", CharSet=CharSet.Auto, SetLastError=true ) ]
+        internal static extern IntPtr CreateEvent(IntPtr SecurityAttributes, Boolean bManualReset, Boolean bInitialState, String lpName);
+       
+        [ DllImport( "kernel32.dll", CharSet=CharSet.Auto, SetLastError=true ) ]
+        internal static extern SafeFileHandle CreateFile(String lpFileName, UInt32 dwDesiredAccess, Int32 dwShareMode, IntPtr lpSecurityAttributes, Int32 dwCreationDisposition, Int32 dwFlagsAndAttributes, Int32 hTemplateFile);
+
+        [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
+        internal static extern int FormatMessage (Int32 dwFlags, Int32 lpSource, Int32 dwMessageId, Int32 dwLanguageZId, string lpBuffer, Int32 nSize, Int32 Arguments);
+    
+		[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
+		internal static extern bool GetOverlappedResult(SafeFileHandle hFile, IntPtr lpOverlapped, ref Int32 lpNumberOfBytesTransferred, Boolean bWait);       
+
+        [ DllImport( "kernel32.dll", SetLastError=true ) ]
+        internal static extern bool ReadFile(SafeFileHandle hFile, IntPtr lpBuffer, Int32 nNumberOfBytesToRead, ref Int32 lpNumberOfBytesRead, IntPtr lpOverlapped);
+
+        [DllImport("kernel32.dll", SetLastError = true)]
+        internal static extern void Sleep(UInt32 dwMilliseconds);
+
+        [ DllImport( "kernel32.dll", SetLastError=true ) ]
+        internal static extern Int32 WaitForSingleObject(IntPtr hHandle, Int32 dwMilliseconds);        
+       
+        [ DllImport( "kernel32.dll", SetLastError=true ) ]
+        internal static extern bool WriteFile(SafeFileHandle hFile, IntPtr lpBuffer, Int32 nNumberOfBytesToWrite, ref Int32 lpNumberOfBytesWritten, IntPtr lpOverlapped);
+    }     
+} 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HspGuiSourceV301/GuiDLLs/RPCSupport/HidSupport/HID.cs	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,2143 @@
+/*******************************************************************************
+* Copyright (C) 2016 Maxim Integrated Products, Inc., All rights Reserved.
+* 
+* This software is protected by copyright laws of the United States and
+* of foreign countries. This material may also be protected by patent laws
+* and technology transfer regulations of the United States and of foreign
+* countries. This software is furnished under a license agreement and/or a
+* nondisclosure agreement and may only be used or reproduced in accordance
+* with the terms of those agreements. Dissemination of this information to
+* any party or parties not specified in the license agreement and/or
+* nondisclosure agreement is expressly prohibited.
+*
+* The above copyright notice and this permission notice shall be included
+* in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+* OTHER DEALINGS IN THE SOFTWARE.
+*
+* Except as contained in this notice, the name of Maxim Integrated
+* Products, Inc. shall not be used except as stated in the Maxim Integrated
+* Products, Inc. Branding Policy.
+*
+* The mere transfer of this software does not imply any licenses
+* of trade secrets, proprietary technology, copyrights, patents,
+* trademarks, maskwork rights, or any other form of intellectual
+* property whatsoever. Maxim Integrated Products, Inc. retains all
+* ownership rights.
+*******************************************************************************
+*/
+
+using System;
+using System.Collections;
+using System.Threading;
+using System.IO;
+using System.Windows.Forms;
+using System.Runtime.InteropServices;
+using Microsoft.Win32.SafeHandles;
+using System.Text;
+
+//------------------------------------------------------------------------------------------
+// OS24EVK-59 split into HeartRateApp EXE and MAX30101 DLL.
+// Moved all MAX30101 DLL classes into namespace Maxim.MAX30101GUI
+// Moved all HeartRateApp GUI classes into namespace Maxim.MAX30101
+// OS24EVK-59 Create separate project that builds Maxim.MAX30101GUI DLL library
+
+// OS24EVK-59 moved class HID into namespace Maxim.MAX30101 instead of namespace HeartRateApp
+namespace RPCSupport
+{
+#pragma warning disable 1574
+    /// <summary>
+    /// USB Human Interface Device functions to connect to EV kit without requiring a custom device driver
+    /// </summary>
+#pragma warning restore 1574
+    internal class HID
+    {
+
+        #region Globals
+        private IntPtr EventObject;
+        private System.Threading.NativeOverlapped managedOverlapped;
+        private IntPtr nonManagedOverlapped;
+        private IntPtr nonManagedBuffer;
+        public SafeFileHandle writeHandle;
+        public ArrayList writeHandleArray = new ArrayList();
+        public SafeFileHandle readHandle;
+        public ArrayList readHandleArray = new ArrayList();
+        public ArrayList desiredHIDPathNameArray = new ArrayList();
+
+        public const int DEFAULT_VENDOR_ID = 0x0B6A; // update USB VID PID from default Vid_16C0&Pid_0830
+        public const int DEFAULT_PRODUCT_ID = 0x1366; // MAX30100EVKit USB Vid_0B6A&Pid_1364; MAX30101EVKit USB Vid_0B6A&Pid_1365
+        public const byte DEFAULT_I2C_ADDRESS = 0xAE;   // 8-bit address (write address)
+
+        public String deviceID = System.String.Format("Vid_{0:x4}&Pid_{1:x4}", DEFAULT_VENDOR_ID, DEFAULT_PRODUCT_ID);
+
+        private bool explicit_report_id = false;
+        private const byte DEFAULT_REPORT_ID = 0;
+        private const byte SHORT_REPORT_ID = 1;
+        public const byte HID_REPORT_ID_1 = 1; // MAX30101 optical data, 3 bytes per channel, up to 3 channels per sample
+        public const byte HID_REPORT_ID_2 = 2; // LIS2DH accelerometer data, 2 bytes per channel, 3 channels per sample
+        public const byte HID_REPORT_ID_3 = 3; // reserved
+        private const byte USB_OVERFLOW = 8;
+        private const byte USB_WRITE_ERROR = 4;
+        private const byte USB_READ_ERROR = 2;
+        public const byte I2C_NACK_ERROR = 1;
+        private const byte API_FAIL = 0;     //API functions return non-0 upon success, to easily denote 'true' for C programs
+        private const byte I2C_SUCCESS = 3;  //we'll also use a non-0 value to denote success, since returning a '0' would lead to trouble when mixed with API's returns.
+        private const byte GP_SUCCESS = 3;
+        private const byte GP_FAIL = 0;
+        private const byte REPORT_SIZE = 65;
+
+        #region I2C clock speeds
+        public const byte I2C_ClOCK_100KHz = 0;
+        public const byte I2C_ClOCK_400KHz = 1;
+        public const byte I2C_ClOCK_1MHz = 2;
+
+        #endregion
+
+        #region Command Codes
+        private const byte COMMAND_SUCCESS = 0xEE;
+        private const byte COMMAND_FAILED = 0xFF;
+
+        private const byte GET_FIRMWARE_VERSION = 0x00;
+        private const byte SET_LED = 0x01;
+        private const byte I2C_INIT = 0x03;
+        private const byte I2C_CONFIG = 0x04;
+        private const byte I2C_TRANSACTION	= 0x06;
+        #endregion
+        // verify: https://jira.maxim-ic.com/browse/OS24EVK-57 mutex lock HID.IOBuf[] before FlushQueue()
+        // mutexGuardIOBuf.WaitOne();   // Wait until it is safe to enter.
+        // mutexGuardIOBuf.ReleaseMutex();    // Release the Mutex.
+        public static Mutex mutexGuardIOBuf = new Mutex();
+        // TODO1: OS24EVK-57 2015-04-01 myHID.readHID2() needs to return result into IOBuf. But IOBuf = new byte[64], do we replace with IOBuf = new byte[128]? Does this affect readHID()?
+        public byte[] IOBuf = new byte[REPORT_SIZE];
+
+        private const int IOtimeout = 10000;
+
+        // API declarations relating to device management (SetupDixxx and 
+        // RegisterDeviceNotification functions).   
+
+        // from dbt.h
+
+        internal const Int32 DBT_DEVNODES_CHANGED = 7; 
+        internal const Int32 DBT_DEVICEARRIVAL = 0X8000;
+        internal const Int32 DBT_DEVICEREMOVECOMPLETE = 0X8004;
+        internal const Int32 DBT_DEVTYP_DEVICEINTERFACE = 5;
+        internal const Int32 DBT_DEVTYP_HANDLE = 6;
+        internal const Int32 DEVICE_NOTIFY_ALL_INTERFACE_CLASSES = 4;
+        internal const Int32 DEVICE_NOTIFY_SERVICE_HANDLE = 1;
+        internal const Int32 DEVICE_NOTIFY_WINDOW_HANDLE = 0;
+        internal const Int32 WM_DEVICECHANGE = 0X219;
+        internal const Int32 SPDRP_HARDWAREID = 1;
+
+        // from setupapi.h
+
+        internal const Int32 DIGCF_PRESENT = 2;
+        internal const Int32 DIGCF_DEVICEINTERFACE = 0X10;
+        #endregion
+
+        #region Variable Stuctures
+        // Two declarations for the DEV_BROADCAST_DEVICEINTERFACE structure.
+
+        // Use this one in the call to RegisterDeviceNotification() and
+        // in checking dbch_devicetype in a DEV_BROADCAST_HDR structure:
+
+        [StructLayout(LayoutKind.Sequential)]
+        internal class DEV_BROADCAST_DEVICEINTERFACE
+        {
+            internal Int32 dbcc_size;
+            internal Int32 dbcc_devicetype;
+            internal Int32 dbcc_reserved;
+            internal Guid dbcc_classguid;
+            internal Int16 dbcc_name;
+        }
+
+        // Use this to read the dbcc_name String and classguid:
+
+        [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
+        internal class DEV_BROADCAST_DEVICEINTERFACE_1
+        {
+            internal Int32 dbcc_size;
+            internal Int32 dbcc_devicetype;
+            internal Int32 dbcc_reserved;
+            [MarshalAs(UnmanagedType.ByValArray, ArraySubType = UnmanagedType.U1, SizeConst = 16)]
+            internal Byte[] dbcc_classguid;
+            [MarshalAs(UnmanagedType.ByValArray, SizeConst = 255)]
+            internal Char[] dbcc_name;
+        }
+
+        [StructLayout(LayoutKind.Sequential)]
+        internal class DEV_BROADCAST_HDR
+        {
+            internal Int32 dbch_size;
+            internal Int32 dbch_devicetype;
+            internal Int32 dbch_reserved;
+        }
+
+        internal struct SP_DEVICE_INTERFACE_DATA        
+        {
+            internal Int32 cbSize;
+            internal System.Guid InterfaceClassGuid;
+            internal Int32 Flags;
+            internal IntPtr Reserved;
+        }
+
+        //[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
+        //internal struct SP_DEVICE_INTERFACE_DETAIL_DATA
+        //{
+        //    internal Int32 cbSize;
+        //    //internal String DevicePath;            
+        //    internal Char[] DevicePath;
+        //}
+
+// warning CS0649: Field 'Maxim.MAX30101.HID.SP_DEVINFO_DATA.cbSize' is never assigned to, and will always have its default value 0
+#pragma warning disable 0649
+        internal struct SP_DEVINFO_DATA
+        {
+            internal Int32 cbSize;
+            internal System.Guid ClassGuid;
+            internal Int32 DevInst;
+            internal Int32 Reserved;
+        }
+#pragma warning restore 0649
+        #endregion
+
+        #region External Functions from dll
+        //HDEVINFO SetupDiGetClassDevs(const GUID *ClassGuid, PCTSTR Enumerator, HWND hwndParent, DWORD Flags);
+        [DllImport("setupapi.dll", SetLastError = true, CharSet = CharSet.Auto)]
+        internal static extern IntPtr SetupDiGetClassDevs(ref System.Guid ClassGuid, IntPtr Enumerator, IntPtr hwndParent, Int32 Flags);
+
+        //BOOL SetupDiDestroyDeviceInfoList(HDEVINFO DeviceInfoSet);
+        [DllImport("setupapi.dll", SetLastError = true)]
+        internal static extern Boolean SetupDiDestroyDeviceInfoList(IntPtr DeviceInfoSet);
+
+        //BOOL SetupDiEnumDeviceInterfaces(HDEVINFO DeviceInfoSet, PSP_DEVINFO_DATA DeviceInfoData, const GUID *InterfaceClassGuid, DWORD MemberIndex, PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData);
+        [DllImport("setupapi.dll", SetLastError = true)]
+        internal static extern Boolean SetupDiEnumDeviceInterfaces(IntPtr DeviceInfoSet, ref SP_DEVINFO_DATA DeviceInfoData, ref System.Guid InterfaceClassGuid, Int32 MemberIndex, ref SP_DEVICE_INTERFACE_DATA DeviceInterfaceData);
+        [DllImport("setupapi.dll", SetLastError = true)]
+        // required to pass DeviceInfoData=null
+        internal static extern Boolean SetupDiEnumDeviceInterfaces(IntPtr DeviceInfoSet, IntPtr DeviceInfoData, ref System.Guid InterfaceClassGuid, Int32 MemberIndex, ref SP_DEVICE_INTERFACE_DATA DeviceInterfaceData);
+
+        //BOOL SetupDiGetDeviceInterfaceDetail(HDEVINFO DeviceInfoSet, PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData, PSP_DEVICE_INTERFACE_DETAIL_DATA DeviceInterfaceDetailData, DWORD DeviceInterfaceDetailDataSize, PDWORD RequiredSize, PSP_DEVINFO_DATA DeviceInfoData);
+        //[DllImport("setupapi.dll", SetLastError = true, CharSet = CharSet.Auto)]
+        //internal  extern Boolean SetupDiGetDeviceInterfaceDetail(IntPtr DeviceInfoSet, ref SP_DEVICE_INTERFACE_DATA DeviceInterfaceData, ref SP_DEVICE_INTERFACE_DETAIL_DATA DeviceInterfaceDetailData, Int32 DeviceInterfaceDetailDataSize, ref Int32 RequiredSize, ref SP_DEVINFO_DATA DeviceInfoData);
+        //[DllImport("setupapi.dll", SetLastError = true, CharSet = CharSet.Auto)]
+        //// required to pass DeviceInfoData=null
+        //internal  extern Boolean SetupDiGetDeviceInterfaceDetail(IntPtr DeviceInfoSet, ref SP_DEVICE_INTERFACE_DATA DeviceInterfaceData, ref SP_DEVICE_INTERFACE_DETAIL_DATA DeviceInterfaceDetailData, Int32 DeviceInterfaceDetailDataSize, ref Int32 RequiredSize, IntPtr DeviceInfoData);
+        // cannot get SP_DEVICE_INTERFACE_DETAIL_DATA's DevicePath field to work properly, so use IntPtr instead of ref SP_DEVICE_INTERFACE_DATA
+        [DllImport("setupapi.dll", SetLastError = true, CharSet = CharSet.Auto)]
+        // required to pass DeviceInterfaceDetailData=null
+        internal static extern Boolean SetupDiGetDeviceInterfaceDetail(IntPtr DeviceInfoSet, ref SP_DEVICE_INTERFACE_DATA DeviceInterfaceData, IntPtr DeviceInterfaceDetailData, Int32 DeviceInterfaceDetailDataSize, ref Int32 RequiredSize, ref SP_DEVINFO_DATA DeviceInfoData); 
+        [DllImport("setupapi.dll", SetLastError = true, CharSet = CharSet.Auto)]
+        // required to pass DeviceInterfaceDetailData=null, DeviceInfoData=null
+        internal static extern Boolean SetupDiGetDeviceInterfaceDetail(IntPtr DeviceInfoSet, ref SP_DEVICE_INTERFACE_DATA DeviceInterfaceData, IntPtr DeviceInterfaceDetailData, Int32 DeviceInterfaceDetailDataSize, ref Int32 RequiredSize, IntPtr DeviceInfoData); 
+
+        //BOOL SetupDiEnumDeviceInfo(HDEVINFO DeviceInfoSet, DWORD MemberIndex, PSP_DEVINFO_DATA DeviceInfoData);
+        [DllImport("setupapi.dll", SetLastError = true)]
+        internal static extern Boolean SetupDiEnumDeviceInfo(IntPtr DeviceInfoSet, Int32 MemberIndex, ref SP_DEVINFO_DATA DevInfoData);
+
+        //BOOL SetupDiGetDeviceRegistryProperty(HDEVINFO DeviceInfoSet, PSP_DEVINFO_DATA DeviceInfoData, DWORD Property, PDWORD PropertyRegDataType, PBYTE PropertyBuffer, DWORD PropertyBufferSize, PDWORD RequiredSize);
+        [DllImport("setupapi.dll", SetLastError = true, CharSet = CharSet.Auto)]
+        internal static extern Boolean SetupDiGetDeviceRegistryProperty(IntPtr DeviceInfoSet, ref SP_DEVINFO_DATA DevInfoData, Int32 Property, IntPtr PropertyRegDataType, IntPtr PropertyBuffer, Int32 PropertyBufferSize, ref Int32 RequiredSize);
+        
+        [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
+        internal static extern IntPtr RegisterDeviceNotification(IntPtr hRecipient, IntPtr NotificationFilter, Int32 Flags);
+
+        [DllImport("user32.dll", SetLastError = true)]
+        internal static extern Boolean UnregisterDeviceNotification(IntPtr Handle);
+
+        //  API declarations for HID communications.
+
+        //  from hidpi.h
+        //  Typedef enum defines a set of integer constants for HidP_Report_Type
+
+        internal const Int16 HidP_Input = 0;
+        internal const Int16 HidP_Output = 1;
+        internal const Int16 HidP_Feature = 2;
+
+        [StructLayout(LayoutKind.Sequential)]
+        internal struct HIDD_ATTRIBUTES
+        {
+            internal Int32 Size;
+            internal UInt16 VendorID;
+            internal UInt16 ProductID;
+            internal UInt16 VersionNumber;
+        }
+
+        [DllImport("hid.dll", SetLastError = true)]
+        internal static extern Boolean HidD_FlushQueue(SafeFileHandle HidDeviceObject);
+
+        [DllImport("hid.dll", SetLastError = true)]
+        internal static extern Boolean HidD_GetAttributes(SafeFileHandle HidDeviceObject, ref HIDD_ATTRIBUTES Attributes);
+
+        [DllImport("hid.dll", SetLastError = true)]
+        internal static extern void HidD_GetHidGuid(ref System.Guid HidGuid);
+        #endregion
+
+        #region Setup HID
+        public void getHidGuid(ref System.Guid hidGuid)
+        {
+            DebugMessage = string.Format("{0} entered", System.Reflection.MethodInfo.GetCurrentMethod().Name);
+#if DEBUG
+            HidD_GetHidGuid(ref hidGuid);
+#else
+            try
+            {
+                HidD_GetHidGuid(ref hidGuid);
+            }
+            catch (Exception ex)
+            {
+                throw new Exception(ex.Message + Environment.NewLine + new System.Diagnostics.StackFrame().GetMethod().Name);
+            }
+#endif
+            DebugMessage = string.Format("{0} exited", System.Reflection.MethodInfo.GetCurrentMethod().Name);
+        }
+
+        public string DebugMessage;
+        //public void TraceMessage(string message,
+        //[System.Runtime.CompilerServices.CallerMemberName] string memberName = "",
+        //[System.Runtime.CompilerServices.CallerFilePath] string sourceFilePath = "",
+        //[System.Runtime.CompilerServices.CallerLineNumber] int sourceLineNumber = 0)
+        //{
+        //    Console.WriteLine("message: " + message);
+        //    Console.WriteLine("member name: " + memberName);
+        //    Console.WriteLine("source file path: " + sourceFilePath);
+        //    Console.WriteLine("source line number: " + sourceLineNumber);
+        //}
+
+        /// <summary>
+        /// FindDesiredHIDPathNamesFromGuid() only appends to desiredHIDPathNameArray. 
+        /// Desired HIDs that have been removed from the system are removed from desiredHIDPathNameArray in openHIDhandles
+        /// </summary>
+        /// <param name="myGuid"></param>
+        private void FindDesiredHIDPathNamesFromGuid(System.Guid myGuid)
+        {
+            DebugMessage = string.Format("{0} entered", System.Reflection.MethodInfo.GetCurrentMethod().Name);
+            // VERIFY: https://jira.maxim-ic.com/browse/OS24EVK-59 (intermittent) Matlab Exception Message: Arithmetic operation resulted in an overflow.
+            // But I never see this kind of exception thrown from within the C# GUI.
+            // HID.findHIDs() still raises the exception in Matlab, 
+            // Message: Arithmetic operation resulted in an overflow.
+            //
+            //    % Required: connect to MAX30101EVKIT hardware
+            //    fprintf('Connecting to MAX30101EVKIT hardware...\n');
+            //    for trial=0:2000
+            //        try
+            //            %pause(1) % delay at least 1 second
+            //            myMAX30101.myHID.findHIDs();
+            //            % Sometimes we get Error using MAX30101Example
+            //            %   If this happens, try clearing the workspace and run again.
+            //            % Message: Arithmetic operation resulted in an overflow.
+            //            % FindDesiredHIDPathNamesFromGuid
+            //            % findHIDs
+            //            % Source: MAX30101
+            //            % HelpLink:    
+            //            if (myMAX30101.myHID.isConnected())
+            //                break
+            //            end
+            //        catch me
+            //            % disp(me)
+            //        end
+            //    end
+            //
+            // If matlab does successfully connect to USB, it is able to get 
+            // streaming data through the PartialArrayIntAvailable event 
+            // handler -- even though it can't understand 
+            // System.Collections.ArrayList data, it does at least understand 
+            // Array<System.Int32> or int[] data.
+            //
+            Int32 memberIndex = 0;
+            Int32 bufferSize = 0;
+            IntPtr deviceInfoSet = new System.IntPtr();
+            SP_DEVICE_INTERFACE_DATA DeviceInterfaceData = new SP_DEVICE_INTERFACE_DATA();
+            IntPtr deviceInterfaceDetailDataBuffer = IntPtr.Zero;
+
+            // VERIFY: https://jira.maxim-ic.com/browse/OS24EVK-59 (intermittent) Matlab Exception Message: Arithmetic operation resulted in an overflow.
+            // diagnostic: trying to avoid "Arithmetic overflow" from matlab. Limit the number of HID devices to be checked.
+            const int memberIndexLimit = 100;
+            
+#if DEBUG
+#else
+            try
+            {
+#endif
+            DebugMessage = string.Format("{0} first deviceInfoSet = SetupDiGetClassDevs(ref myGuid, IntPtr.Zero, IntPtr.Zero, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);", System.Reflection.MethodInfo.GetCurrentMethod().Name);
+            deviceInfoSet = SetupDiGetClassDevs(ref myGuid, IntPtr.Zero, IntPtr.Zero, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);
+
+                memberIndex = 0;
+
+                // The cbSize element of the DeviceInterfaceData structure must be set to the structure's size in bytes. 
+                // The size is 28 bytes for 32-bit code and 32 bits for 64-bit code.
+                DeviceInterfaceData.cbSize = Marshal.SizeOf(DeviceInterfaceData);
+
+                while (memberIndex < memberIndexLimit)
+                {
+                    // Begin with memberIndex = 0 and increment through the device information set until no more devices are available.
+                    DebugMessage = string.Format("{0} memberIndex={1} first SetupDiEnumDeviceInterfaces ", System.Reflection.MethodInfo.GetCurrentMethod().Name, memberIndex);
+                    if (!SetupDiEnumDeviceInterfaces(deviceInfoSet, IntPtr.Zero, ref myGuid, memberIndex, ref DeviceInterfaceData))
+                    {
+                        break;
+                    }
+
+                    DebugMessage = string.Format("{0} memberIndex={1} first SetupDiGetDeviceInterfaceDetail ", System.Reflection.MethodInfo.GetCurrentMethod().Name, memberIndex);
+                    SetupDiGetDeviceInterfaceDetail(deviceInfoSet, ref DeviceInterfaceData, IntPtr.Zero, 0, ref bufferSize, IntPtr.Zero);
+                    //tempLastError = GetLastError();
+                    //if (tempLastError != ERROR_INSUFFICIENT_BUFFER)  // ERROR_INSUFFICIENT_BUFFER is expected on this first call
+                    //    break;
+                    //FIXME add error check
+
+                    // Allocate memory for the SP_DEVICE_INTERFACE_DETAIL_DATA structure using the returned buffer size.
+                    DebugMessage = string.Format("{0} memberIndex={1} Marshal.AllocHGlobal(bufferSize) ", System.Reflection.MethodInfo.GetCurrentMethod().Name, memberIndex);
+                    deviceInterfaceDetailDataBuffer = Marshal.AllocHGlobal(bufferSize);
+                    // Returns a System.IntPtr pointer to the newly allocated global heap memory.
+                    // This memory must be released using the Marshal.FreeHGlobal method.
+                    // Marshal.AllocHGlobal(numBytes) could throw OutOfMemoryException ?
+
+                    // Store cbSize in the first bytes of the array. The number of bytes varies with 32- and 64-bit systems.
+                    DebugMessage = string.Format("{0} memberIndex={1} Marshal.WriteInt32 ", System.Reflection.MethodInfo.GetCurrentMethod().Name, memberIndex);
+                    Marshal.WriteInt32(deviceInterfaceDetailDataBuffer, (IntPtr.Size == 4) ? (4 + Marshal.SystemDefaultCharSize) : 8);
+
+                    // Call SetupDiGetDeviceInterfaceDetail again.
+                    // This time, pass a pointer to DetailDataBuffer and the returned required buffer size.
+                    DebugMessage = string.Format("{0} memberIndex={1} second SetupDiGetDeviceInterfaceDetail ", System.Reflection.MethodInfo.GetCurrentMethod().Name, memberIndex);
+                    if (!SetupDiGetDeviceInterfaceDetail(deviceInfoSet, ref DeviceInterfaceData, deviceInterfaceDetailDataBuffer, bufferSize, ref bufferSize, IntPtr.Zero))
+                        break;
+
+                    // Skip over cbsize (4 bytes) to get the address of the devicePathName.
+                    // VERIFY: https://jira.maxim-ic.com/browse/OS24EVK-59 (intermittent) Matlab Exception Message
+                    DebugMessage = string.Format("{0} memberIndex={1} IntPtr pDevicePathName = IntPtr.Add(deviceInterfaceDetailDataBuffer, 4); ", System.Reflection.MethodInfo.GetCurrentMethod().Name, memberIndex);
+                    IntPtr pDevicePathName = IntPtr.Add(deviceInterfaceDetailDataBuffer, 4);
+                    // DebugMessage = string.Format("{0} memberIndex={1} new IntPtr(deviceInterfaceDetailDataBuffer.ToInt32() + 4); ", System.Reflection.MethodInfo.GetCurrentMethod().Name, memberIndex);
+                    // BAD CODE. IntPtr pDevicePathName = new IntPtr(deviceInterfaceDetailDataBuffer.ToInt32() + 4);
+                    // BAD CODE. assumes the pointer is a 32-bit address, intermittently fails from 64-bit matlab client.
+
+                    // Get the String containing the devicePathName.
+                    DebugMessage = string.Format("{0} memberIndex={1} Marshal.PtrToStringAuto(pDevicePathName); ", System.Reflection.MethodInfo.GetCurrentMethod().Name, memberIndex);
+                    string tempPathName = Marshal.PtrToStringAuto(pDevicePathName);
+
+                    // match any device pathname that contains deviceID (case-insensitive match) "Vid_{0:x4}&Pid_{1:x4}"
+                    DebugMessage = string.Format("{0} memberIndex={1} if (tempPathName.ToLower().IndexOf(deviceID.ToLower()) != -1) ", System.Reflection.MethodInfo.GetCurrentMethod().Name, memberIndex);
+                    if (tempPathName.ToLower().IndexOf(deviceID.ToLower()) != -1)
+                    {
+                        DebugMessage = string.Format("{0} memberIndex={1} desiredHIDPathNameArray.Add(tempPathName); ", System.Reflection.MethodInfo.GetCurrentMethod().Name, memberIndex);
+                        desiredHIDPathNameArray.Add(tempPathName);
+                    }
+
+                    DebugMessage = string.Format("{0} memberIndex={1} memberIndex = memberIndex + 1; ", System.Reflection.MethodInfo.GetCurrentMethod().Name, memberIndex);
+
+                    // VERIFY: https://jira.maxim-ic.com/browse/OS24EVK-59 (intermittent) Matlab Exception Message
+                    // why didn't they call Marshal.FreeHGlobal here, inside the while loop? Isn't this a memory leak?
+                    // Free the memory allocated previously by AllocHGlobal.
+                    if (deviceInterfaceDetailDataBuffer != IntPtr.Zero)
+                    {
+                        Marshal.FreeHGlobal(deviceInterfaceDetailDataBuffer);
+                        deviceInterfaceDetailDataBuffer = IntPtr.Zero;
+                    }
+                    
+                    memberIndex = memberIndex + 1;
+                }
+#if DEBUG
+                // Free the memory allocated previously by AllocHGlobal.
+                if (deviceInterfaceDetailDataBuffer != IntPtr.Zero)
+                    Marshal.FreeHGlobal(deviceInterfaceDetailDataBuffer);
+
+                if (deviceInfoSet != IntPtr.Zero)
+                    SetupDiDestroyDeviceInfoList(deviceInfoSet);
+#else
+            }
+            catch (Exception ex)
+            {
+                throw new Exception(ex.Message + Environment.NewLine + new System.Diagnostics.StackFrame().GetMethod().Name);
+            }
+            finally
+            {
+                // Free the memory allocated previously by AllocHGlobal.
+                if (deviceInterfaceDetailDataBuffer != IntPtr.Zero)
+                    Marshal.FreeHGlobal(deviceInterfaceDetailDataBuffer);
+
+                if (deviceInfoSet != IntPtr.Zero)
+                    SetupDiDestroyDeviceInfoList(deviceInfoSet);
+            }
+#endif
+                DebugMessage = string.Format("{0} exited", System.Reflection.MethodInfo.GetCurrentMethod().Name);
+        }
+
+        private void FindAllHIDPathNamesFromGuid(System.Guid myGuid, ArrayList allHIDPathNameArray)
+        {
+            DebugMessage = string.Format("{0} entered", System.Reflection.MethodInfo.GetCurrentMethod().Name);
+            // VERIFY: https://jira.maxim-ic.com/browse/OS24EVK-59 (intermittent) Matlab Exception Message: Arithmetic operation resulted in an overflow.
+            // But I never see this kind of exception thrown from within the C# GUI.
+            // HID.findHIDs() still raises the exception in Matlab, 
+            // Message: Arithmetic operation resulted in an overflow.
+            Int32 memberIndex = 0; 
+            Int32 bufferSize = 0;
+            IntPtr deviceInfoSet = new System.IntPtr();
+            SP_DEVICE_INTERFACE_DATA DeviceInterfaceData = new SP_DEVICE_INTERFACE_DATA(); 
+            IntPtr deviceInterfaceDetailDataBuffer = IntPtr.Zero;
+
+            // VERIFY: https://jira.maxim-ic.com/browse/OS24EVK-59 (intermittent) Matlab Exception Message: Arithmetic operation resulted in an overflow.
+            // diagnostic: trying to avoid "Arithmetic overflow" from matlab. Limit the number of HID devices to be checked.
+            const int memberIndexLimit = 100;
+            
+            
+#if DEBUG
+#else
+            try
+            {
+#endif
+            DebugMessage = string.Format("{0} first deviceInfoSet = SetupDiGetClassDevs(ref myGuid, IntPtr.Zero, IntPtr.Zero, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);", System.Reflection.MethodInfo.GetCurrentMethod().Name);
+            deviceInfoSet = SetupDiGetClassDevs(ref myGuid, IntPtr.Zero, IntPtr.Zero, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);
+
+                memberIndex = 0;
+
+                // The cbSize element of the DeviceInterfaceData structure must be set to the structure's size in bytes. 
+                // The size is 28 bytes for 32-bit code and 32 bits for 64-bit code.
+                DeviceInterfaceData.cbSize = Marshal.SizeOf(DeviceInterfaceData);
+
+                // VERIFY: https://jira.maxim-ic.com/browse/OS24EVK-59 (intermittent) Matlab Exception Message: Arithmetic operation resulted in an overflow.
+                while (memberIndex < memberIndexLimit)
+                {
+                    DebugMessage = string.Format("{0} memberIndex={1} first SetupDiEnumDeviceInterfaces ", System.Reflection.MethodInfo.GetCurrentMethod().Name, memberIndex);
+                    if (!SetupDiEnumDeviceInterfaces(deviceInfoSet, IntPtr.Zero, ref myGuid, memberIndex, ref DeviceInterfaceData))
+                    {
+                        break;
+                    }
+
+                    DebugMessage = string.Format("{0} memberIndex={1} first SetupDiGetDeviceInterfaceDetail ", System.Reflection.MethodInfo.GetCurrentMethod().Name, memberIndex);
+                    SetupDiGetDeviceInterfaceDetail(deviceInfoSet, ref DeviceInterfaceData, IntPtr.Zero, 0, ref bufferSize, IntPtr.Zero);
+
+                    // Allocate memory for the SP_DEVICE_INTERFACE_DETAIL_DATA structure using the returned buffer size.
+                    DebugMessage = string.Format("{0} memberIndex={1} Marshal.AllocHGlobal(bufferSize) ", System.Reflection.MethodInfo.GetCurrentMethod().Name, memberIndex);
+                    deviceInterfaceDetailDataBuffer = Marshal.AllocHGlobal(bufferSize);
+
+                    // Store cbSize in the first bytes of the array. The number of bytes varies with 32- and 64-bit systems.
+                    DebugMessage = string.Format("{0} memberIndex={1} Marshal.WriteInt32 ", System.Reflection.MethodInfo.GetCurrentMethod().Name, memberIndex);
+                    Marshal.WriteInt32(deviceInterfaceDetailDataBuffer, (IntPtr.Size == 4) ? (4 + Marshal.SystemDefaultCharSize) : 8);
+
+                    // Call SetupDiGetDeviceInterfaceDetail again.
+                    // This time, pass a pointer to deviceInterfaceDetailDataBuffer and the returned required buffer size.
+                    DebugMessage = string.Format("{0} memberIndex={1} second SetupDiGetDeviceInterfaceDetail ", System.Reflection.MethodInfo.GetCurrentMethod().Name, memberIndex);
+                    if (!SetupDiGetDeviceInterfaceDetail(deviceInfoSet, ref DeviceInterfaceData, deviceInterfaceDetailDataBuffer, bufferSize, ref bufferSize, IntPtr.Zero))
+                        break;
+
+                    // Skip over cbsize (4 bytes) to get the address of the devicePathName.
+                    // VERIFY: https://jira.maxim-ic.com/browse/OS24EVK-59 (intermittent) Matlab Exception Message
+                    DebugMessage = string.Format("{0} memberIndex={1} IntPtr pDevicePathName = IntPtr.Add(deviceInterfaceDetailDataBuffer, 4); ", System.Reflection.MethodInfo.GetCurrentMethod().Name, memberIndex);
+                    // example: IntPtr right way to add an offset (portable to 64-bit clients)
+                    IntPtr pDevicePathName = IntPtr.Add(deviceInterfaceDetailDataBuffer, 4);
+                    // DebugMessage = string.Format("{0} memberIndex={1} IntPtr pDevicePathName = new IntPtr(deviceInterfaceDetailDataBuffer.ToInt32() + 4); ", System.Reflection.MethodInfo.GetCurrentMethod().Name, memberIndex);
+                    // BAD CODE. IntPtr pDevicePathName = new IntPtr(deviceInterfaceDetailDataBuffer.ToInt32() + 4);
+                    // BAD CODE. assumes the pointer is a 32-bit address, intermittently fails from 64-bit matlab client.
+
+                    // Get the String containing the devicePathName.
+                    DebugMessage = string.Format("{0} memberIndex={1} Marshal.PtrToStringAuto(pDevicePathName); ", System.Reflection.MethodInfo.GetCurrentMethod().Name, memberIndex);
+                    allHIDPathNameArray.Add(Marshal.PtrToStringAuto(pDevicePathName));
+
+                    // VERIFY: https://jira.maxim-ic.com/browse/OS24EVK-59 (intermittent) Matlab Exception Message
+                    // why didn't they call Marshal.FreeHGlobal here, inside the while loop? Isn't this a memory leak?
+                    // Free the memory allocated previously by AllocHGlobal.
+                    if (deviceInterfaceDetailDataBuffer != IntPtr.Zero)
+                    {
+                        Marshal.FreeHGlobal(deviceInterfaceDetailDataBuffer);
+                        deviceInterfaceDetailDataBuffer = IntPtr.Zero;
+                    }
+                   
+                    memberIndex = memberIndex + 1;
+                }
+#if DEBUG
+                // Free the memory allocated previously by AllocHGlobal.
+                if (deviceInterfaceDetailDataBuffer != IntPtr.Zero)
+                    Marshal.FreeHGlobal(deviceInterfaceDetailDataBuffer);
+
+                if (deviceInfoSet != IntPtr.Zero)
+                    SetupDiDestroyDeviceInfoList(deviceInfoSet);
+#else
+            }
+            catch (Exception ex)
+            {
+                throw new Exception(ex.Message + Environment.NewLine + new System.Diagnostics.StackFrame().GetMethod().Name);
+            }
+            finally
+            {
+                // Free the memory allocated previously by AllocHGlobal.
+                if (deviceInterfaceDetailDataBuffer != IntPtr.Zero)                    
+                    Marshal.FreeHGlobal(deviceInterfaceDetailDataBuffer);                
+
+                if (deviceInfoSet != IntPtr.Zero)
+                    SetupDiDestroyDeviceInfoList(deviceInfoSet);
+            }
+#endif
+            DebugMessage = string.Format("{0} exited", System.Reflection.MethodInfo.GetCurrentMethod().Name);
+        }
+
+        public bool isConnected()
+        {
+            try
+            {
+                return desiredHIDPathNameArray.Count != 0 ? true : false;
+            }
+            catch (Exception ex)
+            {
+                throw new Exception(ex.Message + Environment.NewLine + new System.Diagnostics.StackFrame().GetMethod().Name);
+            }
+        }
+
+
+        /// <summary>
+        /// Called when a WM_DEVICECHANGE message has arrived,
+        /// indicating that a device has been attached or removed.
+        /// 
+        /// </summary>
+        /// <param name="m"> a message with information about the device </param>
+        /// <returns>true on HID device arrival or remove complete</returns>
+        public bool HandleWMDeviceChangeMessage(Message m)
+        {
+            // Example code:
+            // 
+            // <code>
+            // protected override void WndProc(ref Message m)
+            // {
+            //     if (myHID != null)
+            //     {
+            //         if (myHID.HandleWMDeviceChangeMessage(m) /* m.Msg == HID.WM_DEVICECHANGE */ )
+            //         {
+            //             // optional: handle newly arrived connection or surprise disconnect
+            //         }
+            //     }
+            //     // Let the base form process the message.
+            //     base.WndProc(ref m);
+            // }
+            // </code>
+            // 
+            // https://jira.maxim-ic.com/browse/OS24EVK-59 WndProc if HID.WM_DEVICECHANGE do HID.OnDeviceChange(Message m)
+            try
+            {
+                if (m.Msg == HID.WM_DEVICECHANGE)
+                {
+                    //if ((int)m.WParam == HID.DBT_DEVNODES_CHANGED)  //this always occurs when any USB device is attached/detached. Use this if not registering for device notifications.
+                    if (
+                            (   m.WParam.ToInt32() == HID.DBT_DEVICEARRIVAL 
+                            ||  m.WParam.ToInt32() == HID.DBT_DEVICEREMOVECOMPLETE
+                            ) 
+                        && 
+                            (m.LParam.ToInt32() != 0) 
+                        && 
+                            DeviceIDMatch(m)
+                       )
+                    {
+                        closeHIDhandles();
+                        findHIDs();
+                        // cboEVB_init();
+                        return true;
+                    }
+                }
+                return false;
+            }
+            catch (Exception ex)
+            {
+                throw new Exception(ex.Message + Environment.NewLine + new System.Diagnostics.StackFrame().GetMethod().Name);
+            }
+        }
+
+        /// <summary>
+        /// findHIDs() called upon startup or if a desired HID has been inserted or removed
+        /// </summary>
+        public void findHIDs()
+        {
+            DebugMessage = string.Format("{0} entered", System.Reflection.MethodInfo.GetCurrentMethod().Name);
+            ArrayList allHIDPathNameArray = new ArrayList();
+            System.Guid hidGuid = new System.Guid();
+
+            // https://jira.maxim-ic.com/browse/OS24EVK-59 (intermittent) Matlab Exception Message: Arithmetic operation resulted in an overflow.
+#if DEBUG
+#else
+            try
+            {
+#endif
+                HidD_GetHidGuid(ref hidGuid);
+                // FindDesiredHIDPathNamesFromGuid() builds desiredHIDPathNameArray which is a list of all desired HIDs in the system
+                // desiredHIDPathNameArray is a global list and is used to maintain the order of desired HIDs in the selection list. 
+                // USB ports have different priorities, and the user could have attached the first desired HID to a lower priority port. 
+                // Hence, when another desired HID is attached to a higher priority port, it will come earlier in allHIDPathNameArray, but it will be maintained in the same attachment order in desiredHIDPathNameArray.
+                // Note that desiredHIDPathNameArray is only appended to or deleted from; it is never recreated in whole.
+                // FIXME desiredHIDPathNameArray will get duplicate pathnames for desired HIDs that were already attached, but these will be removed by openHIDhandles() since they're in allHIDPathNameArray only once. 
+                // These duplicates pathnames are appended after the initial list, so they won't affect order.
+                FindDesiredHIDPathNamesFromGuid(hidGuid);
+                // FindAllHIDPathNamesFromGuid() builds allHIDPathNameArray which is a list of all HIDs in the system. It is recreated every time a desired HID is attached or removed.
+                FindAllHIDPathNamesFromGuid(hidGuid, allHIDPathNameArray);
+                // openHIDhandles() gets handles for all desired HIDs
+                // openHIDhandles() loops through all attached HIDs and checks for a match of each item in desiredHIDPathNameArray. This maintains the attachement order.
+                // If a previously attached HID has been removed, it won't be found in allHIDPathNameArray and it will be removed from desiredHIDPathNameArray.
+                openHIDhandles(allHIDPathNameArray);
+                if (desiredHIDPathNameArray.Count != 0)
+                {
+                    prepareForOverlappedTransfer();
+                }
+#if DEBUG
+#else
+            }
+            catch (Exception ex)
+            {
+                throw new Exception(ex.Message + Environment.NewLine + new System.Diagnostics.StackFrame().GetMethod().Name);
+            }
+#endif
+            DebugMessage = string.Format("{0} exited", System.Reflection.MethodInfo.GetCurrentMethod().Name);
+        }
+
+        private void openHIDhandles(ArrayList allHIDPathNameArray)
+        {
+            DebugMessage = string.Format("{0} entered", System.Reflection.MethodInfo.GetCurrentMethod().Name);
+            int desiredHIDPathNameArrayCounter;
+            int allHIDPathNameArrayCounter;
+            bool found_installed_device;
+            try
+            {
+                desiredHIDPathNameArrayCounter = 0;
+                while (desiredHIDPathNameArrayCounter < desiredHIDPathNameArray.Count) // count will change if a previously installed device has been removed, so don't use a for loop
+                {
+                    found_installed_device = false;
+                    allHIDPathNameArrayCounter = 0;
+                    while (allHIDPathNameArrayCounter < allHIDPathNameArray.Count)
+                    {
+                        if ((string)allHIDPathNameArray[allHIDPathNameArrayCounter] == (string)desiredHIDPathNameArray[desiredHIDPathNameArrayCounter])
+                        {
+                            writeHandle = FileIO.CreateFile((string)desiredHIDPathNameArray[desiredHIDPathNameArrayCounter], FileIO.GENERIC_READ | FileIO.GENERIC_WRITE, FileIO.FILE_SHARE_READ | FileIO.FILE_SHARE_WRITE, IntPtr.Zero, FileIO.OPEN_EXISTING, 0, 0);
+                            if (!(writeHandle.IsInvalid))
+                            {
+                                readHandle = FileIO.CreateFile((string)desiredHIDPathNameArray[desiredHIDPathNameArrayCounter], FileIO.GENERIC_READ | FileIO.GENERIC_WRITE, FileIO.FILE_SHARE_READ | FileIO.FILE_SHARE_WRITE, IntPtr.Zero, FileIO.OPEN_EXISTING, FileIO.FILE_FLAG_OVERLAPPED, 0);
+                                if (!(readHandle.IsInvalid))
+                                {
+                                    writeHandleArray.Add(writeHandle);
+                                    readHandleArray.Add(readHandle);
+                                    allHIDPathNameArray.RemoveAt(allHIDPathNameArrayCounter); // remove it so we don't repeatedly add it when we check for new devices (after we finish checking for previously installed devices)
+                                    found_installed_device = true;
+                                }
+                                else
+                                {
+                                    writeHandle.Close();
+                                    writeHandle = null;
+                                    readHandle = null;
+                                }
+                            }
+                            else
+                            {
+                                writeHandle = null;
+                                readHandle = null; 
+                            }
+                            break;
+                        }
+                        allHIDPathNameArrayCounter++;
+                    }
+                    if (found_installed_device == false)    // no match in all allHIDPathNameArray elements; the device has been removed so remove its pathname from desiredHIDPathNameArray. Don't use counter at max count to check if not found, since max count can change.
+                        desiredHIDPathNameArray.RemoveAt(desiredHIDPathNameArrayCounter);   // decrements count by 1; don't increment desiredHIDPathNameArrayCounter
+                    else
+                        desiredHIDPathNameArrayCounter++;
+                }
+            }
+            catch (Exception ex)
+            {
+                DebugMessage = string.Format("{0} exception {1}", System.Reflection.MethodInfo.GetCurrentMethod().Name, ex.Message + Environment.NewLine + new System.Diagnostics.StackFrame().GetMethod().Name);
+                throw new Exception(ex.Message + Environment.NewLine + new System.Diagnostics.StackFrame().GetMethod().Name);
+            }
+            DebugMessage = string.Format("{0} exited", System.Reflection.MethodInfo.GetCurrentMethod().Name);
+        }
+
+        
+
+        private void prepareForOverlappedTransfer()
+        {
+            try
+            {
+                EventObject = FileIO.CreateEvent(IntPtr.Zero, false, false, String.Empty);
+                managedOverlapped.OffsetLow = 0;
+                managedOverlapped.OffsetHigh = 0;
+                managedOverlapped.EventHandle = EventObject; // HIDOverlapped is the overlapped structure used in ReadFile; EventObject will be signaled upon completion of ReadFile
+                nonManagedOverlapped = Marshal.AllocHGlobal(Marshal.SizeOf(managedOverlapped));
+                Marshal.StructureToPtr(managedOverlapped, nonManagedOverlapped, false);
+
+                nonManagedBuffer = Marshal.AllocHGlobal(REPORT_SIZE);
+            }
+            catch (Exception ex)
+            {
+                throw new Exception(ex.Message + Environment.NewLine + new System.Diagnostics.StackFrame().GetMethod().Name);
+            }
+        }
+
+        ///  <summary>
+        ///  Requests to receive a notification when a device is attached or removed.
+        ///  </summary>
+        ///  
+        ///  <param name="formHandle"> handle to the window that will receive device events. </param>
+        ///  <param name="classGuid"> device interface GUID. </param>
+        ///  <param name="deviceNotificationHandle"> returned device notification handle. </param>
+        ///  
+        ///  <returns>
+        ///  True on success.
+        ///  </returns>
+        ///  
+        public Boolean RegisterForDeviceNotifications(IntPtr formHandle, Guid classGuid, ref IntPtr deviceNotificationHandle)
+        {
+            DEV_BROADCAST_DEVICEINTERFACE devBroadcastDeviceInterface = new DEV_BROADCAST_DEVICEINTERFACE();
+            IntPtr devBroadcastDeviceInterfaceBuffer = IntPtr.Zero;
+            Int32 size = 0;
+
+            try
+            {
+                size = Marshal.SizeOf(devBroadcastDeviceInterface);
+                devBroadcastDeviceInterface.dbcc_size = size;
+                devBroadcastDeviceInterface.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE;
+                devBroadcastDeviceInterface.dbcc_reserved = 0;
+                devBroadcastDeviceInterface.dbcc_classguid = classGuid;
+
+                // Allocate memory for the buffer that holds the DEV_BROADCAST_DEVICEINTERFACE structure.
+                devBroadcastDeviceInterfaceBuffer = Marshal.AllocHGlobal(size);
+
+                // Copy the DEV_BROADCAST_DEVICEINTERFACE structure to the buffer.
+                // Set fDeleteOld True to prevent memory leaks.
+                Marshal.StructureToPtr(devBroadcastDeviceInterface, devBroadcastDeviceInterfaceBuffer, true);
+
+                // ***
+                //  API function
+
+                //  summary
+                //  Request to receive notification messages when a device in an interface class
+                //  is attached or removed.
+
+                //  parameters 
+                //  Handle to the window that will receive device events.
+                //  Pointer to a DEV_BROADCAST_DEVICEINTERFACE to specify the type of 
+                //  device to send notifications for.
+                //  DEVICE_NOTIFY_WINDOW_HANDLE indicates the handle is a window handle.
+
+                //  Returns
+                //  Device notification handle or NULL on failure.
+                // ***
+
+                deviceNotificationHandle = RegisterDeviceNotification(formHandle, devBroadcastDeviceInterfaceBuffer, DEVICE_NOTIFY_WINDOW_HANDLE);
+
+                // Marshal data from the unmanaged block devBroadcastDeviceInterfaceBuffer to the managed object devBroadcastDeviceInterface
+                // why?
+                Marshal.PtrToStructure(devBroadcastDeviceInterfaceBuffer, devBroadcastDeviceInterface);
+
+                return deviceNotificationHandle.ToInt32() == IntPtr.Zero.ToInt32() ? false : true;
+            }
+            catch (Exception ex)
+            {
+                throw new Exception(ex.Message + Environment.NewLine + new System.Diagnostics.StackFrame().GetMethod().Name);
+            }
+            finally
+            {
+                // Free the memory allocated previously by AllocHGlobal.
+                if (devBroadcastDeviceInterfaceBuffer != IntPtr.Zero)
+                    Marshal.FreeHGlobal(devBroadcastDeviceInterfaceBuffer);
+            }
+        }
+
+        
+
+        public Boolean DeviceIDMatch(Message m)
+        {
+            Int32 stringSize;
+
+            try
+            {
+                DEV_BROADCAST_HDR devBroadcastHeader = new DEV_BROADCAST_HDR();
+                DEV_BROADCAST_DEVICEINTERFACE_1 devBroadcastDeviceInterface = new DEV_BROADCAST_DEVICEINTERFACE_1();
+
+                // The LParam parameter of Message is a pointer to a DEV_BROADCAST_HDR structure.
+                Marshal.PtrToStructure(m.LParam, devBroadcastHeader);
+                if ((devBroadcastHeader.dbch_devicetype == DBT_DEVTYP_DEVICEINTERFACE))
+                {
+                    // The dbch_devicetype parameter indicates that the event applies to a device interface.
+                    // So the structure in LParam is actually a DEV_BROADCAST_INTERFACE structure, 
+                    // which begins with a DEV_BROADCAST_HDR.
+
+                    // Obtain the number of characters in dbch_name by subtracting the 32 bytes
+                    // in the strucutre that are not part of dbch_name and dividing by 2 because there are 
+                    // 2 bytes per character.
+
+                    stringSize = System.Convert.ToInt32((devBroadcastHeader.dbch_size - 32) / 2);
+
+                    // The dbcc_name parameter of devBroadcastDeviceInterface contains the device name. 
+                    // Trim dbcc_name to match the size of the String.         
+
+                    devBroadcastDeviceInterface.dbcc_name = new Char[stringSize + 1];
+
+                    // Marshal data from the unmanaged block pointed to by m.LParam 
+                    // to the managed object devBroadcastDeviceInterface.
+
+                    Marshal.PtrToStructure(m.LParam, devBroadcastDeviceInterface);
+
+                    // Store the device name in a String.
+
+                    String DeviceNameString = new String(devBroadcastDeviceInterface.dbcc_name, 0, stringSize);
+
+                    // Compare the name of the newly attached device with the name of the device 
+                    // the application is accessing (deviceID).
+                    // Set ignorecase True.
+
+                    return (DeviceNameString.ToLower().IndexOf(deviceID.ToLower()) == -1) ? false : true;
+                }
+                else
+                    return false;
+            }
+            catch (Exception ex)
+            {
+                throw new Exception(ex.Message + Environment.NewLine + new System.Diagnostics.StackFrame().GetMethod().Name);
+            }
+        }
+        #endregion
+
+        #region Send/Receive HID reports
+
+        public void FlushQueue()
+        {
+            try
+            {
+                if (writeHandle == null)
+                {
+                    return;
+                }
+                if (readHandle == null)
+                {
+                    return;
+                }
+
+                HidD_FlushQueue(writeHandle);
+                HidD_FlushQueue(readHandle);
+            }
+            catch
+            {
+                throw new Exception(new System.Diagnostics.StackFrame().GetMethod().Name);
+            }
+        }
+
+        public void writeReadHID()
+        {
+            try
+            {
+                if (writeHandle == null)
+                {
+                    return;
+                }
+                if (readHandle == null)
+                {
+                    return;
+                }
+
+                writeHID();
+                readHID();
+            }
+            catch (Exception ex)
+            {
+                throw new Exception(ex.Message + Environment.NewLine + new System.Diagnostics.StackFrame().GetMethod().Name);
+            }
+        }
+
+        public void writeHID()
+        {
+            if (writeHandle == null)
+            {
+                return;
+            }
+            if (readHandle == null)
+            {
+                return;
+            }
+
+            int BytesSucceed;
+            bool api_status;
+
+            try
+            {
+                BytesSucceed = 0;
+                //Byte[] outputReportBuffer = new Byte[REPORT_SIZE];
+
+                //for (int i = 0; i < REPORT_SIZE; i++)
+                //    outputReportBuffer[i] = IOBuf[i];
+                //api_status = FileIO.WriteFile(writeHandle, outputReportBuffer, outputReportBuffer.Length, ref BytesSucceed, IntPtr.Zero);
+
+                Marshal.Copy(IOBuf, 0, nonManagedBuffer, REPORT_SIZE);
+                api_status = FileIO.WriteFile(writeHandle, nonManagedBuffer, REPORT_SIZE, ref BytesSucceed, IntPtr.Zero);
+                
+                //endpoint in interrupt at uC occurs after this WriteFile call since the in data is ready and the host takes it; endpoint in interrupt does not occur after ReadFile call
+
+                if (api_status == false)
+                {
+                    //MessageBox.Show(Err.LastDllError);
+                    throw new Exception(support.ResultOfAPICall("API WriteFile error"));
+                }
+            }
+            catch (Exception ex)
+            {
+                throw new Exception(ex.Message + new System.Diagnostics.StackFrame().GetMethod().Name);
+            }
+        }
+
+        public void readHID()
+        {
+            if (writeHandle == null)
+            {
+                return;
+            }
+            if (readHandle == null)
+            {
+                return;
+            }
+
+            int BytesSucceed;
+            bool api_status;
+            int status;
+
+            try
+            {
+                Array.Clear(IOBuf, 0, IOBuf.Length);
+
+                BytesSucceed = 0;
+
+                api_status = FileIO.ReadFile(readHandle, nonManagedBuffer, REPORT_SIZE, ref BytesSucceed, nonManagedOverlapped);
+                
+                if (api_status == false) 
+                {
+                    //MsgBox(Err.LastDllError)
+                    status = FileIO.WaitForSingleObject(EventObject, IOtimeout);                    
+
+                    if (status != FileIO.WAIT_OBJECT_0) 
+                    {
+                        api_status = FileIO.CancelIo(readHandle);
+                        throw new Exception(support.ResultOfAPICall("API ReadFile error"));
+                    }
+                    FileIO.GetOverlappedResult(readHandle, nonManagedOverlapped, ref BytesSucceed, false);
+                }
+
+                // TODO1: OS24EVK-57 2015-04-01 myHID.readHID2() needs to return result into IOBuf. But IOBuf = new byte[64], do we replace with IOBuf = new byte[128]? Does this affect readHID()?
+                if (BytesSucceed > IOBuf.Length)
+                {
+                    IOBuf = new byte[BytesSucceed];
+                    Array.Clear(IOBuf, 0, IOBuf.Length);
+                }
+                Marshal.Copy(nonManagedBuffer, IOBuf, 0, BytesSucceed);
+            }
+            catch (Exception ex)
+            {
+                throw new Exception(ex.Message + Environment.NewLine + new System.Diagnostics.StackFrame().GetMethod().Name);
+            }
+        }
+
+        public void readHID2() // this function is for testing multiple report read on a single ReadFile()
+        {
+            if (writeHandle == null)
+            {
+                return;
+            }
+            if (readHandle == null)
+            {
+                return;
+            }
+
+            int BytesSucceed;
+            bool api_status;
+            int status;
+
+            try
+            {
+                int size = 128;
+                //byte[] buf = new byte[size];
+                IntPtr nonManagedBuf = Marshal.AllocHGlobal(size);
+                //Array.Clear(buf, 0, size);
+
+                BytesSucceed = 0;
+
+                api_status = FileIO.ReadFile(readHandle, nonManagedBuf, size, ref BytesSucceed, nonManagedOverlapped);
+
+                if (api_status == false)
+                {
+                    //MsgBox(Err.LastDllError)
+                    status = FileIO.WaitForSingleObject(EventObject, IOtimeout);
+
+                    if (status != FileIO.WAIT_OBJECT_0)
+                    {
+                        api_status = FileIO.CancelIo(readHandle);
+                        throw new Exception(support.ResultOfAPICall("API ReadFile error"));
+                    }
+                    FileIO.GetOverlappedResult(readHandle, nonManagedOverlapped, ref BytesSucceed, false);
+                }
+
+                // TODO1: OS24EVK-57 2015-04-01 myHID.readHID2() needs to return result into IOBuf. But IOBuf = new byte[64], do we replace with IOBuf = new byte[128]? Does this affect readHID()?
+                if (BytesSucceed > IOBuf.Length)
+                {
+                    IOBuf = new byte[BytesSucceed];
+                    Array.Clear(IOBuf, 0, IOBuf.Length);
+                }
+                Marshal.Copy(nonManagedBuf, IOBuf, 0, BytesSucceed);
+                
+                if (nonManagedBuf != IntPtr.Zero)
+                    Marshal.FreeHGlobal(nonManagedBuffer);
+            }
+            catch (Exception ex)
+            {
+                throw new Exception(ex.Message + Environment.NewLine + new System.Diagnostics.StackFrame().GetMethod().Name);
+            }
+        }
+        #endregion
+
+        #region Close HID
+        public void closeHIDhandles()
+        {
+            try
+            {
+                if (desiredHIDPathNameArray.Count != 0)
+                {
+                    foreach (Object obj in writeHandleArray)
+                        ((SafeFileHandle)obj).Close();
+                    writeHandleArray.Clear();
+                    writeHandle = null;
+                    foreach (Object obj in readHandleArray)
+                        ((SafeFileHandle)obj).Close();
+                    readHandleArray.Clear();
+                    readHandle = null;
+                }
+            }
+            catch (Exception ex)
+            {
+                throw new Exception(ex.Message + Environment.NewLine + new System.Diagnostics.StackFrame().GetMethod().Name);
+            }
+        }
+        ///  <summary>
+        ///  Requests to stop receiving notification messages when a device in an
+        ///  interface class is attached or removed.
+        ///  </summary>
+        ///  
+        ///  <param name="deviceNotificationHandle"> handle returned previously by
+        ///  RegisterDeviceNotification. </param>
+
+        public void StopReceivingDeviceNotifications(IntPtr deviceNotificationHandle)
+        {
+            try
+            {
+                UnregisterDeviceNotification(deviceNotificationHandle);
+            }
+            catch (Exception ex)
+            {
+                throw new Exception(ex.Message + Environment.NewLine + new System.Diagnostics.StackFrame().GetMethod().Name);
+            }
+        }
+        public void freeHeap()
+        {
+            try
+            {
+                if (nonManagedBuffer != IntPtr.Zero)
+                    Marshal.FreeHGlobal(nonManagedBuffer);
+                if (nonManagedOverlapped != IntPtr.Zero)
+                    Marshal.FreeHGlobal(nonManagedOverlapped);
+            }
+            catch (Exception ex)
+            {
+                throw new Exception(ex.Message + Environment.NewLine + new System.Diagnostics.StackFrame().GetMethod().Name);
+            }
+        }
+        #endregion
+
+        #region Create Report
+        public void reportID()
+        {
+            try
+            {
+                if (explicit_report_id)
+                    IOBuf[0] = SHORT_REPORT_ID;     // explicit out report ID in HID's descriptor
+                else
+                    IOBuf[0] = DEFAULT_REPORT_ID;   // default report ID; this byte is dropped in transfer, so we don't really waste a byte transmitting it
+            }
+            catch (Exception ex)
+            {
+                throw new Exception(ex.Message + Environment.NewLine + new System.Diagnostics.StackFrame().GetMethod().Name);
+            }
+        }
+
+        #region I2C Commands
+
+        #region oldCommands
+        /*public int readI2C(byte deviceAddress, byte numDataBytes, byte numRegBytes, byte[] readData, byte[] reg, bool ignoreNACK = false)
+        {
+            //readData is passed back to caller with the read data
+            int status;
+            int i;
+
+            try
+            {
+                if (numDataBytes > REPORT_SIZE - 2) {
+                    throw new Exception("USB buffer overflow");
+                }
+
+                // verify: https://jira.maxim-ic.com/browse/OS24EVK-57 mutex lock HID.IOBuf[] in readI2C
+                mutexGuardIOBuf.WaitOne();   // Wait until it is safe to enter.
+                FlushQueue();
+                Array.Clear(IOBuf, 0, IOBuf.Length);
+
+                reportID();
+                IOBuf[1] = I2C_TRANSACTION;	// I2C transaction -- see usb_app.c int parseHIDReport(uint8_t *data_from_host, unsigned int len) 
+                IOBuf[2] = (byte)(deviceAddress | 1);     // set read bit
+                IOBuf[3] = numDataBytes;
+                IOBuf[4] = numRegBytes;
+                // TODO1: OS24EVK-57 HID readI2C no validation that numRegBytes == reg.Length ?
+                for (i = 0; i < numRegBytes; i++) {
+                    IOBuf[i + 5] = reg[i];
+                }
+
+                writeHID();
+                mutexGuardIOBuf.ReleaseMutex();    // Release the Mutex.
+
+                status = checkNACK();
+
+                // checkNACK also reads the data, assuming NACK didn't occur
+                if (status == I2C_NACK_ERROR && ignoreNACK == false) {
+                    throw new Exception("invalid I2C address");
+                }
+
+                for (i = 0; i < numDataBytes; i++) {
+                    readData[i] = IOBuf[i + 2];
+                }
+
+                return status;      // the caller will not need the return value if an exception is thrown
+            }
+            catch (Exception ex)
+            {
+                throw new Exception(ex.Message + Environment.NewLine + new System.Diagnostics.StackFrame().GetMethod().Name);
+            }
+        }*/
+
+        /*public void writeI2C(byte deviceAddress, byte numDataBytes, byte numRegBytes, byte[] data, byte[] reg, bool ignoreNACK = false)
+        {
+            int i;
+
+            try
+            {
+                if (numDataBytes > REPORT_SIZE - 5) {
+                    throw new Exception("USB buffer overflow");
+                }
+
+                // verify: https://jira.maxim-ic.com/browse/OS24EVK-57 mutex lock HID.IOBuf[] in writeI2C
+                mutexGuardIOBuf.WaitOne();   // Wait until it is safe to enter.
+                FlushQueue();
+                Array.Clear(IOBuf, 0, IOBuf.Length);
+
+                //send data to tell uC to do I2C read from slave
+                reportID();
+                IOBuf[1] = I2C_TRANSACTION;	// I2C transaction -- see usb_app.c int parseHIDReport(uint8_t *data_from_host, unsigned int len) 
+                IOBuf[2] = deviceAddress;
+                IOBuf[3] = numDataBytes;
+                IOBuf[4] = numRegBytes;
+                for (i = 0; i < numRegBytes; i++) {
+                    IOBuf[i + 5] = reg[i];
+                }
+                for (i = 0; i < numDataBytes; i++) {
+                    IOBuf[i + 5 + numRegBytes] = data[i];
+                }
+
+                writeHID();
+                mutexGuardIOBuf.ReleaseMutex();    // Release the Mutex.
+
+                if (checkNACK() == I2C_NACK_ERROR && ignoreNACK == false) {
+                    throw new Exception("invalid I2C address");
+                }
+            }
+            catch (Exception ex)
+            {
+                throw new Exception(ex.Message + Environment.NewLine + new System.Diagnostics.StackFrame().GetMethod().Name);
+            }
+        }
+
+        private int checkNACK()
+        {
+            // Check if I2C write was really succesful or a NACK occurred, since this is independent of USB success
+            // This function also reads all the data from the report. If NACK occured, the data is invalid.
+            try
+            {
+                readHID();
+                return (IOBuf[1] == 0 ? I2C_SUCCESS : I2C_NACK_ERROR);    // the caller will not need the return value if an exception is thrown
+            }
+            catch (Exception ex)
+            {
+                throw new Exception(ex.Message + Environment.NewLine + new System.Diagnostics.StackFrame().GetMethod().Name);
+            }
+        }*/
+
+        // only allows 2 byte data
+        /*public void setBitI2C(byte deviceAddress, int reg, byte range, int data, bool ignoreNACK = false)
+        {
+            int i;
+            
+            try
+            {
+                int LSb = range & 0xF;
+                int MSb = (range & 0xF0) >> 4;
+                if (MSb < LSb)
+                    throw new Exception("invalid bit range");
+                //if (numDataBytes > REPORT_SIZE - 5)
+                //    throw new Exception("USB buffer overflow");
+
+                // verify: https://jira.maxim-ic.com/browse/OS24EVK-57 mutex lock HID.IOBuf[] in setBitI2C
+                mutexGuardIOBuf.WaitOne();   // Wait until it is safe to enter.
+                FlushQueue();
+
+                Array.Clear(IOBuf, 0, IOBuf.Length);
+
+                //send data to tell uC to do I2C read from slave
+                reportID();
+                IOBuf[1] = I2C_TRANSACTION;	// I2C transaction -- see usb_app.c int parseHIDReport(uint8_t *data_from_host, unsigned int len) 
+                IOBuf[2] = deviceAddress;
+                byte numDataBytes = (byte)(MSb > 7 ? 2 : 1);
+                IOBuf[3] = numDataBytes;
+                byte numRegBytes = (byte)Math.Ceiling(reg / 255.0);
+                IOBuf[4] = numRegBytes;
+                for (i = 0; i < numRegBytes; i++)                
+                    IOBuf[i + 5] = (byte)((reg>>(8*i)) & 0xFF);                
+                //for (i = 0; i < numDataBytes; i++)
+                //    IOBuf[i + 5 + numRegBytes] = data[i];
+
+                writeHID();
+                mutexGuardIOBuf.ReleaseMutex();    // Release the Mutex.
+
+                if (checkNACK() == I2C_NACK_ERROR && ignoreNACK == false)
+                    throw new Exception("invalid I2C address");
+            }
+            catch (Exception ex)
+            {
+                throw new Exception(ex.Message + Environment.NewLine + new System.Diagnostics.StackFrame().GetMethod().Name);
+            }
+        }*/
+
+        
+        /// <summary>
+        /// <para>Firmware command code 4 OUT = I2C configuration </para>
+        ///  (IO_BUFFER.Ptr[3+gOffset] &amp; 1) ? (SMB0CF |= 0x10) : (SMB0CF &amp;= 0xEF)
+        /// </summary>
+        /// <param name="gI2Cflags">bit0 == 1: repeated start</param>
+        /// <param name="EXTHOLD">set EXTHOLD bit (SMBus setup / hold time extension)</param>
+        /// <param name="ClearSDAbyTogglingSCL">clear SDA by toggling SCL</param>
+       /* public void I2CConfigSet(byte gI2Cflags, byte EXTHOLD, byte ClearSDAbyTogglingSCL)
+        {
+            // verify: https://jira.maxim-ic.com/browse/OS24EVK-24 Refactor: HID report enum and wrappers I2CConfigSet(byte gI2Cflags, byte EXTHOLD, byte ClearSDAbyTogglingSCL)
+            // verify: https://jira.maxim-ic.com/browse/OS24EVK-57 mutex lock HID.IOBuf[] in I2CConfigSet
+            mutexGuardIOBuf.WaitOne();   // Wait until it is safe to enter.
+            FlushQueue();
+            Array.Clear(IOBuf, 0, IOBuf.Length);
+            reportID();
+            IOBuf[1] = 4; // case (4): //I2C configuration -- see usb_app.c int parseHIDReport(uint8_t *data_from_host, unsigned int len) 
+            IOBuf[2] = 0; //    case (0):	// write
+            IOBuf[3] = gI2Cflags;   // gI2Cflags = IO_BUFFER.Ptr[2+gOffset];
+            // // bit0 == 1: repeated start (versus stop/start) after write before read (applies to random read only)
+            // // bit1 == 1: start random read with a write, but end the write right away without sending reg address (emulate Jungo dongle for debug purposes)
+            // // bit2 == 1: repeat transaction if slave NACKs (suggest not to use this)
+            // // all flags are OR'd
+            IOBuf[4] = EXTHOLD;    // (IO_BUFFER.Ptr[3+gOffset] & 1) ? (SMB0CF |= 0x10) : (SMB0CF &= 0xEF);	// set EXTHOLD bit (SMBus setup / hold time extension)
+            IOBuf[5] = ClearSDAbyTogglingSCL;   // if (IO_BUFFER.Ptr[4+gOffset] & 1)	// clear SDA by toggling SCL
+            // {s
+            // 	IO_BUFFER.Ptr[0] = SHORT_REPORT_ID;
+            // 	IO_BUFFER.Ptr[0+gOffset] = 0; 	// transaction error status
+            // 	IO_BUFFER.Ptr[1+gOffset] = clearSDA();	// clearSDA error status
+            // 	SendPacket();			// send status of clearing SDA to host
+            // }
+            writeHID();
+            mutexGuardIOBuf.ReleaseMutex();    // Release the Mutex.
+        }*/
+
+        /// <summary>
+        /// <para>Firmware command code 4 IN = I2C configuration </para>
+        /// (IO_BUFFER.Ptr[3+gOffset] &amp; 1) ? (SMB0CF |= 0x10) : (SMB0CF &amp;= 0xEF)
+        /// </summary>
+        /// <param name="gI2Cflags">bit0 == 1: repeated start</param>
+        /// <param name="EXTHOLD">SMB0CF &amp; 0x10</param>
+       /* public void I2CConfigGet(out byte gI2Cflags, out byte EXTHOLD)
+        {
+            // verify: https://jira.maxim-ic.com/browse/OS24EVK-24 Refactor: HID report enum and wrappers I2CConfigGet(out byte gI2Cflags, out byte EXTHOLD)
+            // verify: https://jira.maxim-ic.com/browse/OS24EVK-57 mutex lock HID.IOBuf[] in I2CConfigGet
+            mutexGuardIOBuf.WaitOne();   // Wait until it is safe to enter.
+            FlushQueue();
+            Array.Clear(IOBuf, 0, IOBuf.Length);
+            reportID();
+            IOBuf[1] = 4; // case (4): //I2C configuration -- see usb_app.c int parseHIDReport(uint8_t *data_from_host, unsigned int len) 
+            IOBuf[2] = 1; //    case (1):	// read
+            writeReadHID();
+            // IO_BUFFER.Ptr[0] = SHORT_REPORT_ID;
+            // IO_BUFFER.Ptr[0+gOffset] = 0; // error status					
+            // IO_BUFFER.Ptr[1+gOffset] = gI2Cflags;
+            // IO_BUFFER.Ptr[2+gOffset] = (SMB0CF & 0x10) >> 4; // EXTHOLD
+            gI2Cflags = IOBuf[2];
+            EXTHOLD = IOBuf[3];
+            mutexGuardIOBuf.ReleaseMutex();    // Release the Mutex.
+        }*/
+
+        /// <summary>
+        /// <para>Firmware command code 5 OUT = I2C clock rate (number of counts to overflow) </para>
+        /// <para>SCL_kHz = TimerClockMHz * 1000 / ReloadTH1</para>
+        /// </summary>
+        /// <param name="ReloadTH1">SMBus timer's count value: ReloadTH1 = (byte)(0.5 + (TimerClockMHz * 1000 / SCL_kHz))</param>
+       /* public void I2CClockSet(byte ReloadTH1)
+        {
+            // verify: https://jira.maxim-ic.com/browse/OS24EVK-24 Refactor: HID report enum and wrappers I2CClockSet(byte ReloadTH1)
+            // verify: https://jira.maxim-ic.com/browse/OS24EVK-57 mutex lock HID.IOBuf[] in I2CClockSet
+            mutexGuardIOBuf.WaitOne();   // Wait until it is safe to enter.
+            FlushQueue();
+            Array.Clear(IOBuf, 0, IOBuf.Length);
+            reportID();
+            IOBuf[1] = 5; // case (5): //I2C clock rate (number of counts to overflow) -- see usb_app.c int parseHIDReport(uint8_t *data_from_host, unsigned int len) 
+            IOBuf[2] = 0; //    case (0):	// write
+            IOBuf[3] = ReloadTH1;
+            // gSMBusClkFreq = gTimer1ClkFreq / 3.0 / IO_BUFFER.Ptr[2+gOffset];	//GUI sends the number of counts to overflow; HID must calculate the desired SMBus clock frequency
+            // TR1 = 0;
+            // Timer1_Init();
+            writeHID();
+            mutexGuardIOBuf.ReleaseMutex();    // Release the Mutex.
+        }*/
+
+        /// <summary>
+        /// <para>Firmware command code 5 IN = I2C clock rate (number of counts to overflow) </para>
+        /// <para>SCL_kHz = TimerClockMHz * 1000 / ReloadTH1</para>
+        /// </summary>
+        /// <param name="TimerClockMHz">SMBus timer's clock frequency (in MHz); expect constant 8</param>
+        /// <param name="ReloadTH1">SMBus timer's count value: SCL_kHz = TimerClockMHz * 1000 / ReloadTH1</param>
+        /*public void I2CClockGet(out byte TimerClockMHz, out byte ReloadTH1)
+        {
+            // verify: https://jira.maxim-ic.com/browse/OS24EVK-24 Refactor: HID report enum and wrappers I2CClockGet(out byte TimerClockMHz, out byte ReloadTH1)
+            // verify: https://jira.maxim-ic.com/browse/OS24EVK-57 mutex lock HID.IOBuf[] in I2CClockGet
+            mutexGuardIOBuf.WaitOne();   // Wait until it is safe to enter.
+            FlushQueue();
+            Array.Clear(IOBuf, 0, IOBuf.Length);
+            reportID();
+            IOBuf[1] = 5; // case (5): //I2C clock rate (number of counts to overflow) -- see usb_app.c int parseHIDReport(uint8_t *data_from_host, unsigned int len) 
+            IOBuf[2] = 1; //    case (1):	// read
+            writeReadHID();
+            // case (1): 	// read -- myHID.I2CClockGet(out TimerClockMHz, out ReloadTH1)
+            // IO_BUFFER.Ptr[0] = SHORT_REPORT_ID;
+            // IO_BUFFER.Ptr[0+gOffset] = 0; // error status
+            // IO_BUFFER.Ptr[1+gOffset] = gTimer1ClkFreq / 1000000 / 3;	//return the SMBus timer's clock frequency (in MHz)
+            // IO_BUFFER.Ptr[2+gOffset] = 256-TH1;						//and return the SMBus timer's count value in order to calculate the SMBus clock frequency; TH1 is the reload value that gets loaded into TL0 upon overflow; the reload value is 256-TH1 since (0)-TH1 gives the proper number of counts to overflow
+            // SendPacket(); // no need to check for internal call since only the GUI will request a read through this function
+            // break;
+            TimerClockMHz = IOBuf[2];
+            ReloadTH1 = IOBuf[3];
+            // todo: OS24EVK-24 how determine SCL from TimerClockMHZ? Observed I2CClockGet() TimerClockMHz = 8 when SCL = 400kHz.
+            mutexGuardIOBuf.ReleaseMutex();    // Release the Mutex.
+        }*/
+
+        /// <summary>
+        /// <para>Firmware command code 6 OUT = I2C transaction </para>
+        /// 
+        /// </summary>
+        /// <param name="deviceAddress">I2C device address, 8-bit left-justified (LSB=R/w bit)</param>
+        /// <param name="numDataBytes">I2C burst write register data count, in bytes</param>
+        /// <param name="numRegBytes">I2C device register address length, normally 1 byte. Can be 0 for SMBusQuick protocol.</param>
+        /// <param name="data">byte array containing the register data to transmit</param>
+        /// <param name="reg">byte array containing the device register address</param>
+        /// <param name="ignoreNACK"></param>
+        /*public void I2CWrite(byte deviceAddress, byte numDataBytes, byte numRegBytes, byte[] data, byte[] reg, bool ignoreNACK = false)
+        {
+            // https://jira.maxim-ic.com/browse/OS24EVK-24 Refactor: HID report enum and wrappers
+            // alias of existing function
+            // IOBuf[1] = 6; // case (6):	// I2C transaction -- HID.cs void writeI2C() readI2C() -- see usb_app.c int parseHIDReport(uint8_t *data_from_host, unsigned int len) 
+            writeI2C(deviceAddress, numDataBytes, numRegBytes, data, reg, ignoreNACK);
+        }*/
+
+        /// <summary>
+        /// <para>Firmware command code 6 IN = I2C transaction </para>
+        /// 
+        /// </summary>
+        /// <param name="deviceAddress">I2C device address, 8-bit left-justified (LSB=R/w bit)</param>
+        /// <param name="numDataBytes">I2C burst read register data count, in bytes</param>
+        /// <param name="numRegBytes">I2C device register address length, normally 1 byte. Can be 0 for SMBusQuick protocol.</param>
+        /// <param name="readData">byte array which receives the register data</param>
+        /// <param name="reg">byte array containing the device register address</param>
+        /// <param name="ignoreNACK"></param>
+        /// <returns>status value; may be HID.I2C_NACK_ERROR if ignoreNACK parameter is true</returns>
+       /* public int I2CRead(byte deviceAddress, byte numDataBytes, byte numRegBytes, byte[] readData, byte[] reg, bool ignoreNACK = false)
+        {
+            // https://jira.maxim-ic.com/browse/OS24EVK-24 Refactor: HID report enum and wrappers
+            // alias of existing function
+            // IOBuf[1] = 6; // case (6):	// I2C transaction -- HID.cs void writeI2C() readI2C() -- see usb_app.c int parseHIDReport(uint8_t *data_from_host, unsigned int len) 
+            return readI2C(deviceAddress, numDataBytes, numRegBytes, readData, reg, ignoreNACK);
+        }*/
+
+        /*/// <summary>
+        /// Search for a device attached to I2C bus, 
+        /// given a list of poossible device addresses, 
+        /// and a constant device ID register to test.
+        /// </summary>
+        /// <param name="I2C_DeviceAddressList_8bitLeftJustified">List of possible I2C device addresses to test. I2C device addresses are 8-bit left-justified (LSB=R/w bit)</param>
+        /// <param name="DeviceId_RegAddress">device register address of a constant "Device ID" register</param>
+        /// <param name="DeviceId_RegValue_Expect">register value of the constant "Device ID" register</param>
+        /// <returns>I2C device addresses, or 0 if not found</returns>
+        public byte SearchI2CdeviceAddressList(byte[] I2C_DeviceAddressList_8bitLeftJustified, byte DeviceId_RegAddress, byte DeviceId_RegValue_Expect)
+        {
+            // https://jira.maxim-ic.com/browse/OS24EVK-57 accelerometer support: SearchI2CdeviceAddressList optional I2C device
+            foreach (byte test_I2C_Address in I2C_DeviceAddressList_8bitLeftJustified)
+            {
+                //try
+                //{
+                byte[] data = new byte[2];
+                byte[] reg = new byte[1];
+                reg[0] = (byte)DeviceId_RegAddress;
+                // readI2C should already take care of mutex lock / unlock
+                // https://jira.maxim-ic.com/browse/OS24EVK-59 avoid NACK exception in SearchI2CdeviceAddressList
+                bool ignoreNACK = true;
+                int status = readI2C(test_I2C_Address, 2, 1, data, reg, ignoreNACK);
+                if (status == HID.I2C_NACK_ERROR)
+                {
+                    continue;
+                }
+                else
+                {
+                    byte DeviceId_RegValue_Actual = data[0];
+                    if (DeviceId_RegValue_Actual == DeviceId_RegValue_Expect)
+                    {
+                        return test_I2C_Address;
+                    }
+                }
+                //}
+                //catch (Exception)
+                //{
+                //    // myHID.readI2C can throw Exception("invalid I2C address");
+                //}
+            }
+            return 0;
+        }*/
+        #endregion
+
+        public bool I2C_Initialize(byte index, byte clockSpeed)
+        {
+            bool success = false;
+
+            mutexGuardIOBuf.WaitOne();   // Wait until it is safe to enter.
+            FlushQueue();
+            Array.Clear(IOBuf, 0, IOBuf.Length);
+
+            reportID();
+            IOBuf[1] = I2C_INIT; // command code -- see usb_app int parseHIDReport(uint8_t *data_from_host, unsigned int len) 
+            IOBuf[2] = index;
+            IOBuf[3] = clockSpeed; // 0 = 100KHz, 1 = 400KHz, 2 = 1MHz
+
+            writeReadHID();
+
+            if (IOBuf[1] == COMMAND_SUCCESS)
+                success = true;
+
+            mutexGuardIOBuf.ReleaseMutex();    // Release the Mutex.
+
+            return success;
+        }
+
+        public byte SearchI2CdeviceAddressList(byte index, byte[] I2C_DeviceAddressList_8bitLeftJustified, byte DeviceId_RegAddress, byte DeviceId_RegValue_Expect)
+        {
+            foreach (byte test_I2C_Address in I2C_DeviceAddressList_8bitLeftJustified)
+            {
+                byte[] data = new byte[2];
+                byte[] reg = new byte[1];
+                reg[0] = (byte)DeviceId_RegAddress;
+
+                bool success = I2C_Read(index, test_I2C_Address, 1, reg, 2, ref data);
+
+                if (success)
+                {
+                    byte DeviceId_RegValue_Actual = data[0];
+                    if (DeviceId_RegValue_Actual == DeviceId_RegValue_Expect)
+                    {
+                        return test_I2C_Address;
+                    }
+                }
+            }
+            return 0;
+        }
+
+        public bool I2C_Read(byte index, byte slaveAddress, byte num_cmd_bytes, byte[] cmd_data, byte num_data_bytes, ref byte[] data)
+        {
+            bool success = false;
+
+            if ((5 + num_cmd_bytes) > 63)
+                return false;
+            if ((1 + num_data_bytes) > 63)
+                return false;
+
+            mutexGuardIOBuf.WaitOne();   // Wait until it is safe to enter.
+            FlushQueue();
+            Array.Clear(IOBuf, 0, IOBuf.Length);
+
+            reportID();
+            IOBuf[1] = I2C_TRANSACTION; // command code -- see usb_app int parseHIDReport(uint8_t *data_from_host, unsigned int len) 
+            IOBuf[2] = index;
+            IOBuf[3] = (byte)(slaveAddress | 0x01); //LSB = 1 for read
+            IOBuf[4] = num_cmd_bytes;
+
+            for (int i = 0; i < num_cmd_bytes; i++)
+                IOBuf[5 + i] = cmd_data[i];
+
+            IOBuf[5 + num_cmd_bytes] = num_data_bytes;
+
+            writeReadHID();
+
+            if (IOBuf[1] == COMMAND_SUCCESS)
+                success = true;
+
+            for (int i = 0; i < num_data_bytes; i++)
+                data[i] = IOBuf[2 + i];
+
+            mutexGuardIOBuf.ReleaseMutex();    // Release the Mutex.
+
+            return success;
+        }
+        public bool I2C_Write(byte index, byte slaveAddress, byte num_cmd_bytes, byte[] cmd_data, byte num_data_bytes, byte[] data)
+        {
+            bool success = false;
+
+            if ((5 + num_cmd_bytes) > 63)
+                return false;
+            if ((1 + num_data_bytes) > 63)
+                return false;
+
+            mutexGuardIOBuf.WaitOne();   // Wait until it is safe to enter.
+            FlushQueue();
+            Array.Clear(IOBuf, 0, IOBuf.Length);
+
+            reportID();
+            IOBuf[1] = I2C_TRANSACTION; // command code -- see usb_app int parseHIDReport(uint8_t *data_from_host, unsigned int len) 
+            IOBuf[2] = index;
+            IOBuf[3] = (byte)(slaveAddress | 0x01); //LSB = 1 for read
+            IOBuf[4] = num_cmd_bytes;
+
+            for (int i = 0; i < num_cmd_bytes; i++)
+                IOBuf[5 + i] = cmd_data[i];
+
+            IOBuf[5 + num_cmd_bytes] = num_data_bytes;
+
+            for (int i = 0; i < num_data_bytes; i++)
+                IOBuf[6 + num_cmd_bytes + i] = data[i];
+
+            writeReadHID();
+
+            if (IOBuf[1] == COMMAND_SUCCESS)
+                success = true;
+
+            mutexGuardIOBuf.ReleaseMutex();    // Release the Mutex.
+
+            return success;
+        }
+
+        public String RPC_Call(String str) {
+
+            mutexGuardIOBuf.WaitOne();   // Wait until it is safe to enter.
+            FlushQueue();
+            Array.Clear(IOBuf, 0, IOBuf.Length);
+
+            reportID();
+            int i = 1;
+            foreach (char ch in str)
+            {
+                IOBuf[i] = (byte)ch;
+                i++;
+            }
+
+            writeReadHID();
+
+            StringBuilder sb = new StringBuilder();
+            for (i = 1; i < 64; i++)
+            {
+                if (IOBuf[i] == 13) break;
+                sb.Append((char)IOBuf[i]);             
+            }
+
+            mutexGuardIOBuf.ReleaseMutex();    // Release the Mutex.
+            return sb.ToString();
+        }
+
+        #endregion
+
+        #region General Commmands
+        /// <summary>
+        /// <para>Firmware command code 0 IN = Firmware version</para>
+        /// 
+        /// </summary>
+        /// <param name="VerMajor"></param>
+        /// <param name="VerMinor"></param>
+        /// <param name="verYearHundreds"></param>
+        /// <param name="verYear"></param>
+        /// <param name="verMonth"></param>
+        /// <param name="verDay"></param>
+        public bool FirmwareVersion(out byte VerMajor, out byte VerMinor, out byte verYearHundreds, out byte verYear, out byte verMonth, out byte verDay)
+        {
+            bool success = false;
+
+            if (FirmwareINT0Enabled != 0)
+            {
+                // firmware is busy streaming out HID reports,
+                // so return a previously retrieved firmware version.
+                VerMajor = _VerMajor;
+                VerMinor = _VerMinor;
+                verYearHundreds = _verYearHundreds;
+                verYear = _verYear;
+                verMonth = _verMonth;
+                verDay = _verDay;
+                return true;
+            }
+            // https://jira.maxim-ic.com/browse/OS24EVK-24 Refactor: HID report enum and wrappers
+            // verify: https://jira.maxim-ic.com/browse/OS24EVK-57 mutex lock HID.IOBuf[] in FirmwareVersion
+            mutexGuardIOBuf.WaitOne();   // Wait until it is safe to enter.
+            FlushQueue();
+            Array.Clear(IOBuf, 0, IOBuf.Length);
+            reportID();
+            IOBuf[1] = 0; // Firmware version -- see usb_app.c int parseHIDReport(uint8_t *data_from_host, unsigned int len) 
+            writeReadHID();
+            VerMajor = IOBuf[2];
+            VerMinor = IOBuf[3];
+            verYearHundreds = IOBuf[4];
+            verYear = IOBuf[5];
+            verMonth = IOBuf[6];
+            verDay = IOBuf[7];
+
+            if (IOBuf[1] == COMMAND_SUCCESS)
+            {
+                success = true;
+                
+                // save the recently read values
+                _VerMajor = VerMajor;
+                _VerMinor = VerMinor;
+                _verYearHundreds = verYearHundreds;
+                _verYear = verYear;
+                _verMonth = verMonth;
+                _verDay = verDay;
+            }
+           
+            mutexGuardIOBuf.ReleaseMutex();    // Release the Mutex.
+
+            return success;
+        }
+        private byte _VerMajor = 0;
+        private byte _VerMinor = 0;
+        private byte _verYearHundreds = 0;
+        private byte _verYear = 0;
+        private byte _verMonth = 0;
+        private byte _verDay = 0;
+        /// <summary>
+        /// <para>Firmware command code 1 </para>
+        /// 
+        /// </summary>
+        /// <param name="ON">ON = true: LED turns on</param>
+        public bool LEDSet(bool ON)
+        {
+            bool success = false;
+
+            mutexGuardIOBuf.WaitOne();   // Wait until it is safe to enter.
+            FlushQueue();
+            Array.Clear(IOBuf, 0, IOBuf.Length);
+            reportID();
+            IOBuf[1] = 1; // command code -- see usb_app int parseHIDReport(uint8_t *data_from_host, unsigned int len) 
+
+            if(ON)
+                IOBuf[2] = 1;
+            else
+                IOBuf[2] = 0;
+
+            writeReadHID();
+
+            if (IOBuf[1] == COMMAND_SUCCESS)
+                success = true;
+
+            mutexGuardIOBuf.ReleaseMutex();    // Release the Mutex.
+
+            return success;
+        }
+        #endregion
+
+        #region GPIO commands
+        /// <summary>
+        /// <para>Firmware command code 1 IN = GPIOP0Get read I/O pins P0.6, P0.7</para>
+        /// 
+        /// </summary>
+        /// <param name="xxxxxxP06P07"></param>
+        public void GPIOP0Get(out byte xxxxxxP06P07)
+        {
+            // todo: verify: https://jira.maxim-ic.com/browse/OS24EVK-24 Refactor: HID report enum and wrappers GPIOP0Get(out byte xxxxxxP06P07)
+            // https://jira.maxim-ic.com/browse/OS24EVK-24 Refactor: Rename LEDGet(out byte xxxxxxP06P07) to GPIOP0Get(out byte xxxxxxP06P07)
+            // verify: https://jira.maxim-ic.com/browse/OS24EVK-57 mutex lock HID.IOBuf[] in GPIOP0Get
+            mutexGuardIOBuf.WaitOne();   // Wait until it is safe to enter.
+            FlushQueue();
+            Array.Clear(IOBuf, 0, IOBuf.Length);
+            reportID();
+            IOBuf[1] = 1; // case (1): //LED (C51F321 P2.2=red, P2.1=green) -- see usb_app.c int parseHIDReport(uint8_t *data_from_host, unsigned int len) 
+            IOBuf[2] = 1; //    case (1):	// read
+            writeReadHID();
+            // IO_BUFFER.Ptr[0] = SHORT_REPORT_ID;
+            // IO_BUFFER.Ptr[0 + gOffset] = 0; // error status
+            // IO_BUFFER.Ptr[1 + gOffset] = ((P0 & 0x80) >> 7) + ((P0 & 0x40) >> 5);
+            xxxxxxP06P07 = IOBuf[2];
+            mutexGuardIOBuf.ReleaseMutex();    // Release the Mutex.
+        }
+
+        /// <summary>
+        /// <para>Firmware command code 2 OUT = GPIO configuration (C51F321 P1 and P2) </para>
+        /// 
+        /// </summary>
+        /// <param name="P1MDOUT"></param>
+        /// <param name="P2MDOUT"></param>
+        /// <param name="weakPullupDisable"></param>
+        public void GPIOP1P2ConfigSet(byte P1MDOUT, byte P2MDOUT, byte weakPullupDisable)
+        {
+            // verify: https://jira.maxim-ic.com/browse/OS24EVK-24 Refactor: HID report enum and wrappers GPIOP1P2ConfigSet(byte P1MDOUT, byte P2MDOUT, byte weakPullupDisable)
+            // verify: https://jira.maxim-ic.com/browse/OS24EVK-57 mutex lock HID.IOBuf[] in GPIOP1P2ConfigSet
+            mutexGuardIOBuf.WaitOne();   // Wait until it is safe to enter.
+            FlushQueue();
+            Array.Clear(IOBuf, 0, IOBuf.Length);
+            reportID();
+            IOBuf[1] = 2; // case (2): //GPIO configuration (C51F321 P1 and P2) -- see usb_app.c int parseHIDReport(uint8_t *data_from_host, unsigned int len) 
+            IOBuf[2] = 0; //    case (0):	// write
+            IOBuf[3] = P1MDOUT; // P1MDOUT = IO_BUFFER.Ptr[2+gOffset];	// P1 push-pull (1) or open-collector (0)
+            IOBuf[4] = P2MDOUT; // P2MDOUT = IO_BUFFER.Ptr[3 + gOffset];	// P2 push-pull (1) or open-collector (0)
+            IOBuf[5] = weakPullupDisable; // (IO_BUFFER.Ptr[4 + gOffset] & 1) ? (XBR1 |= 0x80) : (XBR1 &= 0x7F);	// weak pull up disable (open collector only); 1 disabled, 0 enabled
+            writeHID();
+            mutexGuardIOBuf.ReleaseMutex();    // Release the Mutex.
+        }
+
+        /// <summary>
+        /// <para>Firmware command code 2 IN = GPIO configuration (C51F321 P1 and P2) </para>
+        /// 
+        /// </summary>
+        /// <param name="P1MDOUT"></param>
+        /// <param name="P2MDOUT"></param>
+        /// <param name="weakPullupDisable"></param>
+        public void GPIOP1P2ConfigGet(out byte P1MDOUT, out byte P2MDOUT, out byte weakPullupDisable)
+        {
+            // verify: https://jira.maxim-ic.com/browse/OS24EVK-24 Refactor: HID report enum and wrappers GPIOP1P2ConfigGet(out byte P1MDOUT, out byte P2MDOUT, out byte weakPullupDisable)
+            // verify: https://jira.maxim-ic.com/browse/OS24EVK-57 mutex lock HID.IOBuf[] in GPIOP1P2ConfigGet
+            mutexGuardIOBuf.WaitOne();   // Wait until it is safe to enter.
+            FlushQueue();
+            Array.Clear(IOBuf, 0, IOBuf.Length);
+            reportID();
+            IOBuf[1] = 2; // case (2): //GPIO configuration (C51F321 P1 and P2) -- see usb_app.c int parseHIDReport(uint8_t *data_from_host, unsigned int len) 
+            IOBuf[2] = 1; //    case (1):	// read
+            writeReadHID();
+            // IO_BUFFER.Ptr[0] = SHORT_REPORT_ID;
+            // IO_BUFFER.Ptr[0 + gOffset] = 0; // error status					
+            // IO_BUFFER.Ptr[1 + gOffset] = P1MDOUT;	// P1 push-pull (1) or open-collector (0)
+            // IO_BUFFER.Ptr[2 + gOffset] = P2MDOUT;	// P2 push-pull (1) or open-collector (0)
+            // IO_BUFFER.Ptr[3 + gOffset] = (XBR1 & 0x80) >> 7; // weakPullupDisable
+            P1MDOUT = IOBuf[2];
+            P2MDOUT = IOBuf[3];
+            weakPullupDisable = IOBuf[4];
+            mutexGuardIOBuf.ReleaseMutex();    // Release the Mutex.
+        }
+
+        /// <summary>
+        /// <para>Firmware command code 3 OUT = GPIO value (C51F321 P1 and P2) </para>
+        /// 
+        /// </summary>
+        /// <param name="P1"></param>
+        /// <param name="P2"></param>
+        public void GPIOP1P2Out(byte P1, byte P2)
+        {
+            // verify: https://jira.maxim-ic.com/browse/OS24EVK-24 Refactor: HID report enum and wrappers GPIOP1P2Out(byte P1, byte P2)
+            // verify: https://jira.maxim-ic.com/browse/OS24EVK-57 mutex lock HID.IOBuf[] in GPIOP1P2Out
+            mutexGuardIOBuf.WaitOne();   // Wait until it is safe to enter.
+            FlushQueue();
+            Array.Clear(IOBuf, 0, IOBuf.Length);
+            reportID();
+            IOBuf[1] = 3; // case (3): //GPIO value (C51F321 P1 and P2) -- see usb_app.c int parseHIDReport(uint8_t *data_from_host, unsigned int len) 
+            IOBuf[2] = 0; //    case (0):	// write
+            IOBuf[3] = P1; // P1 = IO_BUFFER.Ptr[2 + gOffset];		// P1 HI (1) or LO (0); set P1==1 and P1MDOUT==1 for HI-Z
+            IOBuf[4] = P2; // P2 = IO_BUFFER.Ptr[3 + gOffset];		// P2 HI (1) or LO (0); set P2==1 and P1MDOUT==2 for HI-Z
+            writeHID();
+            mutexGuardIOBuf.ReleaseMutex();    // Release the Mutex.
+        }
+
+        /// <summary>
+        /// <para>Firmware command code 3 IN = GPIO value (C51F321 P1 and P2) </para>
+        /// 
+        /// </summary>
+        /// <param name="P1"></param>
+        /// <param name="P2"></param>
+        public void GPIOP1P2In(out byte P1, out byte P2)
+        {
+            // verify: https://jira.maxim-ic.com/browse/OS24EVK-24 Refactor: HID report enum and wrappers GPIOP1P2In(out byte P1, out byte P2)
+            // verify: https://jira.maxim-ic.com/browse/OS24EVK-57 mutex lock HID.IOBuf[] in GPIOP1P2In
+            mutexGuardIOBuf.WaitOne();   // Wait until it is safe to enter.
+            FlushQueue();
+            Array.Clear(IOBuf, 0, IOBuf.Length);
+            reportID();
+            IOBuf[1] = 3; // case (3): //GPIO value (C51F321 P1 and P2) -- see usb_app.c int parseHIDReport(uint8_t *data_from_host, unsigned int len) 
+            IOBuf[2] = 1; //    case (1):	// read
+            writeReadHID();
+            // temp = XBR1;
+            // if (IO_BUFFER.Ptr[2+gOffset] & 1)	// enable weak pullups in case GP pins are open-collector and not connected to anything (which would falsely give '0')
+            // {
+            // 	XBR1 &= 0x7F;
+            // 	Timer0_Init(HALFMS);
+            // 	T0_Wait(2);
+            // }
+            // IO_BUFFER.Ptr[0] = SHORT_REPORT_ID;
+            // IO_BUFFER.Ptr[0+gOffset] = 0; 		// error status
+            // IO_BUFFER.Ptr[1+gOffset] = P1;		// P1 HI (1) or LO (0)
+            // IO_BUFFER.Ptr[2+gOffset] = P2;		// P2 HI (1) or LO (0)
+            // XBR1 = temp;
+            // SendPacket(); // no need to check for internal call since only the GUI will request a read through this function
+            P1 = IOBuf[2];
+            P2 = IOBuf[3];
+            mutexGuardIOBuf.ReleaseMutex();    // Release the Mutex.
+        }
+        #endregion
+
+        #region SPI Commands
+        /*
+
+        /// <summary>
+        /// <para>Firmware command code 5 OUT = I2C clock rate (number of counts to overflow) </para>
+        /// <para>SCL_kHz = TimerClockMHz * 1000 / ReloadTH1</para>
+        /// </summary>
+        /// <param name="ReloadTH1">SMBus timer's count value: ReloadTH1 = (byte)(0.5 + (TimerClockMHz * 1000 / SCL_kHz))</param>
+        public void I2CClockSet(byte ReloadTH1)
+        {
+            // verify: https://jira.maxim-ic.com/browse/OS24EVK-24 Refactor: HID report enum and wrappers I2CClockSet(byte ReloadTH1)
+            // verify: https://jira.maxim-ic.com/browse/OS24EVK-57 mutex lock HID.IOBuf[] in I2CClockSet
+            mutexGuardIOBuf.WaitOne();   // Wait until it is safe to enter.
+            FlushQueue();
+            Array.Clear(IOBuf, 0, IOBuf.Length);
+            reportID();
+            IOBuf[1] = 5; // case (5): //I2C clock rate (number of counts to overflow) -- see F3xx_USB0_ReportHandler.c void OUT_REPORT_HANDLER(int internalCall) 
+            IOBuf[2] = 0; //    case (0):	// write
+            IOBuf[3] = ReloadTH1;
+            // gSMBusClkFreq = gTimer1ClkFreq / 3.0 / IO_BUFFER.Ptr[2+gOffset];	//GUI sends the number of counts to overflow; HID must calculate the desired SMBus clock frequency
+            // TR1 = 0;
+            // Timer1_Init();
+            writeHID();
+            mutexGuardIOBuf.ReleaseMutex();    // Release the Mutex.
+        }
+
+        /// <summary>
+        /// <para>Firmware command code 5 IN = I2C clock rate (number of counts to overflow) </para>
+        /// <para>SCL_kHz = TimerClockMHz * 1000 / ReloadTH1</para>
+        /// </summary>
+        /// <param name="TimerClockMHz">SMBus timer's clock frequency (in MHz); expect constant 8</param>
+        /// <param name="ReloadTH1">SMBus timer's count value: SCL_kHz = TimerClockMHz * 1000 / ReloadTH1</param>
+        public void I2CClockGet(out byte TimerClockMHz, out byte ReloadTH1)
+        {
+            // verify: https://jira.maxim-ic.com/browse/OS24EVK-24 Refactor: HID report enum and wrappers I2CClockGet(out byte TimerClockMHz, out byte ReloadTH1)
+            // verify: https://jira.maxim-ic.com/browse/OS24EVK-57 mutex lock HID.IOBuf[] in I2CClockGet
+            mutexGuardIOBuf.WaitOne();   // Wait until it is safe to enter.
+            FlushQueue();
+            Array.Clear(IOBuf, 0, IOBuf.Length);
+            reportID();
+            IOBuf[1] = 5; // case (5): //I2C clock rate (number of counts to overflow) -- see F3xx_USB0_ReportHandler.c void OUT_REPORT_HANDLER(int internalCall) 
+            IOBuf[2] = 1; //    case (1):	// read
+            writeReadHID();
+            // case (1): 	// read -- myHID.I2CClockGet(out TimerClockMHz, out ReloadTH1)
+            // IO_BUFFER.Ptr[0] = SHORT_REPORT_ID;
+            // IO_BUFFER.Ptr[0+gOffset] = 0; // error status
+            // IO_BUFFER.Ptr[1+gOffset] = gTimer1ClkFreq / 1000000 / 3;	//return the SMBus timer's clock frequency (in MHz)
+            // IO_BUFFER.Ptr[2+gOffset] = 256-TH1;						//and return the SMBus timer's count value in order to calculate the SMBus clock frequency; TH1 is the reload value that gets loaded into TL0 upon overflow; the reload value is 256-TH1 since (0)-TH1 gives the proper number of counts to overflow
+            // SendPacket(); // no need to check for internal call since only the GUI will request a read through this function
+            // break;
+            TimerClockMHz = IOBuf[2];
+            ReloadTH1 = IOBuf[3];
+            // todo: OS24EVK-24 how determine SCL from TimerClockMHZ? Observed I2CClockGet() TimerClockMHz = 8 when SCL = 400kHz.
+            mutexGuardIOBuf.ReleaseMutex();    // Release the Mutex.
+        }
+
+        /// <summary>
+        /// <para>Firmware command code 6 OUT = I2C transaction </para>
+        /// 
+        /// </summary>
+        /// <param name="deviceAddress">I2C device address, 8-bit left-justified (LSB=R/w bit)</param>
+        /// <param name="numDataBytes">I2C burst write register data count, in bytes</param>
+        /// <param name="numRegBytes">I2C device register address length, normally 1 byte. Can be 0 for SMBusQuick protocol.</param>
+        /// <param name="data">byte array containing the register data to transmit</param>
+        /// <param name="reg">byte array containing the device register address</param>
+        /// <param name="ignoreNACK"></param>
+        public void I2CWrite(byte deviceAddress, byte numDataBytes, byte numRegBytes, byte[] data, byte[] reg, bool ignoreNACK = false)
+        {
+            // https://jira.maxim-ic.com/browse/OS24EVK-24 Refactor: HID report enum and wrappers
+            // alias of existing function
+            // IOBuf[1] = 6; // case (6):	// I2C transaction -- HID.cs void writeI2C() readI2C() -- see F3xx_USB0_ReportHandler.c void OUT_REPORT_HANDLER(int internalCall) 
+            writeI2C(deviceAddress, numDataBytes, numRegBytes, data, reg, ignoreNACK);
+        }
+
+        /// <summary>
+        /// <para>Firmware command code 6 IN = I2C transaction </para>
+        /// 
+        /// </summary>
+        /// <param name="deviceAddress">I2C device address, 8-bit left-justified (LSB=R/w bit)</param>
+        /// <param name="numDataBytes">I2C burst read register data count, in bytes</param>
+        /// <param name="numRegBytes">I2C device register address length, normally 1 byte. Can be 0 for SMBusQuick protocol.</param>
+        /// <param name="readData">byte array which receives the register data</param>
+        /// <param name="reg">byte array containing the device register address</param>
+        /// <param name="ignoreNACK"></param>
+        /// <returns>status value; may be HID.I2C_NACK_ERROR if ignoreNACK parameter is true</returns>
+        public int I2CRead(byte deviceAddress, byte numDataBytes, byte numRegBytes, byte[] readData, byte[] reg, bool ignoreNACK = false)
+        {
+            // https://jira.maxim-ic.com/browse/OS24EVK-24 Refactor: HID report enum and wrappers
+            // alias of existing function
+            // IOBuf[1] = 6; // case (6):	// I2C transaction -- HID.cs void writeI2C() readI2C() -- see F3xx_USB0_ReportHandler.c void OUT_REPORT_HANDLER(int internalCall) 
+            return readI2C(deviceAddress, numDataBytes, numRegBytes, readData, reg, ignoreNACK);
+        }
+        */
+        /// <summary>
+        /// <para>Firmware command code 7 OUT = SPI config </para>
+        /// ((SPI0CFG &amp; 0x30) &gt;&gt; 4) + (SPI0CN &amp; 4)
+        /// </summary>
+        /// <param name="config"></param>
+        public void SPIConfigSet(byte config)
+        {
+            // todo: https://jira.maxim-ic.com/browse/OS24EVK-24 Refactor: HID report enum and wrappers SPIConfigSet(byte config)
+            // Although the MAX30101EVKIT firmware will accept HID SPI commands, this firmware doesn't support SPI interface.
+            // IOBuf[1] = 7; // case (7):	// SPI config -- HID.cs void writeI2C() readI2C() -- see usb_app.c int parseHIDReport(uint8_t *data_from_host, unsigned int len) 
+        }
+
+        /// <summary>
+        /// <para>Firmware command code 7 IN = SPI config </para>
+        /// ((SPI0CFG &amp; 0x30) &gt;&gt; 4) + (SPI0CN &amp; 4)
+        /// </summary>
+        /// <param name="config"></param>
+        public void SPIConfigGet(out byte config)
+        {
+            // todo: https://jira.maxim-ic.com/browse/OS24EVK-24 Refactor: HID report enum and wrappers SPIConfigGet(out byte config)
+            // Although the MAX30101EVKIT firmware will accept HID SPI commands, this firmware doesn't support SPI interface.
+            // IOBuf[1] = 7; // case (7):	// SPI config -- HID.cs void writeI2C() readI2C() -- see usb_app.c int parseHIDReport(uint8_t *data_from_host, unsigned int len) 
+            config = 0;
+        }
+
+        /// <summary>
+        /// <para>Firmware command code 8 OUT = SPI clock rate </para>
+        /// </summary>
+        /// <param name="SPI0CKR"></param>
+        public void SPIClockSet(byte SPI0CKR)
+        {
+            // todo: https://jira.maxim-ic.com/browse/OS24EVK-24 Refactor: HID report enum and wrappers SPIClockSet(byte SPI0CKR)
+            // Although the MAX30101EVKIT firmware will accept HID SPI commands, this firmware doesn't support SPI interface.
+            // IOBuf[1] = 8; // case (8): 	// SPI clock rate -- see usb_app.c int parseHIDReport(uint8_t *data_from_host, unsigned int len) 
+        }
+
+        /// <summary>
+        /// <para>Firmware command code 8 IN = SPI clock rate </para>
+        /// </summary>
+        /// <param name="SPI0CKR"></param>
+        public void SPIClockGet(out byte SPI0CKR)
+        {
+            // todo: https://jira.maxim-ic.com/browse/OS24EVK-24 Refactor: HID report enum and wrappers SPIClockGet(out byte SPI0CKR)
+            // Although the MAX30101EVKIT firmware will accept HID SPI commands, this firmware doesn't support SPI interface.
+            // IOBuf[1] = 8; // case (8): 	// SPI clock rate -- see usb_app.c int parseHIDReport(uint8_t *data_from_host, unsigned int len) 
+            SPI0CKR = 0;
+        }
+
+        /// <summary>
+        /// <para>Firmware command code 9 = SPI transaction </para>
+        /// </summary>
+        /// <param name="mosiData">SPI MOSI (Master-Out, Slave-In) data to write into slave device</param>
+        /// <param name="misoBuffer">SPI MISO (Master-In, Slave-Out) data buffer containing data bytes received from slave device
+        /// (size will be allocated same size as mosiData)</param>
+        public void SPITransfer(byte[] mosiData, out byte[] misoBuffer)
+        {
+            // verify: https://jira.maxim-ic.com/browse/OS24EVK-24 SPITransfer(byte[] mosiData, out byte[] misoBuffer)
+            // Although the MAX30101EVKIT firmware will accept HID SPI commands, this firmware doesn't support SPI interface.
+            // verify: https://jira.maxim-ic.com/browse/OS24EVK-57 mutex lock HID.IOBuf[] in I2CConfigSet
+            mutexGuardIOBuf.WaitOne();   // Wait until it is safe to enter.
+            FlushQueue();
+            Array.Clear(IOBuf, 0, IOBuf.Length);
+            reportID();
+            // assign default out values in case of failure
+            int byteCount = mosiData.Length;
+            byte num_bytes = (byte)(byteCount & 0xFF);
+            misoBuffer = new byte[byteCount];
+            for (int byteIndex = 0; byteIndex < byteCount; byteIndex++)
+            {
+                // initial dummy data
+                misoBuffer[byteIndex] = 0x55;
+            }
+            IOBuf[1] = 9; // case (9):	// SPI transaction -- see usb_app.c int parseHIDReport(uint8_t *data_from_host, unsigned int len) 
+            //IOBuf[8] = x; // IO_BUFFER.Ptr[7+gOffset] -- first byte of data starts on the (7 + offset) byte
+            for (uint byteIndex = 0; byteIndex < num_bytes; byteIndex++)
+            {
+                IOBuf[8 + byteIndex] = (byte)(mosiData[byteIndex]);
+            }
+            //switch (SPImode)
+            //{
+            //    case 0:
+                    IOBuf[2] = 0; // IO_BUFFER.Ptr[1+gOffset] -- 0 for SPI_mode0: multi-byte SPI transfer.
+                    IOBuf[3] = 0; // IO_BUFFER.Ptr[2+gOffset] -- not used
+                    IOBuf[4] = 0; // IO_BUFFER.Ptr[3+gOffset] -- phase_change // !=0 enable changing the clock phase. some slaves change phase between write/read
+                    IOBuf[5] = 0; // IO_BUFFER.Ptr[4+gOffset] -- phase_change_byte // byte index where phase change should happen
+                    IOBuf[6] = num_bytes; // IO_BUFFER.Ptr[5+gOffset] -- num_bytes
+                    IOBuf[7] = 0; // IO_BUFFER.Ptr[6+gOffset] -- not used
+                    // IO_BUFFER.Ptr[7+gOffset] -- first byte of data starts on the (7 + offset) byte
+                    // SPI_mode0(IO_BUFFER.Ptr[3 + gOffset], IO_BUFFER.Ptr[4 + gOffset], IO_BUFFER.Ptr[5 + gOffset], IO_BUFFER.Ptr);
+                //    break;
+                //case 1:
+                //    IOBuf[2] = 1; // IO_BUFFER.Ptr[1+gOffset] -- 1 for SPI_mode1: two-byte SPI transfer. read flag: enable changing the clock phase on first byte and changing phase between first and second byte
+                //    IOBuf[3] = 0; // IO_BUFFER.Ptr[2+gOffset] -- read flag
+                //    // IO_BUFFER.Ptr[3+gOffset] -- not used
+                //    // IO_BUFFER.Ptr[4+gOffset] -- not used
+                //    // IO_BUFFER.Ptr[5+gOffset] -- not used; num_bytes = 2
+                //    // IO_BUFFER.Ptr[6+gOffset] -- not used
+                //    // IO_BUFFER.Ptr[7+gOffset] -- first byte of data starts on the (7 + offset) byte
+                //    // SPI_mode1(temp, IO_BUFFER.Ptr);
+                //    break;
+                //case 2:
+                //    IOBuf[2] = 2; // IO_BUFFER.Ptr[1+gOffset] --2 for SPI_mode2: two-byte SPI transfer. read flag: enable changing the clock phase on first byte and sampling the LSb after the second byte read
+                //    IOBuf[3] = 0; // IO_BUFFER.Ptr[2+gOffset] -- read flag
+                //    // IO_BUFFER.Ptr[3+gOffset] -- not used
+                //    // IO_BUFFER.Ptr[4+gOffset] -- not used
+                //    // IO_BUFFER.Ptr[5+gOffset] -- not used; num_bytes = 2
+                //    // IO_BUFFER.Ptr[6+gOffset] -- not used
+                //    // IO_BUFFER.Ptr[7+gOffset] -- first byte of data starts on the (7 + offset) byte
+                //    // SPI_mode2(temp, IO_BUFFER.Ptr);
+                //    break;
+            //}
+            writeHID();
+            // IO_BUFFER.Ptr[0] = SHORT_REPORT_ID;
+            // IO_BUFFER.Ptr[0+gOffset] = 0; // error status					
+            // IO_BUFFER.Ptr[1+gOffset] = gI2Cflags;
+            // IO_BUFFER.Ptr[2+gOffset] = (SMB0CF & 0x10) >> 4; // EXTHOLD
+            //gI2Cflags = IOBuf[2];
+            //EXTHOLD = IOBuf[3];
+            for (uint byteIndex = 0; byteIndex < byteCount; byteIndex++)
+            {
+                misoBuffer[byteIndex] = IOBuf[byteIndex + 2];
+            }
+            mutexGuardIOBuf.ReleaseMutex();    // Release the Mutex.
+        }
+        #endregion
+
+        #region Interrupt Commands
+        /// <summary>
+        /// <para>Firmware command code 23 OUT = enable INT0 (or Mock HID FIFO data diagnostic) </para>
+        /// <para>
+        /// - INT0Enable(0) disabled (EX0=0)
+        /// - INT0Enable(1) real hardware (EX0=1)
+        /// - INT0Enable(2) Mock HID x1 channel    101, 102, 103, ...
+        /// - INT0Enable(3) Mock HID x2 channels   101, 201, 102, 202, 103, 203, ...
+        /// - INT0Enable(4) Mock HID x3 channels   101, 201, 301, 102, 202, 302, 103, 203, 303, ...
+        /// - INT0Enable(5) Mock HID x4 channels   101, 201, 301, 401, 102, 202, 302, 402, 103, 203, 303, 403, ...
+        /// </para>
+        /// </summary>
+        /// <param name="EX0"></param>
+        public void INT0Enable(byte EX0)
+        {
+            // https://jira.maxim-ic.com/browse/OS24EVK-24 Refactor: HID report enum and wrappers
+            // reset report counter in the HID and enable INT0
+            // verify: https://jira.maxim-ic.com/browse/OS24EVK-57 mutex lock HID.IOBuf[] in INT0Enable
+            mutexGuardIOBuf.WaitOne();   // Wait until it is safe to enter.
+            FlushQueue();
+            Array.Clear(IOBuf, 0, IOBuf.Length);
+            reportID();
+            IOBuf[1] = 23; // enable INT0 -- see usb_app.c int parseHIDReport(uint8_t *data_from_host, unsigned int len) 
+            IOBuf[2] = EX0; // reportTypeFlag; // 1;
+            writeHID();
+            _firmwareINT0Enabled = EX0;
+            mutexGuardIOBuf.ReleaseMutex();    // Release the Mutex.
+        }
+        private byte _firmwareINT0Enabled = 0;
+        public byte FirmwareINT0Enabled { get { return _firmwareINT0Enabled; } }
+        #endregion
+
+        #endregion
+
+
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HspGuiSourceV301/GuiDLLs/RPCSupport/HidSupport/support.cs	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,202 @@
+/*******************************************************************************
+* Copyright (C) 2016 Maxim Integrated Products, Inc., All rights Reserved.
+* 
+* This software is protected by copyright laws of the United States and
+* of foreign countries. This material may also be protected by patent laws
+* and technology transfer regulations of the United States and of foreign
+* countries. This software is furnished under a license agreement and/or a
+* nondisclosure agreement and may only be used or reproduced in accordance
+* with the terms of those agreements. Dissemination of this information to
+* any party or parties not specified in the license agreement and/or
+* nondisclosure agreement is expressly prohibited.
+*
+* The above copyright notice and this permission notice shall be included
+* in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+* OTHER DEALINGS IN THE SOFTWARE.
+*
+* Except as contained in this notice, the name of Maxim Integrated
+* Products, Inc. shall not be used except as stated in the Maxim Integrated
+* Products, Inc. Branding Policy.
+*
+* The mere transfer of this software does not imply any licenses
+* of trade secrets, proprietary technology, copyrights, patents,
+* trademarks, maskwork rights, or any other form of intellectual
+* property whatsoever. Maxim Integrated Products, Inc. retains all
+* ownership rights.
+*******************************************************************************
+*/
+
+using System;
+using System.Windows.Forms;
+
+//------------------------------------------------------------------------------------------
+// OS24EVK-59 split into HeartRateApp EXE and MAX30101 DLL.
+// Moved all MAX30101 DLL classes into namespace Maxim.MAX30101GUI
+// Moved all HeartRateApp GUI classes into namespace Maxim.MAX30101
+// OS24EVK-59 Create separate project that builds Maxim.MAX30101GUI DLL library
+
+// OS24EVK-59 moved class support into namespace Maxim.MAX30101 instead of namespace HeartRateApp
+namespace RPCSupport
+{
+    internal static class support
+    {
+        public const int DEFAULT_VENDOR_ID = 0x0B6A; // update USB VID PID from default Vid_16C0&Pid_0830
+        public const int DEFAULT_PRODUCT_ID = 0x1366; // MAX30100EVKit USB Vid_0B6A&Pid_1364; MAX30101EVKit USB Vid_0B6A&Pid_1365
+        public const byte DEFAULT_I2C_ADDRESS = 0xAE;   // 8-bit address (write address)
+
+        public static Control getControlFromName(Control Page, string controlName)
+        {
+            // getControlFromName was split into two functions: 1) this function called by other subs so that "found" does not need to be declared and passed
+            // and 2) getControlFromNameRecurse which uses the "found" parameter 
+            Boolean found = false;
+
+            try
+            {
+                return getControlFromNameRecurse(Page, controlName, ref found);
+            }
+            catch (Exception ex)
+            {
+                throw new Exception(ex.Message + Environment.NewLine + new System.Diagnostics.StackFrame().GetMethod().Name);
+            }
+        }
+
+        private static Control getControlFromNameRecurse(Control Page, string controlName, ref Boolean found)
+        {
+            Control returnVal = null;
+
+            try
+            {
+                foreach (Control ctrl in Page.Controls)
+                {
+                    if (!found)
+                    {// found is passed by reference; hence when a recursive call finds the control, found will always be True for all calls under the initial call
+                        if (String.Compare(ctrl.Name, controlName, true) == 0)
+                        {
+                            found = true;
+                            returnVal = ctrl;
+                        }
+                        else if (ctrl.Controls.Count > 0)
+                        {
+                            returnVal = getControlFromNameRecurse(ctrl, controlName, ref found);
+                        }
+                    }
+                }
+                return returnVal;
+            }
+            catch (Exception ex)
+            {
+                throw new Exception(ex.Message + Environment.NewLine + new System.Diagnostics.StackFrame().GetMethod().Name);
+            }
+        }
+
+        public static byte getControlIndex(Control sender)
+        {
+            //This function finds the 'index' of a control 'array'. Since there are no control arrays in .Net,
+            //we name all the controls consistently and suffix them with an integer. This integer is the 'index' and is returned by this function.
+            int iterator;
+            int i = 0;
+            String name = sender.Name;
+
+            try
+            {
+                iterator = name.Length;
+                while (char.IsNumber(name, iterator - 1))
+                {
+                    i+=1;
+                    iterator-=1;
+                    if (iterator == 0)
+                        break;
+                }
+                if (i == 0)
+                    throw new Exception("Not a control array");
+                return Convert.ToByte(name.Substring(name.Length - i, i));
+            }
+            catch (Exception ex)
+            {
+                throw new Exception(ex.Message + Environment.NewLine + new System.Diagnostics.StackFrame().GetMethod().Name);
+            }
+        }
+
+        //http://www.vbforums.com/showthread.php?t=546633
+        //use this to make a delay
+        public static void Pause(int msDelay)
+        {
+            DateTime Timeout;
+            DateTime PrevTimer;
+
+            try
+            {
+                PrevTimer = System.DateTime.Now;
+                Timeout = PrevTimer.AddMilliseconds(msDelay);
+                while (PrevTimer < Timeout)
+                {
+                    FileIO.Sleep(4); //-- Timer is only updated every 1/64 sec = 15.625 millisecs.
+                    Application.DoEvents(); //DoEvents seems to be not recommended; is there a better way to do this?
+                    //DoEvents really does cause trouble. Example: pause on device change causes closeHandles and openHandles NOT to run in order!
+                    if (System.DateTime.Now < PrevTimer)
+                        Timeout = Timeout.AddHours(-24); //-- pass midnight
+                    PrevTimer = System.DateTime.Now;
+                }
+            }
+            catch (Exception ex)
+            {
+                throw new Exception(ex.Message + Environment.NewLine + new System.Diagnostics.StackFrame().GetMethod().Name);
+            }
+        }
+
+        public const int FORMAT_MESSAGE_FROM_SYSTEM = 0x1000;
+        /// <summary>
+        /// Get text that describes the result of an API call.
+        /// </summary>
+        /// 
+        /// <param name="functionName"> the name of the API function. </param>
+        /// 
+        /// <returns>
+        /// The text.
+        /// </returns>
+        /// 
+        public static string ResultOfAPICall(string functionName) 
+        {
+            int bytes;
+            int resultCode;
+            string resultString = "";
+            int length = 1000;
+
+            try
+            {
+                resultString = new String((char)0, length); // create space for string with all elements set to NULL
+
+                // Returns the result code for the last API call.
+
+                resultCode = System.Runtime.InteropServices.Marshal.GetLastWin32Error();
+
+                // Get the result message that corresponds to the code.
+
+                bytes = FileIO.FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, 0, resultCode, 0, resultString, length - 1, 0);
+
+                // Subtract all characters from the message from the CR LF and NULLs to the end
+                // Important to remove all NULLs since VB doesn't use NULL to demark end of string, and thus when concatenating strings, the NULLs are troublesome
+
+                if (bytes > 2)
+                    resultString = resultString.Remove(bytes - 2, length - bytes + 2);
+                
+                // Create the string to return.
+
+                resultString = functionName + Environment.NewLine + "Result = " + resultString;
+
+                return resultString;
+            }
+            catch (Exception ex)
+            {
+                throw new Exception(ex.Message + Environment.NewLine + new System.Diagnostics.StackFrame().GetMethod().Name);
+            }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HspGuiSourceV301/GuiDLLs/RPCSupport/Logging/Logging.cs	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,136 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using RPCSupport.Devices;
+using System.Globalization;
+
+namespace RPCSupport.Logging
+{
+    public class Logging : ClientDevice
+    {
+
+        public bool enabledEcg;
+        public bool enabledBioz;
+        public bool enabledRtoR;
+        public bool enabledPace;
+        public bool enabledTemp1;
+        public bool enabledTemp2;
+        public bool enabledPressure;
+        public bool enabledAccel;
+        public struct parametersEcg_Struct
+        {
+        }
+        public struct parametersBioz_Struct
+        {
+        }
+        public struct parametersRtoR_Struct
+        {
+        }
+        public struct parametersPace_Struct
+        {
+        }
+        public struct parametersTemp1_Struct
+        {
+            public int sampleRate;  // seconds
+        } 
+        public parametersTemp1_Struct parametersTemp1;
+
+        public struct parametersTemp2_Struct
+        {
+            public int sampleRate;  // seconds
+        }
+        public struct parametersPressure_Struct
+        {
+            public int sampleRate;  // seconds
+        }
+        public struct parametersAccel_Struct
+        {
+            public int sampleRate;  // seconds
+        }
+
+
+        const string CLASSNAME = "Logging";
+        public Logging(RPCClient client)
+            : base(client)
+        {
+
+        }
+        public void ReadMission()
+        {
+            int val;
+            string cmd;
+            string reply;
+
+            reply = Call(CLASSNAME, "ReadMission");
+
+            // parse through reply string here
+            //
+            //
+
+        }
+        public void WriteMission()
+        {
+            int val;
+            string cmd;
+            string reply;
+
+            reply = Call(CLASSNAME, "StartMissionDefine");
+            enabledTemp1 = true;
+            //if (enabledTemp1)
+            //{
+            parametersTemp1.sampleRate = 1;
+            cmd = String.Format("\"/BMP280/InitStart {0}\"", 1);
+            reply = Call(CLASSNAME, "AppendMissionCmd", cmd);
+            cmd = String.Format("\"/MAX31725/InitStart {0}\"", 2);
+            reply = Call(CLASSNAME, "AppendMissionCmd", cmd);
+            cmd = String.Format("\"/BMP280/InitStart {0}\"", 3);
+            reply = Call(CLASSNAME, "AppendMissionCmd", cmd);
+            //}
+            reply = Call(CLASSNAME, "EndMissionDefine");
+            reply = Call(CLASSNAME, "WriteMission");
+
+            //reply = Call(CLASSNAME, "ReadReg", addr.ToString("X2"));
+            //int.TryParse(reply, NumberStyles.HexNumber, CultureInfo.CurrentCulture, out val);
+        }
+
+
+        public void EraseMission()
+        {
+            int val;
+            string cmd;
+            string reply;
+
+            reply = Call(CLASSNAME, "EraseMission");
+        }
+
+        public void TestMission()
+        {
+            int val;
+            string cmd;
+            string reply;
+
+            reply = Call(CLASSNAME, "TestStartMission");
+        }
+
+        public void TestWriteLog()
+        {
+            throw new NotImplementedException();
+        }
+
+        public void TestReadLog()
+        {
+            throw new NotImplementedException();
+        }
+
+        public void TestBulkErase()
+        {
+            throw new NotImplementedException();
+        }
+
+        public void TestLogSectorsErase()
+        {
+            throw new NotImplementedException();
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HspGuiSourceV301/GuiDLLs/RPCSupport/Pipelines/DataLogPipeline.cs	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,241 @@
+/*******************************************************************************
+* Copyright (C) 2016 Maxim Integrated Products, Inc., All rights Reserved.
+* 
+* This software is protected by copyright laws of the United States and
+* of foreign countries. This material may also be protected by patent laws
+* and technology transfer regulations of the United States and of foreign
+* countries. This software is furnished under a license agreement and/or a
+* nondisclosure agreement and may only be used or reproduced in accordance
+* with the terms of those agreements. Dissemination of this information to
+* any party or parties not specified in the license agreement and/or
+* nondisclosure agreement is expressly prohibited.
+*
+* The above copyright notice and this permission notice shall be included
+* in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+* OTHER DEALINGS IN THE SOFTWARE.
+*
+* Except as contained in this notice, the name of Maxim Integrated
+* Products, Inc. shall not be used except as stated in the Maxim Integrated
+* Products, Inc. Branding Policy.
+*
+* The mere transfer of this software does not imply any licenses
+* of trade secrets, proprietary technology, copyrights, patents,
+* trademarks, maskwork rights, or any other form of intellectual
+* property whatsoever. Maxim Integrated Products, Inc. retains all
+* ownership rights.
+*******************************************************************************
+*/
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using RPCSupport.Pipelines;
+using System.Globalization;
+
+namespace RPCSupport
+{
+    public class DataLogPipeline : Pipeline
+    {
+        int page;
+        bool isConnected;
+        bool endOfLog = false;
+        Pipeline proxyPipeline;
+
+        const int  DATALOG_PARAMETER_PAGE = 0x0;
+        const int  DATALOG_RESUME_TABLE_PAGE = 0x10;
+        const int  DATALOG_DATA_PAGE = 0x12;
+        class DataLogPacket
+        {
+            public int index;
+            public char[] buffer;
+            public int LengthLeft()
+            {
+                return buffer.Length - index;
+            }
+            public char FetchChar()
+            {
+                char ch = (char)buffer[index++];
+                return ch;
+            }
+        }
+        Queue<DataLogPacket> queue = new Queue<DataLogPacket>();
+        public void SetProxyPipeline(Pipeline pipeline)
+        {
+            page = DATALOG_DATA_PAGE;
+            isConnected = true;
+            proxyPipeline = pipeline;
+            endOfLog = false;
+        }
+
+        public override string RawRpcCall(string request, bool reply)
+        {
+            throw new NotImplementedException();
+        }
+
+        public override void SendSingleByte(char ch)
+        {
+            throw new NotImplementedException();
+        }
+
+        public override void Discard()
+        {
+            throw new NotImplementedException();
+        }
+
+        public override string RawRpcCallBinary(string request, bool reply, out bool allOnes)
+        {
+            throw new NotImplementedException();
+        }
+
+        public override bool IsConnected()
+        {
+            return true;
+        }
+
+        public override string ReadString()
+        {
+            throw new NotImplementedException();
+        }
+
+        public override int Read(char[] buffer, int offset, int count)
+        {
+            int numberRead = 0;
+            char[] currentBuffer = ReadDataLog(buffer, offset, count, out numberRead);
+            //String returnStr = "";
+            //bool allOnes;
+            //returnStr = proxyPipeline.CallBinary("S25FS512", "ReadPagesBinary", out allOnes, new String[] { page.ToString("X2"), page.ToString("X2") });
+            return numberRead;
+        }
+
+        private char[] ReadDataLog(char[] buffer, int offset, int count, out int numberRead)
+        {
+            // if queue empty then read from datalog
+            if (queue.Count == 0)
+            {
+                QueuePage();
+            }
+             // get the log packet at the top of the queue
+            DataLogPacket currentPacket = queue.Peek();
+           // check if we need to get another page queued if more buffer count is needed
+            bool extraQueued = false;
+            int currentPacketIndex = currentPacket.index;
+            int currentPacketLengthLeft = currentPacket.LengthLeft();
+            if (currentPacket.LengthLeft() < count)
+            {
+                QueuePage();
+                extraQueued = true;
+            }
+            // get data from the queue
+            for (int i = 0; i < count; i++)
+            {
+                buffer[i] = currentPacket.FetchChar();
+                // if there is no data left in this packet then get the next packet
+                if (currentPacket.LengthLeft() == 0 && i != (count - 1))
+                {
+                    if (queue.Count != 2)
+                    {
+                    }
+                    queue.Dequeue();
+                    currentPacket = queue.Peek();
+                }
+            }
+            // if this is the last buffer then return count of 0 to end the stream
+            //if (IsAllFF(currentPacket.buffer) == true) count = 0;
+            // if the DataLogPacket is exhasted then dequeue it, we are finished with it
+            if (currentPacket.LengthLeft() == 0)
+            {
+                queue.Dequeue();
+            }
+            if (endOfLog == true)
+            {
+                count = 0;
+            }
+            numberRead = count;
+            return buffer;
+        }
+
+        private void QueuePage()
+        {
+            byte[] buf = ReadPageFromFlash(page);
+            if (page >= 0x18F)
+            {
+                //endOfLog = true;
+            }
+            if (IsAllFF(buf) == true)
+            {
+                endOfLog = true;
+            }
+            page++;
+            char[] charArray = BinToCharArray(buf);
+            DataLogPacket packet = new DataLogPacket();
+            packet.buffer = charArray;
+            packet.index = 0;
+            queue.Enqueue(packet);
+        }
+
+        private char[] BinToCharArray(byte[] buf)
+        {
+            int val;
+            int val1;
+            int val2;
+            int val3;
+            int val4;
+            StringBuilder sb = new StringBuilder();
+            for (int i = 0; i < buf.Length / 4; i++) {
+                val1 = (int)buf[i*4 + 3] << 24;
+                val2 = (int)buf[i*4 + 2] << 16;
+                val3 = (int)buf[i*4 + 1] << 8;
+                val4 = (int)buf[i*4 + 0] << 0;
+                val = val1 + val2 + val3 + val4;
+                sb.Append(String.Format("{0:X} ", val));
+            }
+            char[] chars = sb.ToString().ToCharArray();
+            return chars;
+        }
+
+        private byte[] ReadPageFromFlash(int pageToRead)
+        {
+            String returnStr = "";
+            bool allOnes;
+            returnStr = proxyPipeline.CallBinary("S25FS512", "ReadPagesBinary", out allOnes, new String[] { pageToRead.ToString("X2"), pageToRead.ToString("X2") });
+            byte[] array = LineToArray(returnStr);
+            return array;
+        }
+
+        private bool IsAllFF(byte[] buffer)
+        {
+            for (int i = 0; i < buffer.Length; i++)
+            {
+                if (buffer[i] != 0xFF) return false;
+            }
+            return true;
+        }
+
+        private byte[] LineToArray(String hexStr)
+        {
+            byte val;
+            List<byte> intList = new List<byte>();
+            String[] strings = hexStr.Split(new char[] { ' ' });
+            foreach (String str in strings)
+            {
+                if (byte.TryParse(str, NumberStyles.HexNumber, CultureInfo.CurrentCulture, out val))
+                {
+                    intList.Add(val);
+                }
+                else
+                {
+                    throw new Exception(String.Format("Error In hex string \"{0}\" in \"{1}\"", str, hexStr));
+                }
+            }
+            return intList.ToArray();
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HspGuiSourceV301/GuiDLLs/RPCSupport/Pipelines/HidPipeline.cs	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,119 @@
+/*******************************************************************************
+* Copyright (C) 2016 Maxim Integrated Products, Inc., All rights Reserved.
+* 
+* This software is protected by copyright laws of the United States and
+* of foreign countries. This material may also be protected by patent laws
+* and technology transfer regulations of the United States and of foreign
+* countries. This software is furnished under a license agreement and/or a
+* nondisclosure agreement and may only be used or reproduced in accordance
+* with the terms of those agreements. Dissemination of this information to
+* any party or parties not specified in the license agreement and/or
+* nondisclosure agreement is expressly prohibited.
+*
+* The above copyright notice and this permission notice shall be included
+* in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+* OTHER DEALINGS IN THE SOFTWARE.
+*
+* Except as contained in this notice, the name of Maxim Integrated
+* Products, Inc. shall not be used except as stated in the Maxim Integrated
+* Products, Inc. Branding Policy.
+*
+* The mere transfer of this software does not imply any licenses
+* of trade secrets, proprietary technology, copyrights, patents,
+* trademarks, maskwork rights, or any other form of intellectual
+* property whatsoever. Maxim Integrated Products, Inc. retains all
+* ownership rights.
+*******************************************************************************
+*/
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Collections;
+//using Maxim.MAX30101;
+
+namespace RPCSupport.Pipelines
+{
+    class HidPipeline : Pipeline
+    {
+        private HID myHID = new HID();
+
+        public override bool IsConnected()
+        {
+            return myHID.isConnected();
+        }
+
+        public override bool Init()
+        {
+            myHID.findHIDs();
+            return true;
+        }
+
+        /*public String Call(string name, string method, params string[] args)
+        {
+            return SendRPC(name, method, args);
+        }*/
+
+        public override void Connect(string name)
+        {
+        }
+
+        public override void Disconnect()
+        {
+        }
+
+        public override String[] ScanAvailablePortNames()
+        {
+            return null;
+        }
+
+        new public byte GetReturnValue_Byte()
+        {
+            return 0;
+        }
+
+        /*public String GetReturnValue()
+        {
+            return "";
+        }*/
+
+        // /I2c/WriteMultiReg 01 90 02 02 12 34
+        public override string RawRpcCall(string request, bool reply)
+        {
+            if (rawRpcRequest != null) rawRpcRequest(request);
+            String replyStr = myHID.RPC_Call(request);
+            if (rawRpcReply != null) rawRpcReply(replyStr);
+            return replyStr;
+        }
+        public override void SendSingleByte(char ch)
+        {
+            throw new NotImplementedException();
+        }
+        public override string ReadString()
+        {
+            throw new NotImplementedException();
+        }
+        public override int Read(char[] buffer, int offset, int count)
+        {
+            throw new NotImplementedException();
+        }
+        public override void Discard()
+        {
+            throw new NotImplementedException();
+        }
+
+        public override string RawRpcCallBinary(string request, bool reply, out bool allOnes)
+        {
+            allOnes = false;
+            throw new NotImplementedException();
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HspGuiSourceV301/GuiDLLs/RPCSupport/Pipelines/Pipeline.cs	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,216 @@
+/*******************************************************************************
+* Copyright (C) 2016 Maxim Integrated Products, Inc., All rights Reserved.
+* 
+* This software is protected by copyright laws of the United States and
+* of foreign countries. This material may also be protected by patent laws
+* and technology transfer regulations of the United States and of foreign
+* countries. This software is furnished under a license agreement and/or a
+* nondisclosure agreement and may only be used or reproduced in accordance
+* with the terms of those agreements. Dissemination of this information to
+* any party or parties not specified in the license agreement and/or
+* nondisclosure agreement is expressly prohibited.
+*
+* The above copyright notice and this permission notice shall be included
+* in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+* OTHER DEALINGS IN THE SOFTWARE.
+*
+* Except as contained in this notice, the name of Maxim Integrated
+* Products, Inc. shall not be used except as stated in the Maxim Integrated
+* Products, Inc. Branding Policy.
+*
+* The mere transfer of this software does not imply any licenses
+* of trade secrets, proprietary technology, copyrights, patents,
+* trademarks, maskwork rights, or any other form of intellectual
+* property whatsoever. Maxim Integrated Products, Inc. retains all
+* ownership rights.
+*******************************************************************************
+*/
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Globalization;
+using System.Collections;
+
+namespace RPCSupport.Pipelines
+{
+    public abstract class Pipeline 
+    {
+        public delegate void RawRpcRequest(string s);
+        public delegate void RawRpcReply(string s);
+        public delegate void RawRpcStream(string s);
+        internal RawRpcRequest rawRpcRequest;
+        internal RawRpcReply rawRpcReply;
+        internal RawRpcStream rawRpcStream;
+        public virtual bool Init()
+        {
+            return true;
+        }
+
+        public abstract string RawRpcCall(string request, bool reply);
+        public abstract void SendSingleByte(char ch);
+        public abstract void Discard();
+        public abstract string RawRpcCallBinary(string request, bool reply, out bool allOnes);
+
+        public void LogStream(string stream)
+        {
+            if (rawRpcStream != null)
+            {
+                rawRpcStream(stream);
+            }
+        }
+
+        /*public virtual bool IsConnected()
+        {
+            return false;
+        }*/
+        public abstract bool IsConnected();
+
+        public void LogCallback(RawRpcRequest request, RawRpcReply reply, RawRpcStream stream)
+        {
+            rawRpcRequest = request;
+            rawRpcReply = reply;
+            rawRpcStream = stream;
+        }
+
+        public String Call(string name, string method, params string[] args)
+        {
+            return SendRPC(name, method, args);
+        }
+
+        public String CallBinary(string name, string method, out bool allOnes, params string[] args)
+        {
+            return SendRPCBinary(name, method, out allOnes, args);
+        }
+
+        public String CallNoReply(string name, string method, params string[] args)
+        {
+            return SendRPCNoReply(name, method, args);
+        }
+
+        public virtual void Connect(string name)
+        {
+        }
+
+        public virtual void Disconnect()
+        {
+        }
+
+        public virtual String[] ScanAvailablePortNames()
+        {
+            return null;
+        }
+
+        public byte GetReturnValue_Byte()
+        {
+            return 0;
+        }
+
+        public String GetReturnValue()
+        {
+            return "";
+        }
+
+        private String TrimArgument(String str)
+        {
+            String strOut = "0";
+            String strIn = str.TrimStart(new char[] { '0' });
+            if (String.IsNullOrEmpty(strIn) == false)
+            {
+                strOut = strIn;
+            }
+            return strOut;
+        }
+
+        public String SendRPC(String Name, String Method, params String[] Args)
+        {
+            //write to serial port and receive result
+            String Arguments = "";
+
+            if (Args != null)
+            {
+                for (int i = 0; i < Args.Length; i++)
+                {
+                    Arguments = Arguments + " " + TrimArgument(Args[i]);
+                }
+            }
+
+            String request = "/" + Name + "/" + Method + Arguments + "\r\n";
+            Console.WriteLine(request);
+            String reply = RawRpcCall(request, true);
+
+            return reply;
+        }
+
+        public String SendRPCNoReply(String Name, String Method, params String[] Args)
+        {
+            //write to serial port and receive result
+            String Arguments = "";
+
+            if (Args != null)
+            {
+                for (int i = 0; i < Args.Length; i++)
+                {
+                    Arguments = Arguments + " " + Args[i];
+                }
+            }
+
+            String request = "/" + Name + "/" + Method + Arguments + "\r\n";
+            String reply = RawRpcCall(request, false);
+
+            return reply;
+        }
+
+        public String SendRPCBinary(String Name, String Method, out bool allOnes, params String[] Args)
+        {
+            //write to serial port and receive result
+            String Arguments = "";
+
+            if (Args != null)
+            {
+                for (int i = 0; i < Args.Length; i++)
+                {
+                    Arguments = Arguments + " " + Args[i];
+                }
+            }
+
+            String request = "/" + Name + "/" + Method + Arguments + "\r\n";
+            String reply = RawRpcCallBinary(request, false, out allOnes);
+
+            return reply;
+        }
+
+
+        public byte StringToByte(String reply)
+        {
+            byte val = 0xFF;
+            if (byte.TryParse(reply, NumberStyles.HexNumber, CultureInfo.CurrentCulture, out val))
+            {
+            }
+            return val;
+        }
+
+
+        internal byte[] StringToMultiBytes(string reply, byte numBytes)
+        {
+            byte[] data = new Byte[numBytes];
+            string[] strings = reply.Split(new char[] { ' ' });
+            for (int i = 0; i < numBytes; i++)
+            {
+                data[i] = StringToByte(strings[i]);
+            }
+            return data;
+        }
+
+        public abstract string ReadString();
+        public abstract int Read(char[] buffer, int offset, int count);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HspGuiSourceV301/GuiDLLs/RPCSupport/Pipelines/SerialPipeline.cs	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,277 @@
+/*******************************************************************************
+* Copyright (C) 2016 Maxim Integrated Products, Inc., All rights Reserved.
+* 
+* This software is protected by copyright laws of the United States and
+* of foreign countries. This material may also be protected by patent laws
+* and technology transfer regulations of the United States and of foreign
+* countries. This software is furnished under a license agreement and/or a
+* nondisclosure agreement and may only be used or reproduced in accordance
+* with the terms of those agreements. Dissemination of this information to
+* any party or parties not specified in the license agreement and/or
+* nondisclosure agreement is expressly prohibited.
+*
+* The above copyright notice and this permission notice shall be included
+* in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+* OTHER DEALINGS IN THE SOFTWARE.
+*
+* Except as contained in this notice, the name of Maxim Integrated
+* Products, Inc. shall not be used except as stated in the Maxim Integrated
+* Products, Inc. Branding Policy.
+*
+* The mere transfer of this software does not imply any licenses
+* of trade secrets, proprietary technology, copyrights, patents,
+* trademarks, maskwork rights, or any other form of intellectual
+* property whatsoever. Maxim Integrated Products, Inc. retains all
+* ownership rights.
+*******************************************************************************
+*/
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.IO.Ports;
+using System.Diagnostics;
+using RPCSupport.Pipelines;
+using System.Threading;
+using System.Collections;
+
+namespace RPCSupport
+{
+    public class SerialPipeline : Pipeline {
+	    protected SerialPort serialPort;
+
+        public SerialPipeline() 
+        {
+            serialPort = new SerialPort();
+	    }
+
+        public override void Connect(String PortName)
+        {
+            // Set the read/write timeouts
+            serialPort.ReadTimeout = 90000;
+            serialPort.WriteTimeout = 90000;
+
+            serialPort.PortName = PortName;
+            serialPort.BaudRate = 9600;
+
+            // always the same
+            serialPort.DataBits = 8;
+            serialPort.Parity = Parity.None;
+            serialPort.StopBits = StopBits.One;
+            serialPort.Handshake = Handshake.None;
+
+            serialPort.DtrEnable = true;
+            serialPort.RtsEnable = true;
+            Thread.Sleep(10);
+            serialPort.Open();
+
+            //serialPort.DataReceived += new SerialDataReceivedEventHandler(serialPort_DataReceived);
+            //serialPort.ErrorReceived += new SerialErrorReceivedEventHandler(serialPort_ErrorReceived);
+        }
+
+        public override void Disconnect()
+        {
+            serialPort.Close();
+        }
+
+        public override bool IsConnected()
+        {
+            return serialPort.IsOpen;
+        }
+
+        public override String[] ScanAvailablePortNames()
+        {
+            return SerialPort.GetPortNames();
+        }
+
+        /*
+	    public override String SendRPC(String Name, String Method, params String[] Args)
+        {
+		    //write to serial port and receive result
+		    String Response;
+		    String Arguments = "";
+
+		    if(Args != null)
+            {
+			    for(int i = 0; i < Args.Length; i++)
+                {
+				    Arguments = Arguments + " " + Args[i];
+			    }
+		    }
+
+            serialPort.DiscardInBuffer();
+            String sendString = "/" + Name + "/" + Method + Arguments + "\r\n";
+            String reply = RawRpcCall(sendString);
+
+            return reply;
+	    }*/
+
+        /*
+	    public override void delete()
+        {
+		    //Close the serial port
+            if (serialPort != null) serialPort.Close();
+        }
+        */
+
+        private void serialPort_DataReceived(object sender, EventArgs e)
+        {
+            Debug.Print("Serial Port event");
+            //String Interrupt = serialPort.ReadLine();
+            String str = serialPort.ReadExisting();
+        }
+
+        private void serialPort_ErrorReceived(object sender, EventArgs e)
+        {
+            Debug.Print("Serial Port error");
+        }
+
+
+
+
+        //
+        // Serial Byte Collection Thread
+        //
+        /*private BackgroundWorker bw = new BackgroundWorker();
+        private void InitThread()
+        {
+            bw.WorkerReportsProgress = true;
+            bw.WorkerSupportsCancellation = true;
+            bw.DoWork += new DoWorkEventHandler(bw_DoWork);
+            bw.ProgressChanged += new ProgressChangedEventHandler(bw_ProgressChanged);
+            bw.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bw_RunWorkerCompleted);
+        }
+        private void StartThread()
+        {
+            if (bw.IsBusy != true)
+            {
+                bw.RunWorkerAsync();
+            }
+        }
+        private void StopThread()
+        {
+            if (bw.WorkerSupportsCancellation == true)
+            {
+                bw.CancelAsync();
+            }
+        }
+        private void bw_DoWork(object sender, DoWorkEventArgs e)
+        {
+            BackgroundWorker worker = sender as BackgroundWorker;
+
+            for (int i = 1; (i <= 10); i++)
+            {
+                if ((worker.CancellationPending == true))
+                {
+                    e.Cancel = true;
+                    break;
+                }
+                else
+                {
+                    // Perform a time consuming operation and report progress.
+                    System.Threading.Thread.Sleep(500);
+                    worker.ReportProgress((i * 10));
+                }
+            }
+        }*/
+
+        public override string RawRpcCall(string request, bool reply)
+        {
+            if (rawRpcRequest != null) rawRpcRequest(request);
+            //String reply = myHID.RPC_Call(request);
+            serialPort.WriteLine(request);
+            if (reply == false) return "";
+
+            string replyStr;
+            //replyStr = serialPort.ReadLine();
+            int ch;
+            int lastCh;
+            bool gotCR = false;
+            bool gotLF = false;
+            lastCh = 0;
+            ch = serialPort.ReadByte();
+            StringBuilder sb = new StringBuilder();
+            StringBuilder sbDebug = new StringBuilder();
+            while (ch != -1)
+            {
+                //sbDebug.Append("0x" + ch.ToString("X2") + " ");
+                if (ch != '\n') 
+                    sb.Append((char)ch);
+                if (lastCh == '\r' && ch == '\n') break;
+                lastCh = ch;
+                ch = serialPort.ReadByte();
+            }
+            replyStr = sb.ToString();
+            if (rawRpcReply != null) rawRpcReply(sbDebug.ToString());
+            if (rawRpcReply != null) rawRpcReply(replyStr);
+            return replyStr;
+        }
+
+        public override string RawRpcCallBinary(string request, bool reply, out bool allOnes)
+        {
+            if (rawRpcRequest != null) rawRpcRequest(request);
+            //String reply = myHID.RPC_Call(request);
+            serialPort.WriteLine(request);
+            //if (reply == false) return "";
+
+            byte[] buffer = new byte[256];
+            int bytesToRead = 256;
+            while (bytesToRead != 0)
+            {
+                int bytesRead = serialPort.Read(buffer, 256 - bytesToRead, bytesToRead);
+                bytesToRead -= bytesRead;
+            }
+            allOnes = true;
+            for (int i = 0; i < 256; i++) {
+                if (buffer[i] != 0xFF) allOnes = false;
+            }
+            string replyStr;
+            StringBuilder sb = new StringBuilder();
+            for (int i = 0; i < 256; i++)
+            {
+                sb.Append(buffer[i].ToString("X2") + " ");
+            }
+            //replyStr = serialPort.ReadLine();
+            replyStr = sb.ToString().Trim();
+            String otherStr = serialPort.ReadLine();
+            if (rawRpcReply != null) rawRpcReply(replyStr);
+            return replyStr;
+        }
+
+        public override void SendSingleByte(char ch)
+        {
+            if (rawRpcRequest != null) rawRpcRequest("<" + ch + ">");
+            char[] chArray = new char[1];
+            chArray[0] = ch;
+            serialPort.Write(chArray, 0, 1);
+        }
+        public override string ReadString()
+        {
+            return serialPort.ReadExisting();
+        }
+        public override int Read(char[] buffer, int offset, int count)
+        {
+            int val = 0;
+            try
+            {
+                val = serialPort.Read(buffer, offset, count);
+            }
+            catch (Exception)
+            {
+            }
+            return val;
+        }
+        public override void Discard()
+        {
+            serialPort.DiscardInBuffer();
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HspGuiSourceV301/GuiDLLs/RPCSupport/Pipelines/SerialWrapPipeline.cs	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,232 @@
+/*******************************************************************************
+* Copyright (C) 2016 Maxim Integrated Products, Inc., All rights Reserved.
+* 
+* This software is protected by copyright laws of the United States and
+* of foreign countries. This material may also be protected by patent laws
+* and technology transfer regulations of the United States and of foreign
+* countries. This software is furnished under a license agreement and/or a
+* nondisclosure agreement and may only be used or reproduced in accordance
+* with the terms of those agreements. Dissemination of this information to
+* any party or parties not specified in the license agreement and/or
+* nondisclosure agreement is expressly prohibited.
+*
+* The above copyright notice and this permission notice shall be included
+* in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+* OTHER DEALINGS IN THE SOFTWARE.
+*
+* Except as contained in this notice, the name of Maxim Integrated
+* Products, Inc. shall not be used except as stated in the Maxim Integrated
+* Products, Inc. Branding Policy.
+*
+* The mere transfer of this software does not imply any licenses
+* of trade secrets, proprietary technology, copyrights, patents,
+* trademarks, maskwork rights, or any other form of intellectual
+* property whatsoever. Maxim Integrated Products, Inc. retains all
+* ownership rights.
+*******************************************************************************
+*/
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.IO.Ports;
+using System.Diagnostics;
+using RPCSupport.Pipelines;
+using System.Threading;
+using System.Collections;
+
+using SerialWrap;
+
+namespace RPCSupport
+{
+    public class SerialWrapPipeline : Pipeline {
+	    protected SerialPortIo serialPortIo;
+        SerialPortConfig serialPortConfig;
+
+        public SerialWrapPipeline() 
+        {
+            //serialPort = new SerialPort();
+	    }
+
+        public int ReadTimeout
+        {
+            set
+            {
+                serialPortIo.ReadTimeout = value;
+            }
+            get
+            {
+                return serialPortIo.ReadTimeout;
+            }
+        }
+
+        public override void Connect(String PortName)
+        {
+            serialPortConfig = new SerialPortConfig(PortName, 9600, 8, StopBits.One, Parity.None, true, true);
+
+            /*
+            // Set the read/write timeouts
+            serialPort.ReadTimeout = 90000;
+            serialPort.WriteTimeout = 90000;
+
+            serialPort.PortName = PortName;
+            serialPort.BaudRate = 9600;
+
+            // always the same
+            serialPort.DataBits = 8;
+            serialPort.Parity = Parity.None;
+            serialPort.StopBits = StopBits.One;
+            serialPort.Handshake = Handshake.None;
+
+            serialPort.DtrEnable = true;
+            serialPort.RtsEnable = true;
+            */
+
+            serialPortIo = new SerialPortIo(serialPortConfig);
+
+            serialPortIo.ReadTimeout = 1300;
+            //Thread.Sleep(10);
+            //serialPort.Open();
+
+            //serialPort.DataReceived += new SerialDataReceivedEventHandler(serialPort_DataReceived);
+            //serialPort.ErrorReceived += new SerialErrorReceivedEventHandler(serialPort_ErrorReceived);
+        }
+
+        public override void Disconnect()
+        {
+            serialPortIo.Dispose();
+        }
+
+        public override bool IsConnected()
+        {
+            return serialPortIo.IsOpen;
+        }
+
+        public override String[] ScanAvailablePortNames()
+        {
+            return SerialPort.GetPortNames();
+        }
+
+        /*
+	    public override String SendRPC(String Name, String Method, params String[] Args)
+        {
+		    //write to serial port and receive result
+		    String Response;
+		    String Arguments = "";
+
+		    if(Args != null)
+            {
+			    for(int i = 0; i < Args.Length; i++)
+                {
+				    Arguments = Arguments + " " + Args[i];
+			    }
+		    }
+
+            serialPort.DiscardInBuffer();
+            String sendString = "/" + Name + "/" + Method + Arguments + "\r\n";
+            String reply = RawRpcCall(sendString);
+
+            return reply;
+	    }*/
+
+        /*
+	    public override void delete()
+        {
+		    //Close the serial port
+            if (serialPort != null) serialPort.Close();
+        }
+        */
+
+        private void serialPort_DataReceived(object sender, EventArgs e)
+        {
+            Debug.Print("Serial Port event");
+            //String Interrupt = serialPort.ReadLine();
+            String str = serialPortIo.ReadExisting();
+        }
+
+        private void serialPort_ErrorReceived(object sender, EventArgs e)
+        {
+            Debug.Print("Serial Port error");
+        }
+
+        public override string RawRpcCall(string request, bool reply)
+        {
+            if (rawRpcRequest != null) rawRpcRequest(request);
+            //String reply = myHID.RPC_Call(request);
+            serialPortIo.WriteLine(request);
+            if (reply == false) return "";
+
+            string replyStr;
+            replyStr = serialPortIo.ReadLine();
+            if (rawRpcReply != null) rawRpcReply(replyStr);
+            return replyStr;
+        }
+
+        public override void SendSingleByte(char ch)
+        {
+            char[] chArray = new char[1];
+            chArray[0] = ch;
+            serialPortIo.Write(chArray, 0, 1);
+        }
+        public override string ReadString()
+        {
+            return serialPortIo.ReadExisting();
+        }
+        public override int Read(char[] buffer, int offset, int count)
+        {
+            int val = 0;
+            try
+            {
+                val = serialPortIo.Read(buffer, offset, count);
+            }
+            catch (Exception)
+            {
+            }
+            return val;
+        }
+        public override void Discard()
+        {
+            serialPortIo.DiscardInBuffer();
+        }
+
+        public override string RawRpcCallBinary(string request, bool reply, out bool allOnes)
+        {
+            if (rawRpcRequest != null) rawRpcRequest(request);
+            //String reply = myHID.RPC_Call(request);
+            serialPortIo.WriteLine(request);
+            //if (reply == false) return "";
+
+            byte[] buffer = new byte[256];
+            int bytesToRead = 256;
+            while (bytesToRead != 0)
+            {
+                int bytesRead = serialPortIo.Read(buffer, 256 - bytesToRead, bytesToRead);
+                bytesToRead -= bytesRead;
+            }
+            allOnes = true;
+            for (int i = 0; i < 256; i++)
+            {
+                if (buffer[i] != 0xFF) allOnes = false;
+            }
+            string replyStr;
+            StringBuilder sb = new StringBuilder();
+            for (int i = 0; i < 256; i++)
+            {
+                sb.Append((buffer[i]).ToString("X2") + " ");
+            }
+            //replyStr = serialPort.ReadLine();
+            replyStr = sb.ToString().Trim();
+            String otherStr = serialPortIo.ReadLine();
+            if (rawRpcReply != null) rawRpcReply(replyStr);
+            return replyStr;
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HspGuiSourceV301/GuiDLLs/RPCSupport/Properties/AssemblyInfo.cs	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,36 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following 
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("RPCSupport")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("RPCSupport")]
+[assembly: AssemblyCopyright("Copyright ©  2015")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible 
+// to COM components.  If you need to access a type in this assembly from 
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("d813645f-12ae-498b-bdb7-52601ee69ba6")]
+
+// Version information for an assembly consists of the following four values:
+//
+//      Major Version
+//      Minor Version 
+//      Build Number
+//      Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers 
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HspGuiSourceV301/GuiDLLs/RPCSupport/RPCClient.cs	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,340 @@
+/*******************************************************************************
+* Copyright (C) 2016 Maxim Integrated Products, Inc., All rights Reserved.
+* 
+* This software is protected by copyright laws of the United States and
+* of foreign countries. This material may also be protected by patent laws
+* and technology transfer regulations of the United States and of foreign
+* countries. This software is furnished under a license agreement and/or a
+* nondisclosure agreement and may only be used or reproduced in accordance
+* with the terms of those agreements. Dissemination of this information to
+* any party or parties not specified in the license agreement and/or
+* nondisclosure agreement is expressly prohibited.
+*
+* The above copyright notice and this permission notice shall be included
+* in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+* OTHER DEALINGS IN THE SOFTWARE.
+*
+* Except as contained in this notice, the name of Maxim Integrated
+* Products, Inc. shall not be used except as stated in the Maxim Integrated
+* Products, Inc. Branding Policy.
+*
+* The mere transfer of this software does not imply any licenses
+* of trade secrets, proprietary technology, copyrights, patents,
+* trademarks, maskwork rights, or any other form of intellectual
+* property whatsoever. Maxim Integrated Products, Inc. retains all
+* ownership rights.
+*******************************************************************************
+*/
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using RPCSupport.Pipelines;
+using RPCSupport.Devices;
+using RPCSupport.Dialogs;
+
+namespace RPCSupport
+{
+    public class RPCClient
+    {
+        public enum ePipeline
+        {
+            eHid,
+            eSerial,
+            eHttp,
+            eSerialWrap
+        }
+        
+        //SerialPipeline serialPipeline;
+        const string SPINAME = "Spi";
+        I2cDevice i2cDevice;
+        SpiDevice spiDevice;
+        bool rpcLogShown = false;
+        public RPCSupport.Streaming.Streaming streaming;
+
+        public Pipeline pipeline;
+
+        public Pipeline Pipeline
+        {
+            get { return pipeline; }
+        }
+
+        LIS2HD lis2hd;
+        public LIS2HD LIS2HD
+        {
+            get { return lis2hd; }
+            set { lis2hd = value; }
+        }
+
+        public I2cDevice I2cDevice
+        {
+            get { return i2cDevice; }
+            set { i2cDevice = value; }
+        }
+        public SpiDevice SpiDevice
+        {
+            get { return spiDevice; }
+            set { spiDevice = value; }
+        }
+
+        MAX30101 max30101;
+        public MAX30101 MAX30101
+        {
+            get { return max30101; }
+            set { max30101 = value; }
+        }
+
+        MAX30001 max30001;
+        public MAX30001 MAX30001
+        {
+            get { return max30001; }
+            set { max30001 = value; }
+        }
+
+        MAX30205 max30205;
+        public MAX30205 MAX30205
+        {
+            get { return max30205; }
+            set { max30205 = value; }
+        }
+
+        DataLogging.DataLogging dataLogging;
+        public DataLogging.DataLogging DataLogging
+        {
+            get { return dataLogging; }
+            set { dataLogging = value; }
+        }
+
+        Devices.Led led;
+        public Devices.Led Led
+        {
+            get { return led; }
+            set { led = value; }
+        }
+
+        Devices.Testing testing;
+        public Devices.Testing Testing
+        {
+            get { return testing; }
+            set { testing = value; }
+        }
+
+        Devices.S25FS512 s25FS512;
+        public Devices.S25FS512 S25FS512
+        {
+            get { return s25FS512; }
+            set { s25FS512 = value; }
+        }
+
+        public RPCClient(ePipeline pipelineType)
+        {
+            switch (pipelineType)
+            {
+                case ePipeline.eHid:
+                    pipeline = new HidPipeline();
+                    break;
+                case ePipeline.eSerial:
+                    pipeline = new SerialPipeline();
+                    break;
+                case ePipeline.eHttp:
+                    break;
+                case ePipeline.eSerialWrap:
+                    pipeline = new SerialWrapPipeline();
+                    break;
+            }
+            ShowRpcLog(false);
+            LogCallback(new RPCSupport.Pipelines.Pipeline.RawRpcRequest(LogRpcRequest), new RPCSupport.Pipelines.Pipeline.RawRpcReply(LogRpcReply), new RPCSupport.Pipelines.Pipeline.RawRpcStream(LogRpcStream));
+            streaming = new Streaming.Streaming();
+        }
+
+        void LogRpcRequest(string request)
+        {
+            rpcLog.LogRpcRequest(request);
+        }
+
+        void LogRpcReply(string reply)
+        {
+            rpcLog.LogRpcReply(reply);
+        }
+
+        void LogRpcStream(string stream)
+        {
+            rpcLog.LogRpcStream(stream);
+        }
+
+        public void LogCallback(RPCSupport.Pipelines.Pipeline.RawRpcRequest request, RPCSupport.Pipelines.Pipeline.RawRpcReply reply, RPCSupport.Pipelines.Pipeline.RawRpcStream stream)
+        {
+            pipeline.LogCallback(request, reply, stream);
+        }
+
+        public void Connect(string param) {
+            pipeline.Connect(param);
+        }
+
+        public void Disconnect()
+        {
+            pipeline.Disconnect();
+        }
+
+        public string[] ScanAvailablePortNames() {
+            return pipeline.ScanAvailablePortNames();
+        }
+
+        public bool InitPipeline()
+        {
+            bool ret = pipeline.Init();
+            return ret;
+        }
+
+        public bool IsConnected()
+        {
+            return pipeline.IsConnected();
+        }
+
+        public String RawRpcCall(String request, bool reply)
+        {
+            return pipeline.RawRpcCall(request, reply);
+        }
+
+        public Devices.MAX30101 Init_MAX30101(int slaveAddress)
+        {
+            MAX30101 = new RPCSupport.Devices.MAX30101(this, slaveAddress);
+            return MAX30101;
+        }
+
+        public Devices.MAX30001 Init_MAX30001()
+        {
+            MAX30001 = new RPCSupport.Devices.MAX30001(this);
+            return MAX30001;
+        }
+
+        public Devices.MAX30205 Init_MAX30205(int slaveAddress)
+        {
+            MAX30205 = new RPCSupport.Devices.MAX30205(this, slaveAddress);
+            return MAX30205;
+        }
+
+        public Devices.LIS2HD Init_LIS2HD(int slaveAddress)
+        {
+            LIS2HD = new RPCSupport.Devices.LIS2HD(this, slaveAddress);
+            return LIS2HD;
+        }
+
+        public Devices.I2cDevice Init_I2cDevice()
+        {
+            I2cDevice = new RPCSupport.Devices.I2cDevice(this);
+            return I2cDevice;
+        }
+
+        public Devices.SpiDevice Init_SpiDevice()
+        {
+            SpiDevice = new RPCSupport.Devices.SpiDevice(this);
+            return SpiDevice;
+        }
+
+        public DataLogging.DataLogging Init_Logging()
+        {
+            dataLogging = new RPCSupport.DataLogging.DataLogging(this);
+            return dataLogging;
+        }
+
+        public RPCSupport.Devices.Led Init_Led()
+        {
+            led = new RPCSupport.Devices.Led(this);
+            return led;
+        }
+
+        public RPCSupport.Devices.Testing Init_Testing()
+        {
+            testing = new RPCSupport.Devices.Testing(this);
+            return testing;
+        }
+
+        public RPCSupport.Devices.S25FS512 Init_S25FS512()
+        {
+            s25FS512 = new RPCSupport.Devices.S25FS512(this);
+            return s25FS512;
+        }
+        
+
+        public void ReadRegister(DeviceSupport.DeviceDetails deviceDetails, DeviceSupport.RegisterInfo reg)
+        {
+            int hex;
+
+            switch (deviceDetails.type)
+            {
+                case DeviceSupport.DeviceDetails.eType.eI2c:
+                    i2cDevice.ReadReg(deviceDetails, reg);
+                    break;
+                case DeviceSupport.DeviceDetails.eType.eSpi:
+                    spiDevice.ReadReg(deviceDetails, reg);
+                    break;
+                case DeviceSupport.DeviceDetails.eType.eMAX30001:
+                    //reg.data[0] = max30001.ReadReg((byte)reg.address);
+                    hex = max30001.ReadReg((byte)reg.address);
+                    reg.data[0] = (hex >> 16) & 0xFF;
+                    reg.data[1] = (hex >> 8) & 0xFF;
+                    reg.data[2] = hex & 0xFF;
+                    break;
+                case DeviceSupport.DeviceDetails.eType.eMAX30205:
+                    //reg.data[0] = max30001.ReadReg((byte)reg.address);
+                    hex = max30205.ReadReg((byte)reg.address);
+                    reg.data[0] = (hex >> 8) & 0xFF;
+                    reg.data[1] = hex & 0xFF;
+                    break;
+            }
+        }
+
+        public void WriteRegister(DeviceSupport.DeviceDetails deviceDetails, DeviceSupport.RegisterInfo reg)
+        {
+            switch (deviceDetails.type)
+            {
+                case DeviceSupport.DeviceDetails.eType.eI2c:
+                    i2cDevice.WriteReg(deviceDetails, reg);
+                    break;
+                case DeviceSupport.DeviceDetails.eType.eSpi:
+                    spiDevice.WriteReg(deviceDetails, reg);
+                    break;
+                case DeviceSupport.DeviceDetails.eType.eMAX30001:
+                    //max30001.WriteReg((byte)reg.address, reg.data[0]);
+                    max30001.WriteReg((byte)reg.address, reg.data[2] | reg.data[1] << 8 | reg.data[0] << 16);
+                    break;
+                case DeviceSupport.DeviceDetails.eType.eMAX30205:
+                    max30001.WriteReg((byte)reg.address, reg.data[1] | reg.data[0] << 8);
+                    break;
+            }
+        }
+
+        RpcLog rpcLog;
+        public void ShowRpcLog(bool state)
+        {
+            if (rpcLog == null)
+            {
+                rpcLog = new RpcLog();
+            }
+            rpcLogShown = state;
+            if (state == true)
+                rpcLog.Show();
+            else
+                rpcLog.Hide();
+        }
+
+        public bool IsRpcLogShown()
+        {
+            return rpcLogShown;
+        }
+
+        public string Version()
+        {
+            return RawRpcCall("/System/ReadVer\r\n", true);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HspGuiSourceV301/GuiDLLs/RPCSupport/RPCSupport.csproj	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,105 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <PropertyGroup>
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+    <ProductVersion>8.0.30703</ProductVersion>
+    <SchemaVersion>2.0</SchemaVersion>
+    <ProjectGuid>{170A27F5-0680-485D-8B90-EA736719016E}</ProjectGuid>
+    <OutputType>Library</OutputType>
+    <AppDesignerFolder>Properties</AppDesignerFolder>
+    <RootNamespace>RPCSupport</RootNamespace>
+    <AssemblyName>RPCSupport</AssemblyName>
+    <TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
+    <FileAlignment>512</FileAlignment>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+    <DebugSymbols>true</DebugSymbols>
+    <DebugType>full</DebugType>
+    <Optimize>false</Optimize>
+    <OutputPath>bin\Debug\</OutputPath>
+    <DefineConstants>DEBUG;TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+    <DebugType>pdbonly</DebugType>
+    <Optimize>true</Optimize>
+    <OutputPath>bin\Release\</OutputPath>
+    <DefineConstants>TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+    <PlatformTarget>x86</PlatformTarget>
+  </PropertyGroup>
+  <ItemGroup>
+    <Reference Include="MaximStyle">
+      <HintPath>..\MaximStyle\MaximStyle.dll</HintPath>
+    </Reference>
+    <Reference Include="System" />
+    <Reference Include="System.Core" />
+    <Reference Include="System.Drawing" />
+    <Reference Include="System.Windows.Forms" />
+    <Reference Include="System.Xml.Linq" />
+    <Reference Include="System.Data.DataSetExtensions" />
+    <Reference Include="Microsoft.CSharp" />
+    <Reference Include="System.Data" />
+    <Reference Include="System.Xml" />
+  </ItemGroup>
+  <ItemGroup>
+    <Compile Include="DataLogging\DataLogging.cs" />
+    <Compile Include="DataLogging\StreamDataLog.cs" />
+    <Compile Include="DeviceSupport\RegisterBitDescriptions.cs" />
+    <Compile Include="Devices\ClientDevice.cs" />
+    <Compile Include="DeviceSupport\DeviceDetails.cs" />
+    <Compile Include="Devices\I2cDevice.cs" />
+    <Compile Include="DeviceSupport\RegisterInfo.cs" />
+    <Compile Include="Devices\IRegisterDevice.cs" />
+    <Compile Include="Devices\Led.cs" />
+    <Compile Include="Devices\MAX30001.cs" />
+    <Compile Include="Devices\S25FS512.cs" />
+    <Compile Include="Devices\SpiDevice.cs" />
+    <Compile Include="Devices\Testing.cs" />
+    <Compile Include="Dialogs\RpcLog.cs">
+      <SubType>Form</SubType>
+    </Compile>
+    <Compile Include="Dialogs\RpcLog.Designer.cs">
+      <DependentUpon>RpcLog.cs</DependentUpon>
+    </Compile>
+    <Compile Include="HidSupport\FileIODeclarations.cs" />
+    <Compile Include="HidSupport\HID.cs" />
+    <Compile Include="HidSupport\support.cs" />
+    <Compile Include="Pipelines\DataLogPipeline.cs" />
+    <Compile Include="Pipelines\HidPipeline.cs" />
+    <Compile Include="Pipelines\Pipeline.cs" />
+    <Compile Include="Pipelines\SerialWrapPipeline.cs" />
+    <Compile Include="RPCClient.cs" />
+    <Compile Include="Pipelines\SerialPipeline.cs" />
+    <Compile Include="Devices\LIS2HD.cs" />
+    <Compile Include="Devices\MAX30101\MAX30101.cs" />
+    <Compile Include="Devices\MAX30205.cs" />
+    <Compile Include="Properties\AssemblyInfo.cs" />
+    <Compile Include="Streaming\Crc32.cs" />
+    <Compile Include="Streaming\PartialArrayIntAvailableEventArgs.cs" />
+    <Compile Include="Streaming\Streaming.cs" />
+    <Compile Include="Streaming\StreamingParameters.cs" />
+  </ItemGroup>
+  <ItemGroup>
+    <EmbeddedResource Include="Dialogs\RpcLog.resx">
+      <DependentUpon>RpcLog.cs</DependentUpon>
+    </EmbeddedResource>
+  </ItemGroup>
+  <ItemGroup>
+    <ProjectReference Include="..\SerialWrap\SerialWrap.csproj">
+      <Project>{28A72C36-6880-4A8E-800A-86959B22A8AC}</Project>
+      <Name>SerialWrap</Name>
+    </ProjectReference>
+  </ItemGroup>
+  <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+  <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 
+       Other similar extension points exist, see Microsoft.Common.targets.
+  <Target Name="BeforeBuild">
+  </Target>
+  <Target Name="AfterBuild">
+  </Target>
+  -->
+</Project>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HspGuiSourceV301/GuiDLLs/RPCSupport/Streaming/Crc32.cs	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,94 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace RPCSupport.Streaming
+{
+    public class Crc32
+    {
+        static UInt32[] crc32_tab = new UInt32[] {
+	        0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f,
+	        0xe963a535, 0x9e6495a3,	0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
+	        0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2,
+	        0xf3b97148, 0x84be41de,	0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
+	        0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec,	0x14015c4f, 0x63066cd9,
+	        0xfa0f3d63, 0x8d080df5,	0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
+	        0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,	0x35b5a8fa, 0x42b2986c,
+	        0xdbbbc9d6, 0xacbcf940,	0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
+	        0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423,
+	        0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
+	        0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d,	0x76dc4190, 0x01db7106,
+	        0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
+	        0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d,
+	        0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
+	        0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
+	        0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
+	        0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7,
+	        0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
+	        0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa,
+	        0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
+	        0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81,
+	        0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
+	        0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84,
+	        0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
+	        0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
+	        0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
+	        0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e,
+	        0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
+	        0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55,
+	        0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
+	        0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28,
+	        0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
+	        0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f,
+	        0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
+	        0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
+	        0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
+	        0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69,
+	        0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
+	        0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc,
+	        0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
+	        0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693,
+	        0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
+	        0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
+        };
+
+        /**************************************************************************************************************/
+        //
+        //  uint32_t crc32(uint32_t crc, const void *buf, uint32_t size)
+        //
+        //  _____
+        //
+        //  INPUT:  
+        //		_____:
+        //		_____:
+        //		_____:
+        //		_____:
+        //
+        //  OUTPUT: 
+        //		_____:
+        //
+        //  Function return: 0 if successful, -1 if error
+        //
+        /**************************************************************************************************************/
+        static public UInt32 crc32(UInt32 crc, int[] buf, UInt32 size)
+        {
+	        crc = crc ^ ~0U;
+
+	        for (int i = 0; i < size; i++)
+                crc = crc32_tab[(crc ^ (UInt32)buf[i]) & 0xFF] ^ (crc >> 8);
+
+	        return crc ^ ~0U;
+        }
+
+        static public UInt32 crc32Value(UInt32 crc, UInt32 value)
+        {
+	        crc = crc ^ ~0U;
+	        crc = crc32_tab[(crc ^ value) & 0xFF] ^ (crc >> 8);
+	        return crc ^ ~0U;
+        }
+
+
+
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HspGuiSourceV301/GuiDLLs/RPCSupport/Streaming/PartialArrayIntAvailableEventArgs.cs	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,95 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace RPCSupport.Streaming
+{
+    public class PartialArrayIntAvailableEventArgs : EventArgs
+    {
+/*        const int PACKET_MAX30101 = 0x10;
+        const int PACKET_LIS2DH = 0x20;
+        const int PACKET_MAX30001_ECG = 0x30;
+        const int PACKET_MAX30001_PACE = 0x31;
+        const int PACKET_MAX30001_RTOR = 0x32;
+        const int PACKET_MAX30001_BIOZ = 0x33;
+        const int PACKET_MAX30001_LEADOFF_DC = 0x34;
+        //#define PACKET_MAX30001_LEADOFF_DC_BIOZ 	0x36
+        const int PACKET_MAX30001_LEADOFF_AC = 0x35;
+        const int PACKET_MAX30001_BCGMON = 0x36;
+        const int PACKET_MAX31725_TEMP1 = 0x40;
+        const int PACKET_MAX31725_TEMP2 = 0x50;
+        const int PACKET_BMP280_PRESSURE = 0x60;
+        const int PACKET_LSM6DS3_ACCEL = 0x70;
+        const int PACKET_MAX30205_TEMP = 0x80;
+
+        */
+        public const int PACKET_MAX30101   =           0x10;
+
+        public const int PACKET_LIS2DH = 0x20;
+
+        public const int PACKET_MAX30001_ECG = 0x30;
+        public const int PACKET_MAX30001_PACE = 0x31;
+        public const int PACKET_MAX30001_RTOR = 0x32;
+        public const int PACKET_MAX30001_BIOZ = 0x33;
+        public const int PACKET_MAX30001_LEADOFF_DC = 0x34;
+//#define PACKET_MAX30001_LEADOFF_DC_BIOZ   0x36
+        public const int PACKET_MAX30001_LEADOFF_AC = 0x35;
+        public const int PACKET_MAX30001_BCGMON = 0x36;
+
+        public const int PACKET_MAX31725_TEMP1 = 0x40;
+        public const int PACKET_MAX31725_TEMP2 = 0x50;
+        public const int PACKET_BMP280_PRESSURE = 0x60;
+        public const int PACKET_LSM6DS3_ACCEL = 0x70;
+
+        public const int PACKET_DATALOGGING_PARAMETERS = 0xF0;
+        public const int PACKET_DATALOGGING_RESUME_TABLE = 0xF1;
+        public const int PACKET_END_OF_STREAM = 0xF2;
+
+        /// <summary>
+        /// Sequential index of the first sample.
+        /// </summary>
+        public int reportID { get; set; }
+        public int sampleNumberOffset { get; set; }
+
+        public int timestamp { get; set; }
+        public int[] array1 { get; set; }
+        public int[] array2 { get; set; }
+        public int[] array3 { get; set; }
+
+        public static bool ValidatePacketID(int id)
+        {
+            bool valid = false;
+
+            uint idMasked = (uint)(id & 0xFF);
+            uint magicValue55 = (uint)(id & 0xFF000000) >> 24;
+            uint magicValueAA = (uint)(id & 0xFF0000) >> 16;
+            uint incomingChecksum = (uint)(id & 0xFF00) >> 8;
+            uint sum;
+            sum = 0x55;
+            sum += 0xAA;
+            sum += idMasked;
+            sum &= 0xFF;
+            if (sum == incomingChecksum && magicValue55 == 0x55 && magicValueAA == 0xAA) valid = true;
+
+/*            switch (id)
+            {
+                case PartialArrayIntAvailableEventArgs.PACKET_MAX30101: valid = true; break;
+                case PartialArrayIntAvailableEventArgs.PACKET_LIS2DH: valid = true; break;
+                case PartialArrayIntAvailableEventArgs.PACKET_MAX30001_ECG: valid = true; break;
+                case PartialArrayIntAvailableEventArgs.PACKET_MAX30001_PACE: valid = true; break;
+                case PartialArrayIntAvailableEventArgs.PACKET_MAX30001_RTOR: valid = true; break;
+                case PartialArrayIntAvailableEventArgs.PACKET_MAX30001_BIOZ: valid = true; break;
+                case PartialArrayIntAvailableEventArgs.PACKET_MAX30001_LEADOFF_DC: valid = true; break;
+                case PartialArrayIntAvailableEventArgs.PACKET_MAX30001_LEADOFF_AC: valid = true; break;
+                case PartialArrayIntAvailableEventArgs.PACKET_MAX30001_BCGMON: valid = true; break;
+                case PartialArrayIntAvailableEventArgs.PACKET_MAX31725_TEMP1: valid = true; break;
+                case PartialArrayIntAvailableEventArgs.PACKET_MAX31725_TEMP2: valid = true; break;
+                case PartialArrayIntAvailableEventArgs.PACKET_BMP280_PRESSURE: valid = true; break;
+                case PartialArrayIntAvailableEventArgs.PACKET_LSM6DS3_ACCEL: valid = true; break;
+            }*/
+            return valid;
+        }
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HspGuiSourceV301/GuiDLLs/RPCSupport/Streaming/Streaming.cs	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,391 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.ComponentModel;
+using System.Collections;
+using System.Globalization;
+using System.Threading;
+
+namespace RPCSupport.Streaming
+{
+    public class Streaming
+    {
+        BackgroundWorker _testWorker;
+        Pipelines.Pipeline pipeline;
+
+        public int Timestamp;
+        public int NumberPacketCrcErrors;
+        public int NumberPacketHeaderErrors;
+        public ArrayList ArrayListRed = new ArrayList();
+        public ArrayList ArrayListIR = new ArrayList();
+        public ArrayList ArrayListGreen = new ArrayList();
+        public event EventHandler<PartialArrayIntAvailableEventArgs> PartialArrayIntAvailable;
+        private bool handlersInited = false;
+
+        public void Init(Pipelines.Pipeline pipeline)
+        {
+            this.pipeline = pipeline;
+
+            if (handlersInited == false)
+            {
+                handlersInited = true;
+                _testWorker = new BackgroundWorker();
+                _testWorker.WorkerSupportsCancellation = true;
+                _testWorker.ProgressChanged += new ProgressChangedEventHandler(_testWorker_ProgressChanged);
+                _testWorker.DoWork += new DoWorkEventHandler(_testWorker_DoWork);
+                _testWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(_testWorker_RunWorkerCompleted);
+                _testWorker.WorkerReportsProgress = true;
+            }
+        }
+
+        protected virtual void OnPartialArrayIntAvailable(PartialArrayIntAvailableEventArgs e)
+        {
+            EventHandler<PartialArrayIntAvailableEventArgs> handler = PartialArrayIntAvailable;
+            if (handler != null)
+            {
+                handler(this, e);
+            }
+        }
+
+        public void Start()
+        {
+            ArrayListRed.Clear();
+            ArrayListIR.Clear();
+            ArrayListGreen.Clear();
+            _testWorker.RunWorkerAsync();
+        }
+        public void Stop()
+        {
+            _testWorker.CancelAsync();
+        }
+        void _testWorker_ProgressChanged(object sender, ProgressChangedEventArgs e)
+        {
+            var data = (System.Tuple<int, int, int[], int[], int[]>)(e.UserState);
+            int reportID = data.Item1;
+            int timestamp = data.Item2;
+            int[] list1_Red___or_X = data.Item3;
+            int[] list2_IR____or_Y = data.Item4;
+            int[] list3_Green_or_Z = data.Item5;
+
+            if (list1_Red___or_X != null) 
+                for (int index = 0; index < list1_Red___or_X.Length; index++)
+                {
+                    ArrayListRed.Add(list1_Red___or_X[index]);
+                }
+            if (list2_IR____or_Y != null)
+                for (int index = 0; index < list2_IR____or_Y.Length; index++)
+                {
+                    ArrayListIR.Add(list2_IR____or_Y[index]);
+                }
+            if (list3_Green_or_Z != null)
+                for (int index = 0; index < list3_Green_or_Z.Length; index++)
+                {
+                   ArrayListGreen.Add(list3_Green_or_Z[index]);
+                }
+            OnPartialArrayIntAvailable(new PartialArrayIntAvailableEventArgs()
+            {
+                reportID = reportID,
+                timestamp = timestamp,
+                array1 = (int[])ArrayListRed.ToArray(typeof(int)),
+                array2 = (int[])ArrayListIR.ToArray(typeof(int)),
+                array3 = (int[])ArrayListGreen.ToArray(typeof(int))
+            });
+            ArrayListRed.Clear();
+            ArrayListIR.Clear();
+            ArrayListGreen.Clear();
+        }
+        const int STREAM_PACKET_HRMULTI = 0x03;
+        enum ePacketPhase
+        {
+            eId,
+            eTimestamp,
+            eLength,
+            eData
+        }
+        ePacketPhase packetPhase;
+        enum ePacketBuildStage
+        {
+            eAssemble,
+            eProcess,
+            eResync
+        }
+        ePacketBuildStage packetBuildStage;
+        StringBuilder packetStringBuild;
+        int packetDataIndex;
+
+        class Packet
+        {
+            public int id;
+            public int rawId;
+            public int timestamp;
+            public int length;
+            public int crc;
+            public int[] data;
+
+            internal string ToLogString()
+            {
+                StringBuilder sb = new StringBuilder();
+                sb.Append(id.ToString("X2") + " ");
+                sb.Append(timestamp.ToString("X2") + " ");
+                sb.Append(length.ToString("X2") + " ");
+                for (int i = 0; i < length; i++)
+                {
+                    sb.Append(data[i].ToString("X2") + " ");
+                }
+                return sb.ToString();
+            }
+        }
+
+        Queue packetFifo = new Queue(256);
+        Packet currentPacket;
+        private void ProcessIncomingStream(Queue incomingFifo, Queue packetFifo)
+        {
+            while (incomingFifo.Count != 0)
+            {
+                if (packetBuildStage == ePacketBuildStage.eAssemble)
+                {
+                    char ch = (char)incomingFifo.Dequeue();
+                    if (ch != ' ')
+                    {
+                        packetStringBuild.Append(ch);
+                    }
+                    else
+                    {
+                        //pipeline.LogStream(packetStringBuild.ToString());
+                        packetBuildStage = ePacketBuildStage.eProcess;
+                    }
+                }
+                if (packetBuildStage == ePacketBuildStage.eResync)
+                {
+                    char ch = (char)incomingFifo.Dequeue();
+                    if (ch != ' ')
+                    {
+                        packetStringBuild.Append(ch);
+                    }
+                    else
+                    {
+                        //pipeline.LogStream(packetStringBuild.ToString());
+                        int val;
+                        int.TryParse(packetStringBuild.ToString(), NumberStyles.HexNumber, CultureInfo.CurrentCulture, out val);
+                        if (PartialArrayIntAvailableEventArgs.ValidatePacketID(val) == true)
+                        {
+                            packetBuildStage = ePacketBuildStage.eProcess;
+                            packetPhase = ePacketPhase.eId;
+                        }
+                        else
+                        {
+                            packetStringBuild.Clear();
+                        }
+                    }
+                }
+                    
+                if (packetBuildStage == ePacketBuildStage.eProcess)
+                {
+                    int val;
+                    int.TryParse(packetStringBuild.ToString(), NumberStyles.HexNumber, CultureInfo.CurrentCulture, out val);
+                    switch (packetPhase)
+                    {
+                        case ePacketPhase.eId:
+                            currentPacket = new Packet();
+                            currentPacket.id = val & 0xFF;
+                            currentPacket.rawId = val;
+                            if (PartialArrayIntAvailableEventArgs.ValidatePacketID(val) == false)
+                            {
+                                packetBuildStage = ePacketBuildStage.eResync;
+                                packetPhase = ePacketPhase.eId;
+                                packetStringBuild.Clear();
+                                NumberPacketHeaderErrors++;
+                                break;
+                            }
+                            packetPhase = ePacketPhase.eTimestamp;
+                            //pipeline.LogStream("Packet ID = " + packetStringBuild.ToString());
+                            break;
+                        case ePacketPhase.eTimestamp:
+                            currentPacket.timestamp = val;
+                            //if (val != 0x11223344)
+                            //{
+                            //    throw new Exception("timestamp invalid");
+                            //}
+                            packetPhase = ePacketPhase.eLength;
+                            break;
+                        case ePacketPhase.eLength:
+                            currentPacket.length = val & 0xFFFF;
+                            currentPacket.crc = (val >> 16) & 0xFFFF;
+                            packetDataIndex = 0;
+                            currentPacket.data = new int[currentPacket.length];
+                            packetPhase = ePacketPhase.eData;
+                            break;
+                        case ePacketPhase.eData:
+                            currentPacket.data[packetDataIndex++] = val;
+                            if (packetDataIndex >= currentPacket.length)
+                            {
+                                // validate the packet before enqueing
+                                UInt32 crc = 0;
+                                crc = 0;
+                                crc = Crc32.crc32Value(crc, (UInt32)currentPacket.rawId);
+                                crc = Crc32.crc32Value(crc, (UInt32)currentPacket.timestamp);
+                                crc = Crc32.crc32Value(crc, (UInt32)currentPacket.length);
+                                crc = Crc32.crc32(crc, currentPacket.data, (UInt32)currentPacket.length);
+                                // if crc checks out then put in queue
+                                if ((crc & 0xFFFF) == currentPacket.crc || (currentPacket.crc == 0))
+                                {
+                                    packetFifo.Enqueue(currentPacket);
+                                }
+                                else
+                                {
+                                    NumberPacketCrcErrors++;
+                                    packetFifo.Enqueue(currentPacket);
+                                }
+                                pipeline.LogStream(currentPacket.ToLogString());
+                                packetPhase = ePacketPhase.eId;
+                            }
+                            break;
+                    }
+                    packetStringBuild.Clear();
+                    if (packetBuildStage != ePacketBuildStage.eResync) 
+                        packetBuildStage = ePacketBuildStage.eAssemble;
+                }
+            }
+        }
+
+        bool debugFlag = false;
+        public bool DebugFlag()
+        {
+            return debugFlag;
+        }
+
+        int packetCount;
+        Queue incomingFifo = new Queue(256);
+        private void _testWorker_DoWork(object sender, DoWorkEventArgs e)
+        {
+            incomingFifo.Clear();
+            packetFifo.Clear();
+            packetStringBuild = new StringBuilder();
+            packetPhase = ePacketPhase.eId;
+            packetBuildStage = ePacketBuildStage.eAssemble;
+            //Thread.Sleep(500);
+            //pipeline.Discard();
+            packetCount = 0;
+            char[] serialData = new char[128];
+            NumberPacketCrcErrors = 0;
+            NumberPacketHeaderErrors = 0;
+            while (true)
+            {
+                if (_testWorker.CancellationPending)
+                {
+                    return; // end thread
+                }
+                // read from pipe
+                //Thread.Sleep(1000);
+
+                // if this pipe is not connected then shutdown the thread
+                if (pipeline.IsConnected() == false)
+                {
+                    return;
+                }
+                int charsRead = pipeline.Read(serialData, 0, serialData.Length);
+                // get out if there are no longer bytes to be read
+                if (charsRead == 0)
+                {
+                    _testWorker.ReportProgress(0, new System.Tuple<int, int, int[], int[], int[]>(PartialArrayIntAvailableEventArgs.PACKET_END_OF_STREAM, 0, null, null, null));
+                    break;
+                }
+                for (int i = 0; i < charsRead; i++)
+                {
+                    incomingFifo.Enqueue(serialData[i]);
+                }
+                debugFlag = true;
+                ProcessIncomingStream(incomingFifo, packetFifo);
+                if (packetFifo.Count != 0)
+                {
+                    packetCount++;
+                    for (int i = 0; i < packetFifo.Count; i++)
+                    {
+                        ArrayList arrayList1 = new ArrayList();
+                        ArrayList arrayList2 = new ArrayList();
+                        ArrayList arrayList3 = new ArrayList();
+                        Packet packet = (Packet)packetFifo.Dequeue();
+                        if ((packet.id & 0xF0) == 0x10)     // check for MAX30101 data
+                        {
+                            int index = 0;
+                            int ledNumber = packet.id & 0x0F;
+                            if (ledNumber == 1)
+                            {
+                                while (index < packet.length)
+                                {
+                                    arrayList1.Add(packet.data[index++]);
+                                }
+                            }
+                            if (ledNumber == 2)
+                            {
+                                while (index < packet.length)
+                                {
+                                    arrayList1.Add(packet.data[index++]);
+                                    arrayList2.Add(packet.data[index++]);
+                                }
+                            }
+                            if (ledNumber == 3)
+                            {
+                                while (index < packet.length)
+                                {
+                                    arrayList1.Add(packet.data[index++]);
+                                    arrayList2.Add(packet.data[index++]);
+                                    arrayList3.Add(packet.data[index++]);
+                                }
+                            }
+                            int[] array1 = (int[])arrayList1.ToArray(typeof(int));
+                            int[] array2 = (int[])arrayList2.ToArray(typeof(int));
+                            int[] array3 = (int[])arrayList3.ToArray(typeof(int));
+                            _testWorker.ReportProgress(0, new System.Tuple<int, int, int[], int[], int[]>(packet.id, packet.timestamp, array1, array2, array3));
+                        } else
+                        if ((packet.id & 0xF0) == 0x20)     // check for LIS2DH data
+                        {
+                            int index = 0;
+                            while (index < packet.length)
+                            {
+                                arrayList1.Add(packet.data[index++]);
+                                arrayList2.Add(packet.data[index++]);
+                                arrayList3.Add(packet.data[index++]);
+                            }
+                            int[] array1 = (int[])arrayList1.ToArray(typeof(int));
+                            int[] array2 = (int[])arrayList2.ToArray(typeof(int));
+                            int[] array3 = (int[])arrayList3.ToArray(typeof(int));
+                            _testWorker.ReportProgress(0, new System.Tuple<int, int, int[], int[], int[]>(packet.id, packet.timestamp, array1, array2, array3));
+                        }
+                        if ((packet.id & 0xF0) == 0x30)     // check for MAX30001 data
+                        {
+                            int index = 0;
+                            while (index < packet.length)
+                            {
+                                arrayList1.Add(packet.data[index++]);
+                            }
+                            int[] array1 = (int[])arrayList1.ToArray(typeof(int));
+                            int[] array2 = (int[])arrayList2.ToArray(typeof(int));
+                            int[] array3 = (int[])arrayList3.ToArray(typeof(int));
+                            _testWorker.ReportProgress(0, new System.Tuple<int, int, int[], int[], int[]>(packet.id, packet.timestamp, array1, array2, array3));
+                        }
+                        if ((packet.id & 0xF0) == PartialArrayIntAvailableEventArgs.PACKET_BMP280_PRESSURE ||   // check for BMP280 data
+                            (packet.id & 0xF0) == PartialArrayIntAvailableEventArgs.PACKET_MAX31725_TEMP1 ||    // check for BMP280 data
+                            (packet.id & 0xF0) == PartialArrayIntAvailableEventArgs.PACKET_MAX31725_TEMP2       // check for BMP280 data
+                            )     // check for BMP280 data
+                        {
+                            int index = 0;
+                            while (index < packet.length)
+                            {
+                                arrayList1.Add(packet.data[index++]);
+                            }
+                            int[] array1 = (int[])arrayList1.ToArray(typeof(int));
+                            int[] array2 = (int[])arrayList2.ToArray(typeof(int));
+                            int[] array3 = (int[])arrayList3.ToArray(typeof(int));
+                            _testWorker.ReportProgress(0, new System.Tuple<int, int, int[], int[], int[]>(packet.id, packet.timestamp, array1, array2, array3));
+                        }
+                    }
+                }
+            }
+        }
+        void _testWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
+        {
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HspGuiSourceV301/GuiDLLs/RPCSupport/Streaming/StreamingParameters.cs	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,61 @@
+/*******************************************************************************
+* Copyright (C) 2016 Maxim Integrated Products, Inc., All rights Reserved.
+* 
+* This software is protected by copyright laws of the United States and
+* of foreign countries. This material may also be protected by patent laws
+* and technology transfer regulations of the United States and of foreign
+* countries. This software is furnished under a license agreement and/or a
+* nondisclosure agreement and may only be used or reproduced in accordance
+* with the terms of those agreements. Dissemination of this information to
+* any party or parties not specified in the license agreement and/or
+* nondisclosure agreement is expressly prohibited.
+*
+* The above copyright notice and this permission notice shall be included
+* in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+* OTHER DEALINGS IN THE SOFTWARE.
+*
+* Except as contained in this notice, the name of Maxim Integrated
+* Products, Inc. shall not be used except as stated in the Maxim Integrated
+* Products, Inc. Branding Policy.
+*
+* The mere transfer of this software does not imply any licenses
+* of trade secrets, proprietary technology, copyrights, patents,
+* trademarks, maskwork rights, or any other form of intellectual
+* property whatsoever. Maxim Integrated Products, Inc. retains all
+* ownership rights.
+*******************************************************************************
+*/
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace RPCSupport.Streaming
+{
+    class StreamingParameters
+    {
+        // MAX30101 Parameters
+        public int SampleRate {get; set;}
+        public int SampleAverage {get; set;}
+        public int PulseWidth { get; set; }
+        public int AdcFullScaleRange { get; set; }
+        public int RedCurrent { get; set; }
+        public int IrCurrent { get; set; }
+        public int Greencurrent { get; set; }
+        public int PilotPa { get; set; }
+        public int ProxIntThresh { get; set; }
+        public int LedSlot1 { get; set; }
+        public int LedSlot2 { get; set; }
+        public int LedSlot3 { get; set; }
+        public int LedSlot4 { get; set; }
+        //
+    }
+}
Binary file HspGuiSourceV301/GuiDLLs/SKA/SKA.dll has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HspGuiSourceV301/GuiDLLs/SerialWrap/App.config	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<configuration>
+    <startup> 
+        <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0"/>
+    </startup>
+</configuration>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HspGuiSourceV301/GuiDLLs/SerialWrap/SerialPortTester.cs	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,230 @@
+// Copyright 2010-2014 Zach Saw
+// 
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+// 
+//     http://www.apache.org/licenses/LICENSE-2.0
+// 
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+using System;
+using System.IO;
+using System.IO.Ports;
+using System.Runtime.InteropServices;
+using System.Text;
+using Microsoft.Win32.SafeHandles;
+
+namespace SerialPortTester
+{
+    public class SerialPortFixer : IDisposable
+    {
+        public static void Execute(string portName)
+        {
+            using (new SerialPortFixer(portName))
+            {
+            }
+        }
+        #region IDisposable Members
+
+        public void Dispose()
+        {
+            if (m_Handle != null)
+            {
+                m_Handle.Close();
+                m_Handle = null;
+            }
+        }
+
+        #endregion
+
+        #region Implementation
+
+        private const int DcbFlagAbortOnError = 14;
+        private const int CommStateRetries = 10;
+        private SafeFileHandle m_Handle;
+
+        private SerialPortFixer(string portName)
+        {
+            const int dwFlagsAndAttributes = 0x40000000;
+            const int dwAccess = unchecked((int) 0xC0000000); 
+ 
+            if ((portName == null) || !portName.StartsWith("COM", StringComparison.OrdinalIgnoreCase))
+            {
+                throw new ArgumentException("Invalid Serial Port", "portName");
+            }
+            SafeFileHandle hFile = CreateFile(@"\\.\" + portName, dwAccess, 0, IntPtr.Zero, 3, dwFlagsAndAttributes,
+                                              IntPtr.Zero);
+            if (hFile.IsInvalid)
+            {
+                WinIoError();
+            }
+            try
+            {
+                int fileType = GetFileType(hFile);
+                if ((fileType != 2) && (fileType != 0))
+                {
+                     throw new ArgumentException("Invalid Serial Port", "portName");
+                }
+                m_Handle = hFile;
+                InitializeDcb();
+            }
+            catch
+            {
+                hFile.Close();
+                m_Handle = null;
+                throw;
+            }
+        }
+
+        [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
+        private static extern int FormatMessage(int dwFlags, HandleRef lpSource, int dwMessageId, int dwLanguageId,
+                                                StringBuilder lpBuffer, int nSize, IntPtr arguments);
+
+        [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
+        private static extern bool GetCommState(SafeFileHandle hFile, ref Dcb lpDcb);
+
+        [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
+        private static extern bool SetCommState(SafeFileHandle hFile, ref Dcb lpDcb);
+
+        [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
+        private static extern bool ClearCommError(SafeFileHandle hFile, ref int lpErrors, ref Comstat lpStat);
+
+        [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
+        private static extern SafeFileHandle CreateFile(string lpFileName, int dwDesiredAccess, int dwShareMode,
+                                                        IntPtr securityAttrs, int dwCreationDisposition,
+                                                        int dwFlagsAndAttributes, IntPtr hTemplateFile);
+
+        [DllImport("kernel32.dll", SetLastError = true)]
+        private static extern int GetFileType(SafeFileHandle hFile);
+
+        private void InitializeDcb()
+        {
+            Dcb dcb = new Dcb();
+            GetCommStateNative(ref dcb);
+            dcb.Flags &= ~(1u << DcbFlagAbortOnError);
+            SetCommStateNative(ref dcb);
+        }
+
+        private static string GetMessage(int errorCode)
+        {
+            StringBuilder lpBuffer = new StringBuilder(0x200);
+            if (
+                FormatMessage(0x3200, new HandleRef(null, IntPtr.Zero), errorCode, 0, lpBuffer, lpBuffer.Capacity,
+                              IntPtr.Zero) != 0)
+            {
+                return lpBuffer.ToString();
+            }
+            return "Unknown Error";
+        }
+
+        private static int MakeHrFromErrorCode(int errorCode)
+        {
+            return (int) (0x80070000 | (uint) errorCode);
+        }
+
+        private static void WinIoError()
+        {
+            int errorCode = Marshal.GetLastWin32Error();
+            throw new IOException(GetMessage(errorCode), MakeHrFromErrorCode(errorCode));
+        }
+
+        private void GetCommStateNative(ref Dcb lpDcb)
+        {
+            int commErrors = 0;
+            Comstat comStat = new Comstat();
+
+            for (int i = 0; i < CommStateRetries; i++)
+            {
+                if (!ClearCommError(m_Handle, ref commErrors, ref comStat))
+                {
+                     WinIoError();
+                }
+                if (GetCommState(m_Handle, ref lpDcb))
+                {
+                     break;
+                }
+                if (i == CommStateRetries - 1)
+                {
+                     WinIoError();
+                }
+            }
+        } 
+ 
+        private void SetCommStateNative(ref Dcb lpDcb)
+        {
+            int commErrors = 0;
+            Comstat comStat = new Comstat(); 
+ 
+            for (int i = 0; i < CommStateRetries; i++)
+            {
+                 if (!ClearCommError(m_Handle, ref commErrors, ref comStat))
+                 {
+                     WinIoError();
+                 }
+                 if (SetCommState(m_Handle, ref lpDcb))
+                 {
+                     break;
+                 }
+                 if (i == CommStateRetries - 1)
+                 {
+                     WinIoError();
+                 }
+            }
+        }
+
+        #region Nested type: COMSTAT
+
+        [StructLayout(LayoutKind.Sequential)]
+        private struct Comstat
+        {
+            public readonly uint Flags;
+            public readonly uint cbInQue;
+            public readonly uint cbOutQue;
+        }
+
+        #endregion
+
+        #region Nested type: DCB
+
+        [StructLayout(LayoutKind.Sequential)]
+        private struct Dcb
+        {
+            public readonly uint DCBlength;
+            public readonly uint BaudRate;
+            public uint Flags;
+            public readonly ushort wReserved;
+            public readonly ushort XonLim;
+            public readonly ushort XoffLim;
+            public readonly byte ByteSize;
+            public readonly byte Parity;
+            public readonly byte StopBits;
+            public readonly byte XonChar;
+            public readonly byte XoffChar;
+            public readonly byte ErrorChar;
+            public readonly byte EofChar;
+            public readonly byte EvtChar;
+            public readonly ushort wReserved1;
+        }
+
+        #endregion
+
+        #endregion
+    }
+
+    internal class Program
+    {
+        private static void Main(string[] args)
+        {
+            SerialPortFixer.Execute("COM1");
+            using (SerialPort port = new SerialPort("COM1"))
+            {
+                port.Write("test");
+            }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HspGuiSourceV301/GuiDLLs/SerialWrap/SerialWrap.csproj	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,61 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
+  <PropertyGroup>
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+    <ProjectGuid>{28A72C36-6880-4A8E-800A-86959B22A8AC}</ProjectGuid>
+    <OutputType>Exe</OutputType>
+    <AppDesignerFolder>Properties</AppDesignerFolder>
+    <RootNamespace>SerialWrap</RootNamespace>
+    <AssemblyName>SerialWrap</AssemblyName>
+    <TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
+    <FileAlignment>512</FileAlignment>
+    <TargetFrameworkProfile />
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+    <PlatformTarget>AnyCPU</PlatformTarget>
+    <DebugSymbols>true</DebugSymbols>
+    <DebugType>full</DebugType>
+    <Optimize>false</Optimize>
+    <OutputPath>bin\Debug\</OutputPath>
+    <DefineConstants>DEBUG;TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+    <PlatformTarget>x86</PlatformTarget>
+    <DebugType>pdbonly</DebugType>
+    <Optimize>true</Optimize>
+    <OutputPath>bin\Release\</OutputPath>
+    <DefineConstants>TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+  </PropertyGroup>
+  <ItemGroup>
+    <None Include="App.config_" />
+    <None Include="packages.config_" />
+  </ItemGroup>
+  <ItemGroup>
+    <Compile Include="serialportio.cs" />
+    <Compile Include="SerialPortTester.cs" />
+  </ItemGroup>
+  <ItemGroup>
+    <Reference Include="Common.Logging">
+      <HintPath>..\Common.Logging\Common.Logging.dll</HintPath>
+    </Reference>
+    <Reference Include="Common.Logging.Core">
+      <HintPath>..\Common.Logging\Common.Logging.Core.dll</HintPath>
+    </Reference>
+    <Reference Include="System" />
+    <Reference Include="System.Xml" />
+  </ItemGroup>
+  <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+  <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 
+       Other similar extension points exist, see Microsoft.Common.targets.
+  <Target Name="BeforeBuild">
+  </Target>
+  <Target Name="AfterBuild">
+  </Target>
+  -->
+</Project>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HspGuiSourceV301/GuiDLLs/SerialWrap/packages.config	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<packages>
+  <package id="Common.Logging" version="3.3.1" targetFramework="net45" />
+  <package id="Common.Logging.Core" version="3.3.1" targetFramework="net45" />
+</packages>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HspGuiSourceV301/GuiDLLs/SerialWrap/serialportio.cs	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,372 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Threading;
+using System.Reflection;
+using System.IO;
+
+using System.IO.Ports;
+using SerialPortTester;
+
+using Common.Logging;
+
+namespace SerialWrap
+{
+    public interface ISerialPortIo : IDisposable
+    {
+        string PortName { get; }
+        string ReadLine();
+        void WriteLine(string text);
+    }
+
+    public class SerialPortConfig
+    {
+        public string Name { get; private set; }
+        public int BaudRate { get; private set; }
+        public int DataBits { get; private set; }
+        public StopBits StopBits { get; private set; }
+        public Parity Parity { get; private set; }
+        public bool DtrEnable { get; private set; }
+        public bool RtsEnable { get; private set; }
+
+        public SerialPortConfig(
+            string name,
+            int baudRate,
+            int dataBits,
+            StopBits stopBits,
+            Parity parity,
+            bool dtrEnable,
+            bool rtsEnable)
+        {
+            if (String.IsNullOrWhiteSpace(name)) throw new ArgumentNullException("name");
+
+            this.RtsEnable = rtsEnable;
+            this.BaudRate = baudRate;
+            this.DataBits = dataBits;
+            this.StopBits = stopBits;
+            this.Parity = parity;
+            this.DtrEnable = dtrEnable;
+            this.Name = name;
+        }
+
+        public override string ToString()
+        {
+            return String.Format(
+                "{0} (Baud: {1}/DataBits: {2}/Parity: {3}/StopBits: {4}/{5})",
+                this.Name,
+                this.BaudRate,
+                this.DataBits,
+                this.Parity,
+                this.StopBits,
+                this.RtsEnable ? "RTS" : "No RTS");
+        }
+    }
+
+    // Wrapper around SerialPort
+    public class SerialPortIo : ISerialPortIo
+    {
+        protected ILog Log { get; private set; }
+        static readonly ILog s_Log = LogManager.GetLogger(typeof(SerialPortIo));
+
+        readonly SerialPort _port;
+        readonly Stream _internalSerialStream;
+
+        private int readTimeout;
+        private int writeTimeout;
+
+        public int ReadTimeout
+        {
+            get { return readTimeout; }
+            set 
+            {
+                readTimeout = value;
+                _port.ReadTimeout = readTimeout;
+            }
+        }
+
+        public int WriteTimeout
+        {
+            get { return writeTimeout; }
+            set
+            {
+                writeTimeout = value;
+                _port.WriteTimeout = writeTimeout;
+            }
+        }
+
+        public void DiscardInBuffer()
+        {
+            _port.DiscardInBuffer();
+        }
+
+        public bool IsOpen
+        {
+            get { return _port.IsOpen; }
+        }
+
+        public SerialPortIo(SerialPortConfig portConfig)
+        {
+            if (portConfig == null) throw new ArgumentNullException("portConfig");
+
+            this.Log = LogManager.GetLogger(this.GetType());
+
+            // http://zachsaw.blogspot.com/2010/07/net-serialport-woes.html
+            SerialPortFixer.Execute(portConfig.Name);
+
+            var port = new SerialPort(
+                portConfig.Name,
+                portConfig.BaudRate,
+                portConfig.Parity,
+                portConfig.DataBits,
+                portConfig.StopBits)
+            {
+                RtsEnable = portConfig.RtsEnable,
+                DtrEnable = portConfig.DtrEnable,
+                ReadTimeout = 5000,
+                WriteTimeout = 5000
+            };
+            port.Open();
+
+            try
+            {
+                this._internalSerialStream = port.BaseStream;
+                this._port = port;
+                this._port.DiscardInBuffer();
+                this._port.DiscardOutBuffer();
+            }
+            catch (Exception ex)
+            {
+                Stream internalStream = this._internalSerialStream;
+
+                if (internalStream == null)
+                {
+                    FieldInfo field = typeof(SerialPort).GetField(
+                        "internalSerialStream",
+                        BindingFlags.Instance | BindingFlags.NonPublic);
+
+                    // This will happen if the SerialPort class is changed
+                    // in future versions of the .NET Framework
+                    if (field == null)
+                    {
+                        this.Log.WarnFormat(
+                            "An exception occured while creating the serial port adaptor, "
+                            + "the internal stream reference was not acquired and we were unable "
+                            + "to get it using reflection. The serial port may not be accessible "
+                            + "any further until the serial port object finalizer has been run: {0}",
+                            ex);
+
+                        throw;
+                    }
+
+                    internalStream = (Stream)field.GetValue(port);
+                }
+
+                this.Log.DebugFormat(
+                    "An error occurred while constructing the serial port adaptor: {0}", ex);
+
+                SafeDisconnect(port, internalStream);
+                throw;
+            }
+        }
+
+        public string PortName
+        {
+            get { return this._port.PortName; }
+        }
+
+        public int Read(char[] buffer, int offset, int count)
+        {
+            return this._port.Read(buffer, offset, count);
+        }
+
+        public int Read(byte[] buffer, int offset, int count)
+        {
+            return this._port.Read(buffer, offset, count);
+        }
+
+        public string ReadLine()
+        {
+            //return this._port.ReadTo(Environment.NewLine);
+            return this._port.ReadLine();
+        }
+
+        public string ReadExisting()
+        {
+            return this._port.ReadExisting();
+        }
+
+        public void Write(string text)
+        {
+            this._port.Write(text);
+        }
+
+        public void Write(char[] buffer, int offset, int count)
+        {
+            this._port.Write(buffer, offset, count);
+        }
+    
+
+        public void WriteLine(string text)
+        {
+            //this._port.Write(text);
+            //this._port.Write("\r");
+            this._port.WriteLine(text);
+        }
+
+        public void Dispose()
+        {
+            this.Dispose(true);
+        }
+
+        protected void Dispose(bool disposing)
+        {
+            SafeDisconnect(this._port, this._internalSerialStream);
+
+            if (disposing)
+            {
+                GC.SuppressFinalize(this);
+            }
+        }
+
+        /// <summary>
+        /// Safely closes a serial port and its internal stream even if
+        /// a USB serial interface was physically removed from the system
+        /// in a reliable manner.
+        /// </summary>
+        /// <param name="port"></param>
+        /// <param name="internalSerialStream"></param>
+        /// <remarks>
+        /// The <see cref="SerialPort"/> class has 3 different problems in disposal
+        /// in case of a USB serial device that is physically removed:
+        /// 
+        /// 1. The eventLoopRunner is asked to stop and <see cref="SerialPort.IsOpen"/> 
+        /// returns false. Upon disposal this property is checked and closing 
+        /// the internal serial stream is skipped, thus keeping the original 
+        /// handle open indefinitely (until the finalizer runs which leads to the next problem)
+        /// 
+        /// The solution for this one is to manually close the internal serial stream.
+        /// We can get its reference by <see cref="SerialPort.BaseStream" />
+        /// before the exception has happened or by reflection and getting the 
+        /// "internalSerialStream" field.
+        /// 
+        /// 2. Closing the internal serial stream throws an exception and closes 
+        /// the internal handle without waiting for its eventLoopRunner thread to finish, 
+        /// causing an uncatchable ObjectDisposedException from it later on when the finalizer 
+        /// runs (which oddly avoids throwing the exception but still fails to wait for 
+        /// the eventLoopRunner).
+        /// 
+        /// The solution is to manually ask the event loop runner thread to shutdown
+        /// (via reflection) and waiting for it before closing the internal serial stream.
+        /// 
+        /// 3. Since Dispose throws exceptions, the finalizer is not suppressed.
+        /// 
+        /// The solution is to suppress their finalizers at the beginning.
+        /// </remarks>
+        static void SafeDisconnect(SerialPort port, Stream internalSerialStream)
+        {
+            GC.SuppressFinalize(port);
+            GC.SuppressFinalize(internalSerialStream);
+
+            ShutdownEventLoopHandler(internalSerialStream);
+
+            try
+            {
+                s_Log.DebugFormat("Disposing internal serial stream");
+                internalSerialStream.Close();
+            }
+            catch (Exception ex)
+            {
+                s_Log.DebugFormat(
+                    "Exception in serial stream shutdown of port {0}: {1}", port.PortName, ex);
+            }
+
+            try
+            {
+                s_Log.DebugFormat("Disposing serial port");
+                port.Close();
+            }
+            catch (Exception ex)
+            {
+                s_Log.DebugFormat("Exception in port {0} shutdown: {1}", port.PortName, ex);
+            }
+        }
+
+        static void ShutdownEventLoopHandler(Stream internalSerialStream)
+        {
+            try
+            {
+                s_Log.DebugFormat("Working around .NET SerialPort class Dispose bug");
+
+                FieldInfo eventRunnerField = internalSerialStream.GetType()
+                    .GetField("eventRunner", BindingFlags.NonPublic | BindingFlags.Instance);
+
+                if (eventRunnerField == null)
+                {
+                    s_Log.WarnFormat(
+                        "Unable to find EventLoopRunner field. "
+                        + "SerialPort workaround failure. Application may crash after "
+                        + "disposing SerialPort unless .NET 1.1 unhandled exception "
+                        + "policy is enabled from the application's config file.");
+                }
+                else
+                {
+                    object eventRunner = eventRunnerField.GetValue(internalSerialStream);
+                    Type eventRunnerType = eventRunner.GetType();
+
+                    FieldInfo endEventLoopFieldInfo = eventRunnerType.GetField(
+                        "endEventLoop", BindingFlags.Instance | BindingFlags.NonPublic);
+
+                    FieldInfo eventLoopEndedSignalFieldInfo = eventRunnerType.GetField(
+                        "eventLoopEndedSignal", BindingFlags.Instance | BindingFlags.NonPublic);
+
+                    FieldInfo waitCommEventWaitHandleFieldInfo = eventRunnerType.GetField(
+                        "waitCommEventWaitHandle", BindingFlags.Instance | BindingFlags.NonPublic);
+
+                    if (endEventLoopFieldInfo == null
+                        || eventLoopEndedSignalFieldInfo == null
+                        || waitCommEventWaitHandleFieldInfo == null)
+                    {
+                        s_Log.WarnFormat(
+                            "Unable to find the EventLoopRunner internal wait handle or loop signal fields. "
+                            + "SerialPort workaround failure. Application may crash after "
+                            + "disposing SerialPort unless .NET 1.1 unhandled exception "
+                            + "policy is enabled from the application's config file.");
+                    }
+                    else
+                    {
+                        s_Log.DebugFormat(
+                            "Waiting for the SerialPort internal EventLoopRunner thread to finish...");
+
+                        var eventLoopEndedWaitHandle =
+                            (WaitHandle)eventLoopEndedSignalFieldInfo.GetValue(eventRunner);
+                        var waitCommEventWaitHandle =
+                            (ManualResetEvent)waitCommEventWaitHandleFieldInfo.GetValue(eventRunner);
+
+                        endEventLoopFieldInfo.SetValue(eventRunner, true);
+
+                        // Sometimes the event loop handler resets the wait handle
+                        // before exiting the loop and hangs (in case of USB disconnect)
+                        // In case it takes too long, brute-force it out of its wait by 
+                        // setting the handle again.
+                        do
+                        {
+                            waitCommEventWaitHandle.Set();
+                        } while (!eventLoopEndedWaitHandle.WaitOne(2000));
+
+                        s_Log.DebugFormat("Wait completed. Now it is safe to continue disposal.");
+                    }
+                }
+            }
+            catch (Exception ex)
+            {
+                s_Log.ErrorFormat(
+                    "SerialPort workaround failure. Application may crash after "
+                    + "disposing SerialPort unless .NET 1.1 unhandled exception "
+                    + "policy is enabled from the application's config file: {0}",
+                    ex);
+            }
+        }
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HspGuiSourceV301/HSPApp.sln	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,134 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 2013
+VisualStudioVersion = 12.0.31101.0
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HSPGui", "HSPGui\HSPGui.csproj", "{CEF8731E-362F-407C-86A7-F65ACE2A1ACB}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RPCSupport", "GuiDLLs\RPCSupport\RPCSupport.csproj", "{170A27F5-0680-485D-8B90-EA736719016E}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FirFilterTest", "FirFilterTest\FirFilterTest.csproj", "{2BFA2046-7A2C-48FB-8E79-CEB2DE6CDD0F}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SerialWrap", "GuiDLLs\SerialWrap\SerialWrap.csproj", "{28A72C36-6880-4A8E-800A-86959B22A8AC}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EcgViewTest", "EcgViewTest\EcgViewTest.csproj", "{99AD6A39-F828-4C0B-A03F-C34C42083075}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Maxim.Global", "GuiDLLs\MaximGlobal\Maxim.Global.csproj", "{57E4E43C-871B-4113-950E-D649AC6D386A}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FileLog", "GuiDLLs\FileLog\FileLog\FileLog.csproj", "{53B0D46E-43FD-425E-B316-98B8708D161F}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ChartHelper", "GuiDLLs\ChartHelper\ChartHelper\ChartHelper.csproj", "{3A90EBB9-82C1-4928-88AC-A79ABC7F1DE9}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RPCSupportTest", "RPCSupportTest\RPCSupportTest.csproj", "{067456C0-086C-46A8-B37F-1405717B7BFC}"
+EndProject
+Global
+	GlobalSection(SolutionConfigurationPlatforms) = preSolution
+		Debug|Any CPU = Debug|Any CPU
+		Debug|Mixed Platforms = Debug|Mixed Platforms
+		Debug|x86 = Debug|x86
+		Release|Any CPU = Release|Any CPU
+		Release|Mixed Platforms = Release|Mixed Platforms
+		Release|x86 = Release|x86
+	EndGlobalSection
+	GlobalSection(ProjectConfigurationPlatforms) = postSolution
+		{170A27F5-0680-485D-8B90-EA736719016E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{170A27F5-0680-485D-8B90-EA736719016E}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{170A27F5-0680-485D-8B90-EA736719016E}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
+		{170A27F5-0680-485D-8B90-EA736719016E}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
+		{170A27F5-0680-485D-8B90-EA736719016E}.Debug|x86.ActiveCfg = Debug|Any CPU
+		{170A27F5-0680-485D-8B90-EA736719016E}.Debug|x86.Build.0 = Debug|Any CPU
+		{170A27F5-0680-485D-8B90-EA736719016E}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{170A27F5-0680-485D-8B90-EA736719016E}.Release|Any CPU.Build.0 = Release|Any CPU
+		{170A27F5-0680-485D-8B90-EA736719016E}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
+		{170A27F5-0680-485D-8B90-EA736719016E}.Release|Mixed Platforms.Build.0 = Release|Any CPU
+		{170A27F5-0680-485D-8B90-EA736719016E}.Release|x86.ActiveCfg = Release|Any CPU
+		{170A27F5-0680-485D-8B90-EA736719016E}.Release|x86.Build.0 = Release|Any CPU
+		{CEF8731E-362F-407C-86A7-F65ACE2A1ACB}.Debug|Any CPU.ActiveCfg = Debug|x86
+		{CEF8731E-362F-407C-86A7-F65ACE2A1ACB}.Debug|Any CPU.Build.0 = Debug|x86
+		{CEF8731E-362F-407C-86A7-F65ACE2A1ACB}.Debug|Mixed Platforms.ActiveCfg = Debug|x86
+		{CEF8731E-362F-407C-86A7-F65ACE2A1ACB}.Debug|Mixed Platforms.Build.0 = Debug|x86
+		{CEF8731E-362F-407C-86A7-F65ACE2A1ACB}.Debug|x86.ActiveCfg = Debug|x86
+		{CEF8731E-362F-407C-86A7-F65ACE2A1ACB}.Debug|x86.Build.0 = Debug|x86
+		{CEF8731E-362F-407C-86A7-F65ACE2A1ACB}.Release|Any CPU.ActiveCfg = Release|x86
+		{CEF8731E-362F-407C-86A7-F65ACE2A1ACB}.Release|Any CPU.Build.0 = Release|x86
+		{CEF8731E-362F-407C-86A7-F65ACE2A1ACB}.Release|Mixed Platforms.ActiveCfg = Release|x86
+		{CEF8731E-362F-407C-86A7-F65ACE2A1ACB}.Release|Mixed Platforms.Build.0 = Release|x86
+		{CEF8731E-362F-407C-86A7-F65ACE2A1ACB}.Release|x86.ActiveCfg = Release|x86
+		{CEF8731E-362F-407C-86A7-F65ACE2A1ACB}.Release|x86.Build.0 = Release|x86
+		{2BFA2046-7A2C-48FB-8E79-CEB2DE6CDD0F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{2BFA2046-7A2C-48FB-8E79-CEB2DE6CDD0F}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{2BFA2046-7A2C-48FB-8E79-CEB2DE6CDD0F}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
+		{2BFA2046-7A2C-48FB-8E79-CEB2DE6CDD0F}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
+		{2BFA2046-7A2C-48FB-8E79-CEB2DE6CDD0F}.Debug|x86.ActiveCfg = Debug|Any CPU
+		{2BFA2046-7A2C-48FB-8E79-CEB2DE6CDD0F}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{2BFA2046-7A2C-48FB-8E79-CEB2DE6CDD0F}.Release|Any CPU.Build.0 = Release|Any CPU
+		{2BFA2046-7A2C-48FB-8E79-CEB2DE6CDD0F}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
+		{2BFA2046-7A2C-48FB-8E79-CEB2DE6CDD0F}.Release|Mixed Platforms.Build.0 = Release|Any CPU
+		{2BFA2046-7A2C-48FB-8E79-CEB2DE6CDD0F}.Release|x86.ActiveCfg = Release|Any CPU
+		{2BFA2046-7A2C-48FB-8E79-CEB2DE6CDD0F}.Release|x86.Build.0 = Release|Any CPU
+		{28A72C36-6880-4A8E-800A-86959B22A8AC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{28A72C36-6880-4A8E-800A-86959B22A8AC}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{28A72C36-6880-4A8E-800A-86959B22A8AC}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
+		{28A72C36-6880-4A8E-800A-86959B22A8AC}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
+		{28A72C36-6880-4A8E-800A-86959B22A8AC}.Debug|x86.ActiveCfg = Debug|Any CPU
+		{28A72C36-6880-4A8E-800A-86959B22A8AC}.Debug|x86.Build.0 = Debug|Any CPU
+		{28A72C36-6880-4A8E-800A-86959B22A8AC}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{28A72C36-6880-4A8E-800A-86959B22A8AC}.Release|Any CPU.Build.0 = Release|Any CPU
+		{28A72C36-6880-4A8E-800A-86959B22A8AC}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
+		{28A72C36-6880-4A8E-800A-86959B22A8AC}.Release|Mixed Platforms.Build.0 = Release|Any CPU
+		{28A72C36-6880-4A8E-800A-86959B22A8AC}.Release|x86.ActiveCfg = Release|Any CPU
+		{28A72C36-6880-4A8E-800A-86959B22A8AC}.Release|x86.Build.0 = Release|Any CPU
+		{99AD6A39-F828-4C0B-A03F-C34C42083075}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{99AD6A39-F828-4C0B-A03F-C34C42083075}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{99AD6A39-F828-4C0B-A03F-C34C42083075}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
+		{99AD6A39-F828-4C0B-A03F-C34C42083075}.Debug|x86.ActiveCfg = Debug|Any CPU
+		{99AD6A39-F828-4C0B-A03F-C34C42083075}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{99AD6A39-F828-4C0B-A03F-C34C42083075}.Release|Any CPU.Build.0 = Release|Any CPU
+		{99AD6A39-F828-4C0B-A03F-C34C42083075}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
+		{99AD6A39-F828-4C0B-A03F-C34C42083075}.Release|Mixed Platforms.Build.0 = Release|Any CPU
+		{99AD6A39-F828-4C0B-A03F-C34C42083075}.Release|x86.ActiveCfg = Release|Any CPU
+		{57E4E43C-871B-4113-950E-D649AC6D386A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{57E4E43C-871B-4113-950E-D649AC6D386A}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{57E4E43C-871B-4113-950E-D649AC6D386A}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
+		{57E4E43C-871B-4113-950E-D649AC6D386A}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
+		{57E4E43C-871B-4113-950E-D649AC6D386A}.Debug|x86.ActiveCfg = Debug|Any CPU
+		{57E4E43C-871B-4113-950E-D649AC6D386A}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{57E4E43C-871B-4113-950E-D649AC6D386A}.Release|Any CPU.Build.0 = Release|Any CPU
+		{57E4E43C-871B-4113-950E-D649AC6D386A}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
+		{57E4E43C-871B-4113-950E-D649AC6D386A}.Release|Mixed Platforms.Build.0 = Release|Any CPU
+		{57E4E43C-871B-4113-950E-D649AC6D386A}.Release|x86.ActiveCfg = Release|Any CPU
+		{53B0D46E-43FD-425E-B316-98B8708D161F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{53B0D46E-43FD-425E-B316-98B8708D161F}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{53B0D46E-43FD-425E-B316-98B8708D161F}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
+		{53B0D46E-43FD-425E-B316-98B8708D161F}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
+		{53B0D46E-43FD-425E-B316-98B8708D161F}.Debug|x86.ActiveCfg = Debug|Any CPU
+		{53B0D46E-43FD-425E-B316-98B8708D161F}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{53B0D46E-43FD-425E-B316-98B8708D161F}.Release|Any CPU.Build.0 = Release|Any CPU
+		{53B0D46E-43FD-425E-B316-98B8708D161F}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
+		{53B0D46E-43FD-425E-B316-98B8708D161F}.Release|Mixed Platforms.Build.0 = Release|Any CPU
+		{53B0D46E-43FD-425E-B316-98B8708D161F}.Release|x86.ActiveCfg = Release|Any CPU
+		{3A90EBB9-82C1-4928-88AC-A79ABC7F1DE9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{3A90EBB9-82C1-4928-88AC-A79ABC7F1DE9}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{3A90EBB9-82C1-4928-88AC-A79ABC7F1DE9}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
+		{3A90EBB9-82C1-4928-88AC-A79ABC7F1DE9}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
+		{3A90EBB9-82C1-4928-88AC-A79ABC7F1DE9}.Debug|x86.ActiveCfg = Debug|Any CPU
+		{3A90EBB9-82C1-4928-88AC-A79ABC7F1DE9}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{3A90EBB9-82C1-4928-88AC-A79ABC7F1DE9}.Release|Any CPU.Build.0 = Release|Any CPU
+		{3A90EBB9-82C1-4928-88AC-A79ABC7F1DE9}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
+		{3A90EBB9-82C1-4928-88AC-A79ABC7F1DE9}.Release|Mixed Platforms.Build.0 = Release|Any CPU
+		{3A90EBB9-82C1-4928-88AC-A79ABC7F1DE9}.Release|x86.ActiveCfg = Release|Any CPU
+		{067456C0-086C-46A8-B37F-1405717B7BFC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{067456C0-086C-46A8-B37F-1405717B7BFC}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{067456C0-086C-46A8-B37F-1405717B7BFC}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
+		{067456C0-086C-46A8-B37F-1405717B7BFC}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
+		{067456C0-086C-46A8-B37F-1405717B7BFC}.Debug|x86.ActiveCfg = Debug|Any CPU
+		{067456C0-086C-46A8-B37F-1405717B7BFC}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{067456C0-086C-46A8-B37F-1405717B7BFC}.Release|Any CPU.Build.0 = Release|Any CPU
+		{067456C0-086C-46A8-B37F-1405717B7BFC}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
+		{067456C0-086C-46A8-B37F-1405717B7BFC}.Release|Mixed Platforms.Build.0 = Release|Any CPU
+		{067456C0-086C-46A8-B37F-1405717B7BFC}.Release|x86.ActiveCfg = Release|Any CPU
+	EndGlobalSection
+	GlobalSection(SolutionProperties) = preSolution
+		HideSolutionNode = FALSE
+	EndGlobalSection
+EndGlobal
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HspGuiSourceV301/HSPGui/Algorithm/InterfaceRedIRGreenLEDdataConsumer.cs	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,82 @@
+/*******************************************************************************
+* Copyright (C) 2016 Maxim Integrated Products, Inc., All rights Reserved.
+* 
+* This software is protected by copyright laws of the United States and
+* of foreign countries. This material may also be protected by patent laws
+* and technology transfer regulations of the United States and of foreign
+* countries. This software is furnished under a license agreement and/or a
+* nondisclosure agreement and may only be used or reproduced in accordance
+* with the terms of those agreements. Dissemination of this information to
+* any party or parties not specified in the license agreement and/or
+* nondisclosure agreement is expressly prohibited.
+*
+* The above copyright notice and this permission notice shall be included
+* in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+* OTHER DEALINGS IN THE SOFTWARE.
+*
+* Except as contained in this notice, the name of Maxim Integrated
+* Products, Inc. shall not be used except as stated in the Maxim Integrated
+* Products, Inc. Branding Policy.
+*
+* The mere transfer of this software does not imply any licenses
+* of trade secrets, proprietary technology, copyrights, patents,
+* trademarks, maskwork rights, or any other form of intellectual
+* property whatsoever. Maxim Integrated Products, Inc. retains all
+* ownership rights.
+*******************************************************************************
+*/
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+//------------------------------------------------------------------------------------------
+// OS24EVK-59 split into HeartRateApp EXE and MAX30101 DLL.
+// Moved all MAX30101 DLL classes into namespace Maxim.MAX30101GUI
+// Moved all HeartRateApp GUI classes into namespace Maxim.MAX30101
+// OS24EVK-59 Create separate project that builds Maxim.MAX30101GUI DLL library
+
+namespace Maxim.MAX30101GUI
+{
+    interface InterfaceRedIRGreenLEDdataConsumer
+    {
+        /// <summary>
+        /// <para>Producer-Consumer data sink for
+        /// raw Red/IR/Green LED data.
+        /// Produced by MAX30101, consumed by algorithm.
+        /// </para>
+        /// </summary>
+        /// <param name="sampleNumber"></param>
+        /// <param name="rawIR"></param>
+        /// <param name="rawRed"></param>
+        /// <param name="rawGreen"></param>
+        /// <param name="rawIRvalid"></param>
+        /// <param name="rawRedvalid"></param>
+        /// <param name="rawGreenvalid"></param>
+        void ConsumeRedIRGreenLEDdata(
+                int sampleNumber,
+                int rawIR,
+                int rawRed,
+                int rawGreen,
+                bool rawIRvalid,
+                bool rawRedvalid,
+                bool rawGreenvalid
+            );
+
+        // prepare for OS24EVK-37 by adding SensorTemperatureDegreesC(double) to InterfaceRedIRGreenLEDdataConsumer
+        /// <summary>
+        /// <para>Temperature measured at MAX30101, optionally used by algorithm to estimate actual Red LED wavelength.</para>
+        /// </summary>
+        /// <param name="temperatureDegreesC"></param>
+        void SensorTemperatureDegreesC(double temperatureDegreesC);
+
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HspGuiSourceV301/HSPGui/Algorithm/MaximAlgorithmClass.cs	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,186 @@
+/*******************************************************************************
+* Copyright (C) 2016 Maxim Integrated Products, Inc., All rights Reserved.
+* 
+* This software is protected by copyright laws of the United States and
+* of foreign countries. This material may also be protected by patent laws
+* and technology transfer regulations of the United States and of foreign
+* countries. This software is furnished under a license agreement and/or a
+* nondisclosure agreement and may only be used or reproduced in accordance
+* with the terms of those agreements. Dissemination of this information to
+* any party or parties not specified in the license agreement and/or
+* nondisclosure agreement is expressly prohibited.
+*
+* The above copyright notice and this permission notice shall be included
+* in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+* OTHER DEALINGS IN THE SOFTWARE.
+*
+* Except as contained in this notice, the name of Maxim Integrated
+* Products, Inc. shall not be used except as stated in the Maxim Integrated
+* Products, Inc. Branding Policy.
+*
+* The mere transfer of this software does not imply any licenses
+* of trade secrets, proprietary technology, copyrights, patents,
+* trademarks, maskwork rights, or any other form of intellectual
+* property whatsoever. Maxim Integrated Products, Inc. retains all
+* ownership rights.
+*******************************************************************************
+*/
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+//------------------------------------------------------------------------------------------
+// OS24EVK-59 split into HeartRateApp EXE and MAX30101 DLL.
+// Moved all MAX30101 DLL classes into namespace Maxim.MAX30101GUI
+// Moved all HeartRateApp GUI classes into namespace Maxim.MAX30101
+// OS24EVK-59 Create separate project that builds Maxim.MAX30101GUI DLL library
+
+namespace Maxim.MAX30101GUI
+{
+    /// <summary>
+    /// Base class common to any HeartRate / SpO2 algorithm.
+    /// Input is Red / IR / Green LED data, output is Heart Rate and SpO2.
+    /// </summary>
+    public class MaximAlgorithmClass : InterfaceRedIRGreenLEDdataConsumer
+    {
+        public MaximAlgorithmClass() 
+        {
+            Name = "Maxim Generic Algorithm Base Class";
+        }
+
+        public string Name;
+        public int _sampleNumber;
+        public int _sampleNumberLastValidHR;
+        public int _sampleNumberLastValidSpO2;
+
+        public double _heartRateBPM;
+        public bool   _heartRateBPMValid;
+        public double _heartRateBPMSignalStrength;
+        public double _spO2Percent;
+        public bool   _spO2PercentValid;
+        public double _spO2PercentSignalStrength;
+
+        /// <summary>
+        /// Clear any internal class members,
+        /// in response to startMonitorToolStripMenuItem
+        /// </summary>
+        public virtual void Clear()
+        {
+        }
+
+        /// <summary>
+        /// <para>InterfaceRedIRGreenLEDdataConsumer</para>
+        /// <para>Producer-Consumer data sink for
+        /// raw Red/IR/Green LED data.
+        /// Produced by MAX30101, consumed by algorithm.
+        /// </para>
+        /// </summary>
+        /// <param name="sampleNumber"></param>
+        /// <param name="rawIR"></param>
+        /// <param name="rawRed"></param>
+        /// <param name="rawGreen"></param>
+        /// <param name="rawIRvalid"></param>
+        /// <param name="rawRedvalid"></param>
+        /// <param name="rawGreenvalid"></param>
+        public virtual void ConsumeRedIRGreenLEDdata(
+                int sampleNumber,
+                int rawIR,
+                int rawRed,
+                int rawGreen,
+                bool rawIRvalid,
+                bool rawRedvalid,
+                bool rawGreenvalid
+            )
+        {
+            _sampleNumber = sampleNumber;
+        }
+
+        // prepare for OS24EVK-37 by adding SensorTemperatureDegreesC(double) to InterfaceRedIRGreenLEDdataConsumer
+        public double _temperatureDegreesC;
+
+        /// <summary>
+        /// <para>Temperature measured at MAX30101, optionally used by algorithm to estimate actual Red LED wavelength.</para>
+        /// </summary>
+        /// <param name="temperatureDegreesC"></param>
+        public void SensorTemperatureDegreesC(double temperatureDegreesC)
+        {
+            _temperatureDegreesC = temperatureDegreesC;
+        }
+
+        /// <summary>
+        /// <para>Delegate type for event <see cref="OnHeartRateSpO2dataAvailable"/></para>
+        /// </summary>
+        /// <param name="heartRateBPM"></param>
+        /// <param name="heartRateBPMValid"></param>
+        /// <param name="heartRateBPMSignalStrength"></param>
+        /// <param name="spO2Percent"></param>
+        /// <param name="spO2PercentValid"></param>
+        /// <param name="spO2PercentSignalStrength"></param>
+        public delegate void OnHeartRateSpO2dataAvailableHandler(
+                double heartRateBPM,
+                bool   heartRateBPMValid,
+                double heartRateBPMSignalStrength,
+                double spO2Percent,
+                bool   spO2PercentValid,
+                double spO2PercentSignalStrength
+            );
+
+        /// <summary>
+        /// <para>Occurs when HeartRate Data Available Event happens.
+        /// </para>
+        /// <para>An algorithm reports its results by invoking
+        /// <code>OnHeartRateSpO2dataAvailable(heartRateBPM, heartRateBPMValid, heartRateBPMSignalStrength, spO2Percent, spO2PercentValid, spO2PercentSignalStrength);</code>
+        /// </para>
+        /// </summary>
+        public event OnHeartRateSpO2dataAvailableHandler OnHeartRateSpO2dataAvailable;
+
+        /// <summary>
+        /// Report the results of running the algorithm,
+        /// by firing the OnHeartRateSpO2dataAvailable event.
+        /// </summary>
+        /// <param name="heartRateBPM"></param>
+        /// <param name="heartRateBPMValid"></param>
+        /// <param name="heartRateBPMSignalStrength"></param>
+        /// <param name="spO2Percent"></param>
+        /// <param name="spO2PercentValid"></param>
+        /// <param name="spO2PercentSignalStrength"></param>
+        public void ReportResultsHeartRateSpO2dataAvailable(
+                double heartRateBPM,
+                bool heartRateBPMValid,
+                double heartRateBPMSignalStrength,
+                double spO2Percent,
+                bool spO2PercentValid,
+                double spO2PercentSignalStrength
+            )
+        {
+            _heartRateBPM = heartRateBPM;
+            _heartRateBPMValid = heartRateBPMValid;
+            _heartRateBPMSignalStrength = heartRateBPMSignalStrength;
+            _spO2Percent = spO2Percent;
+            _spO2PercentValid = spO2PercentValid;
+            _spO2PercentSignalStrength = spO2PercentSignalStrength;
+            if (heartRateBPMValid)
+            {
+                _sampleNumberLastValidHR = _sampleNumber;
+            }
+            if (spO2PercentValid)
+            {
+                _sampleNumberLastValidSpO2 = _sampleNumber;
+            }
+            if (OnHeartRateSpO2dataAvailable != null)
+            {
+                OnHeartRateSpO2dataAvailable(heartRateBPM, heartRateBPMValid, heartRateBPMSignalStrength, spO2Percent, spO2PercentValid, spO2PercentSignalStrength);
+            }
+        }
+
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HspGuiSourceV301/HSPGui/Algorithm/MaximSKAlgorithmClass.cs	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,313 @@
+/*******************************************************************************
+* Copyright (C) 2016 Maxim Integrated Products, Inc., All rights Reserved.
+* 
+* This software is protected by copyright laws of the United States and
+* of foreign countries. This material may also be protected by patent laws
+* and technology transfer regulations of the United States and of foreign
+* countries. This software is furnished under a license agreement and/or a
+* nondisclosure agreement and may only be used or reproduced in accordance
+* with the terms of those agreements. Dissemination of this information to
+* any party or parties not specified in the license agreement and/or
+* nondisclosure agreement is expressly prohibited.
+*
+* The above copyright notice and this permission notice shall be included
+* in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+* OTHER DEALINGS IN THE SOFTWARE.
+*
+* Except as contained in this notice, the name of Maxim Integrated
+* Products, Inc. shall not be used except as stated in the Maxim Integrated
+* Products, Inc. Branding Policy.
+*
+* The mere transfer of this software does not imply any licenses
+* of trade secrets, proprietary technology, copyrights, patents,
+* trademarks, maskwork rights, or any other form of intellectual
+* property whatsoever. Maxim Integrated Products, Inc. retains all
+* ownership rights.
+*******************************************************************************
+*/
+
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+//------------------------------------------------------------------------------------------
+// OS24EVK-59 split into HeartRateApp EXE and MAX30101 DLL.
+// Moved all MAX30101 DLL classes into namespace Maxim.MAX30101GUI
+// Moved all HeartRateApp GUI classes into namespace Maxim.MAX30101
+// OS24EVK-59 Create separate project that builds Maxim.MAX30101GUI DLL library
+
+namespace Maxim.MAX30101GUI
+{
+    /// <summary>
+    /// Encapsulate the Maxim SKA Algorithm
+    /// </summary>
+    public class MaximSKAlgorithmClass : MaximAlgorithmClass
+    {
+        public MaximSKAlgorithmClass()
+        {
+            // https://jira.maxim-ic.com/browse/OS24EVK-40 remove "algorithm" from algorithm names
+            // https://jira.maxim-ic.com/browse/OS24EVK-45 Rename PBA / SKA algorithms
+            Name = "Maxim Example Algorithm 2 [SKA.dll]";
+        }
+
+        // https://jira.maxim-ic.com/browse/OS24EVK-15 any SKA dependencies? e.g. init MaximSKAlgorithmClass._cboPulseWidthIndex from (byte)(cboPulseWidth.SelectedIndex)
+        // public byte _cboPulseWidthIndex = 0;
+
+        // Steve Koh's variables
+        int _heartRateBPMint; // alias HR
+        float _spO2Percentfloat; // alias fSPO2
+
+        const int _SKA_windowSize = 100;
+        const int _SKA_bufferSize = 500;
+        // https://jira.maxim-ic.com/browse/OS24EVK-15 MaximSKAlgorithmClass accumulate irBuf[0..] _SKA_bufferSize for SKA.SKA_work
+        int[] irBuf = new int[_SKA_bufferSize];
+        int[] redBuf = new int[_SKA_bufferSize];
+        int[] greenBuf = new int[_SKA_bufferSize];
+        // https://jira.maxim-ic.com/browse/OS24EVK-35 Support HR from Green LED (SKA)
+        ArrayList _SKA_IRList = new ArrayList();
+        ArrayList _SKA_tempIRList = new ArrayList();
+        ArrayList _SKA_redList = new ArrayList();
+        ArrayList _SKA_tempRedList = new ArrayList();
+        ArrayList _SKA_greenList = new ArrayList();
+        ArrayList _SKA_tempGreenList = new ArrayList();
+        int _SKA_numSamplesSinceLastCalc;
+        int _SKA_elapsedSecond;
+        //int _SKA_validHRcount;
+        //int _SKA_invalidHRcount;
+        //int _SKA_validSPO2count;
+        //int _SKA_invalidSPO2count;
+        //int _SKA_lastValidHRtimestamp;
+        //int _SKA_lastValidSPO2timestamp;
+        // diagnostic: output from SKA algorithm filtering
+        float[] irAcBuf = new float[100];
+        float[] redAcBuf = new float[100];
+        // end of Steve Koh's variables
+
+        /// <summary>
+        /// Clear any internal class members,
+        /// in response to startMonitorToolStripMenuItem
+        /// </summary>
+        override public void Clear()
+        {
+            _SKA_elapsedSecond = 1;
+            //_SKA_lastValidHRtimestamp = 1;
+            //_SKA_lastValidSPO2timestamp = 1;
+            //_SKA_validHRcount = 0;
+            //_SKA_invalidHRcount = 0;
+            //_SKA_validSPO2count = 0;
+            //_SKA_invalidSPO2count = 0;
+
+            _SKA_IRList = new ArrayList();
+            _SKA_tempIRList = new ArrayList();
+            _SKA_redList = new ArrayList();
+            _SKA_tempRedList = new ArrayList();
+            _SKA_greenList = new ArrayList();
+            _SKA_tempGreenList = new ArrayList();
+            _SKA_numSamplesSinceLastCalc = 0;
+            // https://jira.maxim-ic.com/browse/OS24EVK-15 SKA need preload _SKA_IRList _SKA_bufferSize in startMonitorToolStripMenuItem_Click
+            for (int index = 0; index < _SKA_bufferSize; index++)
+            {
+                _SKA_IRList.Add(0);
+                _SKA_redList.Add(0);
+                _SKA_greenList.Add(0);
+            }
+        }
+
+        /// <summary>
+        /// <para>InterfaceRedIRGreenLEDdataConsumer</para>
+        /// <para>Producer-Consumer data sink for
+        /// raw Red/IR/Green LED data.
+        /// Produced by MAX30101, consumed by algorithm.
+        /// </para>
+        /// </summary>
+        /// <param name="sampleNumber"></param>
+        /// <param name="rawIR"></param>
+        /// <param name="rawRed"></param>
+        /// <param name="rawGreen"></param>
+        /// <param name="rawIRvalid"></param>
+        /// <param name="rawRedvalid"></param>
+        /// <param name="rawGreenvalid"></param>
+        override public void ConsumeRedIRGreenLEDdata(
+                int sampleNumber,
+                int rawIR,
+                int rawRed,
+                int rawGreen,
+                bool rawIRvalid,
+                bool rawRedvalid,
+                bool rawGreenvalid
+            )
+        {
+            base.ConsumeRedIRGreenLEDdata(sampleNumber, rawIR, rawRed, rawGreen, rawIRvalid, rawRedvalid, rawGreenvalid);
+
+            bool valid_IR = rawIRvalid;
+            bool valid_Red = rawRedvalid;
+            bool valid_Green = rawGreenvalid;
+            // https://jira.maxim-ic.com/browse/OS24EVK-25 SpO2 mode if LED mode and Red and IR data
+            bool HRvalid = (valid_Red || valid_Green);
+            bool SPO2valid = (valid_Red && valid_IR);
+            //
+            // example: https://jira.maxim-ic.com/browse/OS24EVK-37 SpO2 Temperature Compensation
+            #region SpO2_Temperature_Compensation
+            // SpO2 Temperature Compensation (See MAX30101 data sheet, Applications Information)
+            // Estimate red LED temperature rise from peak current and pulse width configuration settings,
+            // then use estimated red LED temperature to estimate actual red LED wavelength.
+            //
+            // double red_LED_temperature_delta = lookup table from peak current and duty cycle
+            // See MAX30101 data sheet Table 13. RED LED Current Settings vs LED Temperature Rise
+            //
+            // double red_LED_temperatureDegreesC = base._temperatureDegreesC +  red_LED_temperature_delta;
+            //
+            // double red_LED_wavelength = lookup table from red_LED_temperatureDegreesC 
+            // See MAX30101 data sheet toc10 RED LED PEAK WAVELENGTH vs TEMPERATURE
+            //
+            #endregion SpO2_Temperature_Compensation
+
+            double heartRateBPM; // = (double)heartRateBPMint
+            bool heartRateBPMValid = false;
+            double heartRateBPMSignalStrength = 0;
+            double spO2Percent; //  = (double)spO2Percentfloat
+            bool spO2PercentValid = false;
+            double spO2PercentSignalStrength = 0; // = (double)SPO2error
+            float SPO2error = 0;
+            // https://jira.maxim-ic.com/browse/OS24EVK-15 move SKA algorithm into MaximSKAlgorithmClass
+
+            // https://jira.maxim-ic.com/browse/OS24EVK-15 MaximSKAlgorithmClass accumulate irBuf[0..] _SKA_bufferSize for SKA.SKA_work
+            // int[] irBuf = new int[_SKA_bufferSize];
+            // int[] redBuf = new int[_SKA_bufferSize];
+            for (int index = 0; index < _SKA_tempRedList.Count; index++)
+            {
+                _SKA_IRList.Add((int)_SKA_tempIRList[index]);
+                _SKA_IRList.RemoveAt(0);
+                _SKA_redList.Add((int)_SKA_tempRedList[index]);
+                _SKA_redList.RemoveAt(0);
+                _SKA_greenList.Add((int)_SKA_tempGreenList[index]);
+                _SKA_greenList.RemoveAt(0);
+                _SKA_numSamplesSinceLastCalc++;
+            }
+            _SKA_tempIRList.Clear();
+            _SKA_tempRedList.Clear();
+            _SKA_tempGreenList.Clear();
+            //
+            if (_SKA_numSamplesSinceLastCalc < _SKA_windowSize)
+            {
+                _SKA_IRList.Add(rawIR);
+                _SKA_IRList.RemoveAt(0);
+                _SKA_redList.Add(rawRed);
+                _SKA_redList.RemoveAt(0);
+                _SKA_greenList.Add(rawGreen);
+                _SKA_greenList.RemoveAt(0);
+            }
+            else
+            {
+                _SKA_tempIRList.Add(rawIR);
+                _SKA_tempRedList.Add(rawRed);
+                _SKA_tempGreenList.Add(rawGreen);
+            }
+            _SKA_numSamplesSinceLastCalc++;
+            //
+            if (_SKA_numSamplesSinceLastCalc >= _SKA_windowSize)
+            {
+                _SKA_numSamplesSinceLastCalc = 0;
+                for (int index = 0; index < _SKA_IRList.Count; index++)
+                {
+                    irBuf[index] = (int)_SKA_IRList[index];
+                    redBuf[index] = (int)_SKA_redList[index];
+                    greenBuf[index] = (int)_SKA_greenList[index];
+                }
+
+                // Steve Koh's algorithm uses Fs=100Sps. It processes 500 samples at a time. Shift in 100 new samples before the function is called.
+                // Since we're running at 100Sps, this routine is called every 100 samples.
+                // Although _SKA_elapsedSecond = num samples / Fs, Steve used an integer type and so only Fs=100Sps or 50Sps would work. Regardless, we are using fixed 100Sps.
+                //
+                //	Heart Rate/SpO2 Monitor function takes 18bit input irBuffer[500] and redBuffer[500].
+                //	Inputs:
+                //		int lapsedSecond         -> _SKA_elapsedSecond   must be >3 before anything happens
+                //		const int irBuffer[500]  -> irBuf
+                //		const int redBuffer[500] -> redBuf
+                //	Outputs:
+                //		unsigned int *heartRate  -> HR          Heart Rate in beats per minute.
+                //		float *SPO2              -> fSPO2       SpO2 value as %saturation.
+                //		boolean_T *SPO2valid     -> SPO2valid
+                //		boolean_T *HRvalid       -> HRvalid
+                //		float *SPO2errorStatus   -> SPO2error   looks like a signal strength?
+                //		float last100Ir[100]     -> irAcBuf
+                //		float last100Red[100]    -> redAcBuf
+                //
+                if (valid_Green && !valid_IR) // Green mode - green into IR channel
+                {
+                    // https://jira.maxim-ic.com/browse/OS24EVK-15 move SKA algorithm into MaximSKAlgorithmClass
+                    // https://jira.maxim-ic.com/browse/OS24EVK-35 Support HR from Green LED (SKA Algorithm)
+                    // for SKA green LED support, looks like we have to preload redBuf with Green LED data...
+                    // no IR, but we can use Green instead for HR. (No SpO2 measurement so both channels Green.)
+                    SKA.SKA_work(
+                        _SKA_elapsedSecond, 
+                        greenBuf, 
+                        greenBuf, 
+                        ref _heartRateBPMint, 
+                        ref _spO2Percentfloat,
+                        ref spO2PercentValid,
+                        ref heartRateBPMValid, 
+                        ref SPO2error, 
+                        irAcBuf, 
+                        redAcBuf);
+                }
+                else if (valid_Red && !valid_IR && !valid_Green) // HR mode - red into IR channel
+                {
+                    SKA.SKA_work(
+                        _SKA_elapsedSecond,
+                        redBuf,
+                        redBuf,
+                        ref _heartRateBPMint,
+                        ref _spO2Percentfloat,
+                        ref spO2PercentValid,
+                        ref heartRateBPMValid,
+                        ref SPO2error,
+                        irAcBuf,
+                        redAcBuf);
+                }
+                else // SpO2 mode
+                {
+                    // https://jira.maxim-ic.com/browse/OS24EVK-15 move SKA algorithm into MaximSKAlgorithmClass
+                    // normal HR from Red, SpO2 if IR is available
+                    // SKA.SKA_work(_SKA_elapsedSecond, irBuf, redBuf, ref HR, ref fSPO2, ref SPO2valid, ref HRvalid, ref SPO2error, irAcBuf, redAcBuf);
+                    SKA.SKA_work(
+                        _SKA_elapsedSecond, 
+                        irBuf, 
+                        redBuf, 
+                        ref _heartRateBPMint, 
+                        ref _spO2Percentfloat,
+                        ref spO2PercentValid,
+                        ref heartRateBPMValid, 
+                        ref SPO2error, 
+                        irAcBuf, 
+                        redAcBuf);
+                }
+                _SKA_elapsedSecond++;
+
+
+            // https://jira.maxim-ic.com/browse/OS24EVK-15 SKA algorithm report results by InterfaceHeartRateSpO2dataConsumer.ConsumeHeartRateSpO2data(heartRateBPM, ...)
+            heartRateBPM = (double)_heartRateBPMint;
+            spO2Percent = (double)_spO2Percentfloat;
+            // OS24EVK-35 don't report SpO2 if there was not valid red and IR data (i.e. green only)
+            if (!(valid_Red && valid_IR)) { spO2PercentValid = false; }
+            spO2PercentSignalStrength = (double)SPO2error;
+            // https://jira.maxim-ic.com/browse/OS24EVK-15 SKAAlgorithm reporting SpO2 999 as if that was valid.
+            // SKA Algorithm reports SpO2 bogus value 999% as valid; need to determine why reported as a valid result.
+            // spO2PercentValid = (spO2PercentSignalStrength > 0);
+            // don't modify spO2PercentValid; already passed by ref from SKA.SKA_work()
+            ReportResultsHeartRateSpO2dataAvailable(heartRateBPM, heartRateBPMValid, heartRateBPMSignalStrength, spO2Percent, spO2PercentValid, spO2PercentSignalStrength);
+            System.Diagnostics.Debug.Print("heartRateBPM: " + heartRateBPM + " heartRateBPMValid: " + heartRateBPMValid + " spO2Percent: " + spO2Percent + " spO2PercentValid: " + spO2PercentValid);
+            } // if (_SKA_numSamplesSinceLastCalc >= _SKA_windowSize)
+        }
+   
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HspGuiSourceV301/HSPGui/Algorithm/SKA.cs	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,88 @@
+/*******************************************************************************
+* Copyright (C) 2016 Maxim Integrated Products, Inc., All rights Reserved.
+* 
+* This software is protected by copyright laws of the United States and
+* of foreign countries. This material may also be protected by patent laws
+* and technology transfer regulations of the United States and of foreign
+* countries. This software is furnished under a license agreement and/or a
+* nondisclosure agreement and may only be used or reproduced in accordance
+* with the terms of those agreements. Dissemination of this information to
+* any party or parties not specified in the license agreement and/or
+* nondisclosure agreement is expressly prohibited.
+*
+* The above copyright notice and this permission notice shall be included
+* in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+* OTHER DEALINGS IN THE SOFTWARE.
+*
+* Except as contained in this notice, the name of Maxim Integrated
+* Products, Inc. shall not be used except as stated in the Maxim Integrated
+* Products, Inc. Branding Policy.
+*
+* The mere transfer of this software does not imply any licenses
+* of trade secrets, proprietary technology, copyrights, patents,
+* trademarks, maskwork rights, or any other form of intellectual
+* property whatsoever. Maxim Integrated Products, Inc. retains all
+* ownership rights.
+*******************************************************************************
+*/
+
+using System;
+using System.Windows.Forms;
+using System.Runtime.InteropServices;
+
+
+namespace Maxim.MAX30101GUI
+{
+    public static class SKA  // Steve Koh Algorithm
+    {
+        [DllImport("SKA.dll", CallingConvention = CallingConvention.Cdecl, SetLastError = true)]
+        private static extern void processIrRed_R5_initialize();
+        [DllImport("SKA.dll", CallingConvention = CallingConvention.Cdecl, SetLastError = true)]
+        private static extern void processIrRed_R5_terminate();
+        [DllImport("SKA.dll", CallingConvention = CallingConvention.Cdecl, SetLastError = true)]
+        internal static extern void processIrRed_R5(int lapsedSecond, int[] irBuf, int[] redBuf, ref int HR, ref float SPO2, ref bool SPO2valid, ref bool HRvalid, ref float SPO2errorStatus, float[] IrBuffer_filtered_ac, float[] redBuffer_filtered_ac);
+
+        static public void SKA_init()
+        {
+            try
+            {
+                processIrRed_R5_initialize();
+            }
+            catch (Exception ex)
+            {
+                throw new Exception(ex.Message + Environment.NewLine + new System.Diagnostics.StackFrame().GetMethod().Name);
+            }
+        }
+
+        static public void SKA_term()
+        {
+            try
+            {
+                processIrRed_R5_terminate();
+            }
+            catch (Exception ex)
+            {
+                throw new Exception(ex.Message + Environment.NewLine + new System.Diagnostics.StackFrame().GetMethod().Name);
+            }
+        }
+
+        static public void SKA_work(int lapsedSecond, int[] irBuf, int[] redBuf, ref int HR, ref float SPO2, ref bool SPO2valid, ref bool HRvalid, ref float SPO2error, float[] IrBuffer_filtered_ac, float[] redBuffer_filtered_ac)
+        {
+            try
+            {
+                processIrRed_R5(lapsedSecond, irBuf, redBuf, ref HR, ref SPO2, ref SPO2valid, ref HRvalid, ref SPO2error, IrBuffer_filtered_ac, redBuffer_filtered_ac);
+            }
+            catch (Exception ex)
+            {
+                throw new Exception(ex.Message + Environment.NewLine + new System.Diagnostics.StackFrame().GetMethod().Name);
+            }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HspGuiSourceV301/HSPGui/AlgorithmMobileBU.cs	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,98 @@
+//#define CES_DEMO
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+using System.Runtime.InteropServices;
+
+namespace HealthSensorPlatform
+{
+#if CES_DEMO
+    class AlgorithmMobileBU
+    {
+        // Algorithm from Mobile BU
+        public const string DllName = "algo_win.dll";
+
+        public struct AlgorithmOutput
+        {
+            public double version;
+            public double hr;
+            public double spo2;
+            public double sigQual;
+            public double irAC;
+            public double irDC;
+            public double redAC;
+            public double redDC;
+            //#ifdef _ELFI_
+            public double acLowPerfusion;
+            public double irLEDFlag;
+            public double redLEDFlag;
+            public double flagNoFinger; //Valid only at the first rest before motion
+            public double flagMotion;    //is equal to 1 when there is motion
+            public double flagHrValid;
+            //#endif
+            public double hrUpdateFlag;
+            public double PA_R;
+            public double PA_IR;
+            public double PA_V;
+            public double ppg; // cetin
+            public double raw_without_ppg;
+            public double secondary_hr;
+            public double secondary_spo2;
+            public double source_is_secondary_flag;
+            public double raw_ir;
+            public double raw_red;
+            public double acceleration;
+
+            public double smoothed_ir;
+            public double smoothed_red;
+            public double v42Tr;
+            public double v60Tr;
+            public double R_HR;
+            public double IRHR;
+            public double R_FO;
+            public double IRFO;
+            public double Clock;
+            public double SysClk;
+            public double IR_hrupd;
+            public double R_hrupd;
+
+            public double pulse_average;
+            public double pulse_interval;
+            public double hrv;
+            public double resp_rate;
+            public double heartbeats_reported_in_this_touch;
+            public double last_reported_heartbeat_rate;
+            public double perfusion;
+            public double R;                       // R ratio from SpO2
+        };
+
+        public struct AlgorithmConfiguration
+        {
+            public sbyte snrNoFingerThreshold;  // snr below that threshold will cause flagNoFingerRest to be equal to 1. Valid only at the first few secs rest
+            public double acLowPerfusionThreshold; // Threshold for output.acLowPerfusion// Above this threshold flagLowPerfusion == 1
+            public int isAGC;
+        };
+
+        /// <summary>
+        /// Heart Rate and Pulse Ox algorithm
+        /// </summary>
+        /// <param name="ir"></param>
+        /// <param name="r"></param>
+        /// <param name="led"></param>
+        /// <param name="acThresh"></param>
+        /// <param name="fs"></param>
+        /// <param name="isReset"></param>
+        /// <param name="accel_x"></param>
+        /// <param name="accel_y"></param>
+        /// <param name="accel_z"></param>
+        /// <param name="inputParameters"></param>
+        /// <param name="output"></param>
+        /// <returns></returns>
+        [DllImport(DllName)]
+        public static extern int runAlgorithm_win(int ir, int r, int led, int acThresh, int fs, int isReset,
+            float accel_x, float accel_y, float accel_z, ref AlgorithmConfiguration inputParameters, ref AlgorithmOutput output);
+    }
+#endif
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HspGuiSourceV301/HSPGui/BioZChannel.cs	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,343 @@
+/*******************************************************************************
+* Copyright (C) 2016 Maxim Integrated Products, Inc., All rights Reserved.
+* 
+* This software is protected by copyright laws of the United States and
+* of foreign countries. This material may also be protected by patent laws
+* and technology transfer regulations of the United States and of foreign
+* countries. This software is furnished under a license agreement and/or a
+* nondisclosure agreement and may only be used or reproduced in accordance
+* with the terms of those agreements. Dissemination of this information to
+* any party or parties not specified in the license agreement and/or
+* nondisclosure agreement is expressly prohibited.
+*
+* The above copyright notice and this permission notice shall be included
+* in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+* OTHER DEALINGS IN THE SOFTWARE.
+*
+* Except as contained in this notice, the name of Maxim Integrated
+* Products, Inc. shall not be used except as stated in the Maxim Integrated
+* Products, Inc. Branding Policy.
+*
+* The mere transfer of this software does not imply any licenses
+* of trade secrets, proprietary technology, copyrights, patents,
+* trademarks, maskwork rights, or any other form of intellectual
+* property whatsoever. Maxim Integrated Products, Inc. retains all
+* ownership rights.
+*******************************************************************************
+*/
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace HealthSensorPlatform
+{
+    public partial class HspForm
+    {
+        List<RegisterField> bioZChannelField = new List<RegisterField>();
+
+        RegisterField bioZSampleRateField; // Needed for dynamic changing of options
+        RegisterField bioZDlpfField;
+        RegisterField bioZCgmagField;
+
+        string[][] bioZSampleRateOptions = new string[][] 
+            { 
+                new string[] { "64 sps*", "32 sps" }, 
+                new string[] { "62.5 sps*", "31.25 sps" }, 
+                new string[] { "50 sps*", "25 sps" }, 
+                new string[] { "49.95 sps*", "24.98 sps" } 
+            };
+
+        string[][] bioZCgmagOptions = { new string[] { "Off*", "8 μA", "16 μA", "32 μA", "48 μA", "64 μA", "80 μA", "96 μA" },
+                                        new string[] { "Off*", "8 μA", "16 μA", "32 μA", "48 μA", "64 μA", "80 μA" },
+                                        new string[] { "Off*", "8 μA", "16 μA", "32 μA" },
+                                        new string[] { "Off*", "8 μA", "16 μA" },
+                                        new string[] { "Off*", "8 μA" }
+                                      };
+			
+		string[][][] bioZDlpfOptions;
+
+        void initalizeBioZConfigFields()
+        {
+			bioZDlpfOptions = new string[4][][];
+			
+			for (int i = 0; i < 4; i++)
+			{
+				bioZDlpfOptions[i] = new string[2][];
+			}
+			
+			// 32768 Hz
+			bioZDlpfOptions[0][0] = new string[] {"Bypass", "4.096 Hz*", "8.192 Hz", "16.384 Hz"};
+			bioZDlpfOptions[0][1] = new string[] {"Bypass", "4.096 Hz*", "8.192 Hz"}; //, "4.096 Hz"};
+			// 32000 Hz
+			bioZDlpfOptions[1][0] = new string[] {"Bypass", "4.0 Hz*", "8.0 Hz", "16.0 Hz"};
+			bioZDlpfOptions[1][1] = new string[] {"Bypass", "4.0 Hz*", "8.0 Hz"}; //, "4.0 Hz"};
+			// 32000 Hz
+			bioZDlpfOptions[2][0] = new string[] {"Bypass", "4.0 Hz*", "8.0 Hz", "16.0 Hz"};
+			bioZDlpfOptions[2][1] = new string[] {"Bypass", "4.0 Hz*", "8.0 Hz"}; //, "4.0 Hz"};
+			// 31968 Hz
+			bioZDlpfOptions[3][0] = new string[] {"Bypass", "3.996 Hz*", "7.992 Hz", "15.984 Hz"};
+			bioZDlpfOptions[3][1] = new string[] {"Bypass", "3.996 Hz*", "7.992 Hz"}; //, "3.996 Hz"};
+			
+            string[] aHpfOptions = { "250 Hz", "500 Hz", "1000 Hz*", "2000 Hz", "4000 Hz", "8000 Hz", "Bypass" };
+            string[] gainOptions = { "20 V/V*", "40 V/V", "80 V/V", "160 V/V" };
+            string[] dlpfOptions = { "Bypass", "4 Hz*", "8 Hz", "16 Hz" };
+            string[] dhpfOptions = { "Bypass (DC)*", "0.05 Hz", "0.50 Hz" };
+
+
+            string[] fcgenOptions = { "4*FMSTR (~128 kHz)", "2*FMSTR (~80 kHz) - offset", "FMSTR (~40 kHz) - offset", "FMSTR/2 (~18 kHz) - offset",
+                                    "FMSTR/4 (~8 kHz)", "FMSTR/8 (~4 kHz)", "FMSTR/16 (~2 kHz)", "FMSTR/32 (~1 kHz)",
+                                    "FMSTR/64 (~500 Hz)*", "FMSTR/128 (~250 Hz)", "FMSTR/256 (~125 Hz)"};
+            string[] cgmonOptions = { "Disabled*", "Enabled" };
+            string[] extRbiasOptions = { "Internal*", "External" };
+            string[] cgModeOptions = { "Unchopped w/ LPF*", "Chopped w/o LPF", "Chopped w/ LPF", "Chopped w/ Resistive CM" };
+
+            string[] enBloffOptions = { "Disabled*", "Under Range", "Over Range", "Under and Over Range" };
+            string[] hiITOptions = new string[256];
+            string[] loITOptions = new string[256];
+
+            for (int i = 0; i < hiITOptions.Length; i++)
+            {
+                hiITOptions[i] = "±2048 * " + i;
+                loITOptions[i] = "±32 * " + i;
+            }
+            hiITOptions[255] += "*";
+            loITOptions[255] += "*";
+
+            string[] phoffOptions = new string[16];
+            for (int i = 0; i < phoffOptions.Length/4; i++)
+            {
+                phoffOptions[4 * i] = (11.25 * 4 * i).ToString() + "°  (For all frequencies)";
+                phoffOptions[4 * i + 1] = (11.25 * (4 * i + 1)).ToString() + "°  (For <= 40kHz)";
+                phoffOptions[4 * i + 2] = (11.25 * (4 * i + 2)).ToString() + "°  (For <= 80kHz)";
+                phoffOptions[4 * i + 3] = (11.25 * (4 * i + 3)).ToString() + "°  (For <= 40kHz)";
+            }
+            phoffOptions[0] += "*";
+
+            string[] enDcloffOptions = { "Disabled*", "ECGP/N", "BIP/N" };
+
+            bioZSampleRateField = new RegisterField { Name = "BIOZ_RATE", Register = 0x18, Index = 23, Width = 1, Descriptions = bioZSampleRateOptions[0], Label = lblBioZSampleRate, Control = cboBioZSampleRate, Device = max30001 };
+            RegisterField aHpfField = new RegisterField { Name = "BIOZ_AHPF", Register = 0x18, Index = 20, Width = 3, Descriptions = aHpfOptions, Label = lblBioZAnalogHpf, Control = cboBioZAnalogHpf, Device = max30001 };
+            RegisterField rbiasField = new RegisterField { Name = "\nEXT_RBIAS", Register = 0x18, Index = 19, Width = 1, Descriptions = extRbiasOptions, Label = lblBioZExternalResistorBiasEnable, Control = cboBioZExternalResistorBiasEnable, Device = max30001 };
+            RegisterField gainField = new RegisterField { Name = "BIOZ_GAIN", Register = 0x18, Index = 16, Width = 2, Descriptions = gainOptions, Label = lblBioZChannelGain, Control = cboBioZChannelGain, Device = max30001 };
+            RegisterField digitalHpfField = new RegisterField { Name = "BIOZ_DHPF", Register = 0x18, Index = 14, Width = 2, Descriptions = dhpfOptions, Label = lblBioZDigitalHpf, Control = cboBioZDigitalHpf, Device = max30001 };
+            bioZDlpfField = new RegisterField { Name = "BIOZ_DLPF", Register = 0x18, Index = 12, Width = 2, Descriptions = dlpfOptions, Label = lblBioZDigitalLpf, Control = cboBioZDigitalLpf, Device = max30001 };
+            RegisterField fcgenField = new RegisterField { Name = "BIOZ_FCGEN", Register = 0x18, Index = 8, Width = 4, Descriptions = fcgenOptions, Label = lblBioZCurrentGeneratorFrequency, Control = cboBioZCurrentGeneratorFrequency, Device = max30001 };
+            RegisterField cgmonField = new RegisterField { Name = "BIOZ_CGMON", Register = 0x18, Index = 7, Width = 1, Descriptions = cgmonOptions, Label = lblBioZCurrentGeneratorMonitor, Control = cboBioZCurrentGeneratorMonitor, Device = max30001 };
+            bioZCgmagField = new RegisterField { Name = "BIOZ_CGMAG", Register = 0x18, Index = 4, Width = 3, Descriptions = bioZCgmagOptions[0], Label = lblBioZCurrentGeneratorMagnitude, Control = cboBioZCurrentGeneratorMagnitude, Device = max30001 };
+            RegisterField phoffField = new RegisterField { Name = "\nBIOZ_PHOFF", Register = 0x18, Index = 0, Width = 4, Descriptions = phoffOptions, Label = lblBioZModulationPhaseOffset, Control = cboBioZModulationPhaseOffset, Device = max30001 };
+            bioZChannelField.Add(bioZSampleRateField);
+            bioZChannelField.Add(aHpfField);
+            bioZChannelField.Add(rbiasField);
+            bioZChannelField.Add(gainField);
+            bioZChannelField.Add(digitalHpfField);
+            bioZChannelField.Add(bioZDlpfField);
+            bioZChannelField.Add(fcgenField);
+            bioZChannelField.Add(cgmonField);
+            bioZChannelField.Add(bioZCgmagField);
+            bioZChannelField.Add(phoffField);
+
+            RegisterField cgmodeField = new RegisterField { Name = "BMUX_CG_MODE", Register = 0x17, Index = 12, Width = 2, Descriptions = cgModeOptions, Label = lblBioZCurrentGeneratorMode, Control = cboBioZCurrentGeneratorMode, Device = max30001 };
+            RegisterField enDcloffField = new RegisterField { Name = "EN_BLOFF", Register = 0x10, Index = 14, Width = 2, Descriptions = enBloffOptions, Label = lblBioZDigitalLeadOffDetectionEnable, Control = cboBioZDigitalLeadOffDetectionEnable, Device = max30001 };
+            RegisterField bloffHiItField = new RegisterField { Name = "BLOFF_HI_IT", Register = 0x05, Index = 8, Width = 8, Descriptions = hiITOptions, Label = lblBioZACLeadOffOverRangeThreshold, Control = cboBioZACLeadOffOverRangeThreshold, Device = max30001 };
+            RegisterField bloffLoItField = new RegisterField { Name = "BLOFF_LO_IT", Register = 0x05, Index = 0, Width = 8, Descriptions = loITOptions, Label = lblBioZACLeadOffUnderRangeThreshold, Control = cboBioZACLeadOffUnderRangeThreshold, Device = max30001 };
+            bioZChannelField.Add(cgmodeField);
+            bioZChannelField.Add(enDcloffField);
+            bioZChannelField.Add(bloffHiItField);
+            bioZChannelField.Add(bloffLoItField);
+        }
+
+        void BioZChannelUpdateRegisters()
+        {
+            internalUpdate = true;
+            ReadComboBoxesRegisters(bioZChannelField);
+            internalUpdate = false;
+        }
+
+        private CustomControls.InitArgs.BIOZInitStart getBioZArgs()
+        {
+            CustomControls.InitArgs.BIOZInitStart biozArgs = new CustomControls.InitArgs.BIOZInitStart();
+
+            biozArgs.Openp = cboBioZBmuxOpenp.SelectedIndex;
+            biozArgs.Openn = cboBioZBmuxOpenn.SelectedIndex;
+            biozArgs.Calp_sel = cboBioZBmuxCalpSel.SelectedIndex;
+            biozArgs.Caln_sel = cboBioZBmuxCalnSel.SelectedIndex;
+            biozArgs.CG_mode = cboBioZCurrentGeneratorMode.SelectedIndex;
+            biozArgs.En_bioz = chkEnBioZ.Checked == true ? 1 : 0;
+            biozArgs.B_fit = 7; // comboBox39.SelectedIndex;
+            biozArgs.Rate = cboBioZSampleRate.SelectedIndex;
+            biozArgs.Ahpf = cboBioZAnalogHpf.SelectedIndex;
+            biozArgs.Ext_rbias = cboBioZExternalResistorBiasEnable.SelectedIndex;
+            biozArgs.Gain = cboBioZChannelGain.SelectedIndex;
+            biozArgs.Dhpf = cboBioZDigitalHpf.SelectedIndex;
+            biozArgs.Dlpf = cboBioZDigitalLpf.SelectedIndex;
+            biozArgs.Fcgen = cboBioZCurrentGeneratorFrequency.SelectedIndex;
+            biozArgs.Cgmon = cboBioZCurrentGeneratorMonitor.SelectedIndex;
+            biozArgs.Cgmag = cboBioZCurrentGeneratorMagnitude.SelectedIndex;
+            biozArgs.Phoff = cboBioZModulationPhaseOffset.SelectedIndex;
+
+            return biozArgs;
+        }
+
+        private void setBioZArgs(CustomControls.InitArgs.BIOZInitStart biozArgs)
+        {
+            cboBioZBmuxOpenp.SelectedIndex = biozArgs.Openp;
+            cboBioZBmuxOpenn.SelectedIndex = biozArgs.Openn;
+            cboBioZBmuxCalpSel.SelectedIndex = biozArgs.Calp_sel;
+            cboBioZBmuxCalnSel.SelectedIndex = biozArgs.Caln_sel;
+            cboBioZCurrentGeneratorMode.SelectedIndex = biozArgs.CG_mode;
+            //biozArgs.En_bioz = chkEnBioZ.Checked == true ? 1 : 0;
+            //biozArgs.B_fit = 7; // comboBox39.SelectedIndex;
+            cboBioZSampleRate.SelectedIndex = biozArgs.Rate;
+            cboBioZAnalogHpf.SelectedIndex = biozArgs.Ahpf;
+            cboBioZExternalResistorBiasEnable.SelectedIndex = biozArgs.Ext_rbias;
+            cboBioZChannelGain.SelectedIndex = biozArgs.Gain;
+            cboBioZDigitalHpf.SelectedIndex = biozArgs.Dhpf;
+            cboBioZDigitalLpf.SelectedIndex = biozArgs.Dlpf;
+            cboBioZCurrentGeneratorFrequency.SelectedIndex = biozArgs.Fcgen;
+            cboBioZCurrentGeneratorMonitor.SelectedIndex = biozArgs.Cgmon;
+            cboBioZCurrentGeneratorMagnitude.SelectedIndex = biozArgs.Cgmag;
+            cboBioZModulationPhaseOffset.SelectedIndex = biozArgs.Phoff;
+        }
+
+        public string BioZSettingString()
+        {
+            StringBuilder sb = new StringBuilder();
+            
+            foreach(RegisterField rf in bioZChannelField)
+            {
+                sb.Append(rf.Label.Text.Replace("\n", String.Empty));
+                sb.Append(" = ");
+                sb.Append(((MaximStyle.MaximComboBox)rf.Control).SelectedItem);
+                sb.Append(", ");
+            }
+
+            return sb.ToString();
+        }
+
+        public string EcgSettingString()
+        {
+            StringBuilder sb = new StringBuilder();
+
+            foreach (RegisterField rf in ecgChannelField)
+            {
+                sb.Append(rf.Label.Text.Replace("\n", String.Empty));
+                sb.Append(" = ");
+                sb.Append(((MaximStyle.MaximComboBox)rf.Control).SelectedItem);
+                sb.Append(", ");
+            }
+
+            return sb.ToString();
+        }
+
+
+        private void cboBioZChannelGain_SelectedIndexChanged(object sender, EventArgs e)
+        {
+            MaximStyle.MaximComboBox cbox = (MaximStyle.MaximComboBox)sender;
+
+            switch (cbox.SelectedIndex)
+            {
+                case 0:
+                    ecgView1.GainBioZ = 20;
+                    break;
+                case 1:
+                    ecgView1.GainBioZ = 40;
+                    break;
+                case 2:
+                    ecgView1.GainBioZ = 80;
+                    break;
+                case 3:
+                    ecgView1.GainBioZ = 160;
+                    break;
+            }
+        }
+
+        private void cboBioZCurrentGeneratorMagnitude_SelectedIndexChanged(object sender, EventArgs e)
+        {
+            MaximStyle.MaximComboBox cbox = (MaximStyle.MaximComboBox)sender;
+            int[] currents = { 0, 8, 16, 32, 48, 64, 80, 96 };
+
+            // Equation for Hex code to current magnitude
+            ecgView1.CurrentBioZ = currents[cbox.SelectedIndex];
+        }
+
+        private void cboBioZSampleRate_SelectedIndexChanged(object sender, EventArgs e)
+        {
+            MaximStyle.MaximComboBox cbo = (MaximStyle.MaximComboBox)sender;
+            double[][] sampleRates = new double[][]
+            {
+                new double[] {64, 32},
+                new double[] {62.5, 31.25},
+                new double[] {50, 25},
+                new double[] {49.95, 24.98}
+            };
+
+            if (connected && !internalUpdate)
+                writeComboBox(cbo);
+
+            if (cboMasterClock.SelectedIndex > -1 && cbo.SelectedIndex > -1 && cboBioZDigitalLpf.SelectedIndex > -1) // All boxes are init
+            {
+                ecgView1.SampleRateBioZ = sampleRates[cboMasterClock.SelectedIndex][cbo.SelectedIndex];
+
+                cboBioZDigitalLpf.Items.Clear();
+                bioZDlpfField.Descriptions = bioZDlpfOptions[cboMasterClock.SelectedIndex][cboBioZSampleRate.SelectedIndex];
+                bioZDlpfField.Control = cboBioZDigitalLpf; // Trigger update of descriptions
+
+                cboBioZDigitalLpf.SelectedIndex = bioZDlpfField.ReadField();
+
+            }
+        }
+
+        private void cboBioZCurrentGeneratorFrequency_SelectedIndexChanged(object sender, EventArgs e)
+        {
+            string[] currentOptions; 
+            switch (cboBioZCurrentGeneratorFrequency.SelectedIndex)
+            {
+                case 0:
+                case 1:
+                case 2:
+                case 3:
+                    currentOptions = bioZCgmagOptions[0];
+                    break;
+                case 4:
+                    currentOptions = bioZCgmagOptions[1];
+                    break;
+                case 5:
+                    currentOptions = bioZCgmagOptions[2];
+                    break;
+                case 6:
+                    currentOptions = bioZCgmagOptions[3];
+                    break;
+                default:
+                    currentOptions = bioZCgmagOptions[4];
+                    break;
+            }
+
+            if (cboBioZCurrentGeneratorMagnitude.SelectedIndex >= currentOptions.Length) // Force user selection to be valid
+            {
+                cboBioZCurrentGeneratorMagnitude.SelectedIndex = currentOptions.Length - 1;
+            }
+            bioZCgmagField.Descriptions = currentOptions;
+            bioZCgmagField.Control = cboBioZCurrentGeneratorMagnitude; // Repopulate drop down options
+        }
+
+        private void cboBioZDigitalLeadOffDetectionEnable_SelectedIndexChanged(object sender, EventArgs e)
+        {
+            MaximStyle.MaximComboBox cbo = (MaximStyle.MaximComboBox)sender;
+
+            if (cbo.SelectedIndex == 0)
+                ecgView1.EnableBioZOverUnderRange = false;
+            else
+                ecgView1.EnableBioZOverUnderRange = true;
+        }
+       
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HspGuiSourceV301/HSPGui/BioZLoad.cs	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,197 @@
+/*******************************************************************************
+* Copyright (C) 2016 Maxim Integrated Products, Inc., All rights Reserved.
+* 
+* This software is protected by copyright laws of the United States and
+* of foreign countries. This material may also be protected by patent laws
+* and technology transfer regulations of the United States and of foreign
+* countries. This software is furnished under a license agreement and/or a
+* nondisclosure agreement and may only be used or reproduced in accordance
+* with the terms of those agreements. Dissemination of this information to
+* any party or parties not specified in the license agreement and/or
+* nondisclosure agreement is expressly prohibited.
+*
+* The above copyright notice and this permission notice shall be included
+* in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+* OTHER DEALINGS IN THE SOFTWARE.
+*
+* Except as contained in this notice, the name of Maxim Integrated
+* Products, Inc. shall not be used except as stated in the Maxim Integrated
+* Products, Inc. Branding Policy.
+*
+* The mere transfer of this software does not imply any licenses
+* of trade secrets, proprietary technology, copyrights, patents,
+* trademarks, maskwork rights, or any other form of intellectual
+* property whatsoever. Maxim Integrated Products, Inc. retains all
+* ownership rights.
+*******************************************************************************
+*/
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace HealthSensorPlatform
+{
+    public partial class HspForm
+    {
+        List<RegisterField> bioZLoadField = new List<RegisterField>();
+
+        void initalizeBioZLoadFields()
+        {
+            string[] enBistOptions = { "Disabled*", "Enabled" };
+            string[] rmodOptions = { "SWMOD0 Switch Closed", "SWMOD1 Switch Closed", "SWMOD2 Switch Closed", "SWMOD3 Switch Closed", "Not Modulated*" };
+            string[] fbistOptions = { "FMSTR/2^13 (~4 Hz)*", "FMSTR/2^15 (~1 Hz)", "FMSTR/2^17 (~1/4 Hz)", "FMSTR/2^19 (~1/16 Hz)" };
+            string[] rnomOptions = { "5000 Ω*", "2500 Ω", "1667 Ω", "1250 Ω", "1000 Ω", "833 Ω", "714 Ω", "625 Ω" };
+
+            RegisterField enBistField = new RegisterField { Name = "BMUX_EN_BIST", Register = 0x17, Index = 11, Width = 1, Descriptions = enBistOptions, Label = lblBioZBmuxEnBist, Control = cboBioZBmuxEnBist, Device = max30001 };
+            RegisterField rnomField = new RegisterField { Name = "BMUX_RNOM", Register = 0x17, Index = 8, Width = 3, Descriptions = rnomOptions, Label = lblBioZBmuxRnom, Control = cboBioZBmuxRnom, Device = max30001 };
+            RegisterField rmodField = new RegisterField { Name = "BMUX_RMOD", Register = 0x17, Index = 4, Width = 3, Descriptions = rmodOptions, Label = lblBioZBmuxRmod, Control = cboBioZBmuxRmod, Device = max30001 };
+            RegisterField fbistField = new RegisterField { Name = "BMUX_FBIST", Register = 0x17, Index = 0, Width = 2, Descriptions = fbistOptions, Label = lblBioZBmuxFbist, Control = cboBioZBmuxFbist, Device = max30001 };
+
+            bioZLoadField.Add(enBistField);
+            bioZLoadField.Add(rmodField);
+            bioZLoadField.Add(fbistField);
+            bioZLoadField.Add(rnomField);
+
+            
+
+        }
+
+        private void UpdateBioZLoadSwitches()
+        {
+            //BioZ Load tab switch state reflects the BioZMux tab switch state
+
+            //Lead Off Check
+            if (picBioZLloff1.Image != null)
+                picBioZLloff1.Image.Dispose();
+            if (picBioZLloff2.Image != null)
+                picBioZLloff2.Image.Dispose();
+            if (picLoff1.Image != null)
+            {
+                picBioZLloff1.Image = Properties.Resources.bioz_loadloff1;
+            }
+            else
+            {
+                picBioZLloff1.Image = null;
+            }
+            if (picLoff2.Image != null)
+            {
+                picBioZLloff2.Image = Properties.Resources.bioz_loadloff2;
+            }
+            else
+            {
+                picBioZLloff2.Image = null;
+            }
+
+            //Lead On Check
+            if (picBioZLlon.Image != null)
+                picBioZLlon.Image.Dispose();
+            if (picLeadOn.Image != null)
+            {
+                picBioZLlon.Image = Properties.Resources.bioz_load_leadon;
+            }
+            else
+            {
+                picBioZLlon.Image = null;
+            }
+
+            //Switches
+            if (picBioZLsw1.Image != null)
+                picBioZLsw1.Image.Dispose();
+            if (picBioZLsw2.Image != null)
+                picBioZLsw2.Image.Dispose();
+            if (picBioZsw1.Image != null)
+            {
+                picBioZLsw1.Image = Properties.Resources.bioz_load_sw1;
+            }
+            else
+            {
+                picBioZLsw1.Image = null;
+            }
+            if (picBioZsw2.Image != null)
+            {
+                picBioZLsw2.Image = Properties.Resources.bioz_load_sw2;
+            }
+            else
+            {
+                picBioZLsw2.Image = null;
+            }
+
+            //Lead Bias
+            if (picBioZLlb1.Image != null)
+                picBioZLlb1.Image.Dispose();
+            if (picBioZLlb2.Image != null)
+                picBioZLlb2.Image.Dispose();
+            if (picLeadBias1.Image != null)
+            {
+                picBioZLlb1.Image = Properties.Resources.bioz_load_lb1;
+            }
+            else
+            {
+                picBioZLlb1.Image = null;
+            }
+            if (picLeadBias2.Image != null)
+            {
+                picBioZLlb2.Image = Properties.Resources.bioz_load_lb2;
+            }
+            else
+            {
+                picBioZLlb2.Image = null;
+            }
+
+            //Calibration
+            if (picBioZLcal1.Image != null)
+            {
+                picBioZLcal1.Image.Dispose();
+                picBioZLcal1.Image = Properties.Resources.bioz_load_cal1;
+            }
+            else
+            {
+                picBioZLcal1.Image = null;
+            }
+            if (picBioZLcal2.Image != null)
+            {
+                picBioZLcal2.Image.Dispose();
+                picBioZLcal2.Image = Properties.Resources.bioz_load_cal2;
+            }
+            else
+            {
+                picBioZLcal2.Image = null;
+            }
+
+            //Resistive Load Enable Logic
+            if (picBioZLresload.Image != null)
+                picBioZLresload.Image.Dispose();
+            if (cboBioZBmuxEnBist.SelectedIndex == 1)
+            {
+                picBioZLresload.Image = Properties.Resources.bioz_load_resload;
+            }
+            else
+            {
+                picBioZLresload.Image = null;
+            }
+        }
+
+        void BioZLoadUpdateRegisters()
+        {
+            internalUpdate = true;
+            ReadComboBoxesRegisters(bioZLoadField);
+            //UpdateBioZLoadSwitches(); moved to Form1.cs BioZLoad tab selection section
+            internalUpdate = false;
+        }
+
+        private void cboBioZBmuxEnBist_SelectedIndexChanged(object sender, EventArgs e)
+        {
+            UpdateBioZLoadSwitches();
+        }
+
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HspGuiSourceV301/HSPGui/BioZMux.cs	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,338 @@
+/*******************************************************************************
+* Copyright (C) 2016 Maxim Integrated Products, Inc., All rights Reserved.
+* 
+* This software is protected by copyright laws of the United States and
+* of foreign countries. This material may also be protected by patent laws
+* and technology transfer regulations of the United States and of foreign
+* countries. This software is furnished under a license agreement and/or a
+* nondisclosure agreement and may only be used or reproduced in accordance
+* with the terms of those agreements. Dissemination of this information to
+* any party or parties not specified in the license agreement and/or
+* nondisclosure agreement is expressly prohibited.
+*
+* The above copyright notice and this permission notice shall be included
+* in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+* OTHER DEALINGS IN THE SOFTWARE.
+*
+* Except as contained in this notice, the name of Maxim Integrated
+* Products, Inc. shall not be used except as stated in the Maxim Integrated
+* Products, Inc. Branding Policy.
+*
+* The mere transfer of this software does not imply any licenses
+* of trade secrets, proprietary technology, copyrights, patents,
+* trademarks, maskwork rights, or any other form of intellectual
+* property whatsoever. Maxim Integrated Products, Inc. retains all
+* ownership rights.
+*******************************************************************************
+*/
+
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Data;
+using System.Drawing;
+using System.Linq;
+using System.Text;
+using System.Windows.Forms;
+
+namespace HealthSensorPlatform
+{
+    // Code for ECG Input Mux Tab
+    public partial class HspForm
+    {
+        List<RegisterField> bioZInputMuxField = new List<RegisterField>();
+
+        // Needed for dynamic changing of options
+        RegisterField biozCalFiftyField;
+
+        void initalizeBioZInputMuxFields()
+        {
+            string[] enDcloffOptions = { "Disabled*", "ECG Ch.", "BioZ Ch." };
+            string[] dcloffIpolOptions = { "P: Pull Up, N: Pull Down*", "P: Pull Down, N: Pull Up" };
+            string[] dcloffImagOptions = { "0 nA/Disabled*", "5 nA", "10 nA", "20 nA", "50 nA", "100 nA" };
+            string[] dcloffVthOptions = { "VMID ±300 mV*", "VMID ±400 mV", "VMID ±450 mV", "VMID ±500 mV" };
+
+            string[] bmuxOpenpOptions = { "Connected", "Isolated*" };
+            string[] bmuxOpennOptions = { "Connected", "Isolated*" };
+
+            string[] enRbiasOptions = { "Disabled*", "ECG Bias", "BIOZ Bias" };
+            string[] rBiasvOptions = { "50MΩ", "100MΩ*", "200MΩ" };
+            string[] rBiaspOptions = { "Disconnected*", "Connected" };
+            string[] rBiasnOptions = { "Disconnected*", "Connected" };
+
+            string[] calEnVcalOptions = { "Disabled*", "Enabled" };
+            string[] calVmodeOptions = { "Unipolar*", "Bipolar" };
+            string[] calVmagOptions = { "0.25 mV*", "0.50 mV" };
+            string[] calFcalOptions = { "FMSTR/128 (~256Hz)", "FMSTR/512 (~64Hz)", "FMSTR/2048 (~16Hz)", "FMSTR/8192 (~4Hz)",
+                                      "FMSTR/2^15 (~1Hz)*", "FMSTR/2^17 (~1/4Hz)",  "FMSTR/2^19 (~1/16Hz)", "FMSTR/2^21 (~1/64Hz)" };
+            string[] calFiftyOptions = { "Time High", "50%*" };
+            string[] calThighOptions = new string[2048/8]; // Assume FMSTR = 32768 Hz
+            for (int i = 0; i < 2048/8; i++)
+            {
+                calThighOptions[i] = (30.52 * i * 8).ToString("F0") + " μs";
+            }
+            calThighOptions[0] += "*"; // Default
+
+            string[] calPSelOptions = { "None*", "VMID", "VCALP", "VCALN" };
+            string[] calNSelOptions = calPSelOptions;
+
+            RegisterField enDcloffField = new RegisterField { Name = "\nEN_DCLOFF", Register = 0x10, Index = 12, Width = 2, Descriptions = enDcloffOptions, Label = lblBioZEnDcloff, Control = cboBioZEnDcloff, Device = max30001 };
+            RegisterField dcloffIpolField = new RegisterField { Name = "DCLOFF_IPOL", Register = 0x10, Index = 11, Width = 1, Descriptions = dcloffIpolOptions, Label = lblBioZDcloffIpol, Control = cboBioZDcloffIpol, Device = max30001 };
+            RegisterField dcloffImagField = new RegisterField { Name = "DCLOFF_IMAG", Register = 0x10, Index = 8, Width = 3, Descriptions = dcloffImagOptions, Label = lblBioZDcloffImag, Control = cboBioZDcloffImag, Device = max30001 };
+            RegisterField dcloffVthField = new RegisterField { Name = "DCLOFF_VTH", Register = 0x10, Index = 6, Width = 2, Descriptions = dcloffVthOptions, Label = lblBioZDcloffVth, Control = cboBioZDcloffVth, Device = max30001 };
+            bioZInputMuxField.Add(enDcloffField);
+            bioZInputMuxField.Add(dcloffIpolField);
+            bioZInputMuxField.Add(dcloffImagField);
+            bioZInputMuxField.Add(dcloffVthField);
+
+            RegisterField enUlpLonField = new RegisterField { Name = "\nEN_ULP_LON", Register = 0x10, Index = 22, Width = 2, Descriptions = enDcloffOptions, Label = lblBmuxEnUlpLon, Control = cboBmuxEnUlpLon, Device = max30001 };
+            bioZInputMuxField.Add(enUlpLonField);
+
+            RegisterField bmuxOpenpField = new RegisterField { Name = "BMUX_OPENP", Register = 0x17, Index = 21, Width = 1, Descriptions = bmuxOpenpOptions, Label = lblBioZBmuxOpenp, Control = cboBioZBmuxOpenp, Device = max30001 };
+            RegisterField bmuxOpennField = new RegisterField { Name = "BMUX_OPENN", Register = 0x17, Index = 20, Width = 1, Descriptions = bmuxOpennOptions, Label = lblBioZBmuxOpenn, Control = cboBioZBmuxOpenn, Device = max30001 };
+            bioZInputMuxField.Add(bmuxOpenpField);
+            bioZInputMuxField.Add(bmuxOpennField);
+
+            RegisterField enRbiasField = new RegisterField { Name = "\nEN_RBIAS", Register = 0x10, Index = 4, Width = 2, Descriptions = enDcloffOptions, Label = lblBioZEnRbias, Control = cboBioZEnRbias, Device = max30001 };
+            RegisterField rBiasvField = new RegisterField { Name = "RBIASV", Register = 0x10, Index = 2, Width = 2, Descriptions = rBiasvOptions, Label = lblBioZRbiasv, Control = cboBioZRbiasv, Device = max30001 };
+            RegisterField rBiaspField = new RegisterField { Name = "RBIASP", Register = 0x10, Index = 1, Width = 1, Descriptions = rBiaspOptions, Label = lblBioZRbiasp, Control = cboBioZRbiasp, Device = max30001 };
+            RegisterField rBiasnField = new RegisterField { Name = "RBIASN", Register = 0x10, Index = 0, Width = 1, Descriptions = rBiasnOptions, Label = lblBioZRbiasn, Control = cboBioZRbiasn, Device = max30001 };
+            bioZInputMuxField.Add(enRbiasField);
+            bioZInputMuxField.Add(rBiasvField);
+            bioZInputMuxField.Add(rBiaspField);
+            bioZInputMuxField.Add(rBiasnField);
+
+            RegisterField calEnVcalField = new RegisterField { Name = "CAL_EN_VCAL", Register = 0x12, Index = 22, Width = 1, Descriptions = calEnVcalOptions, Label = lblBioZCalEnVcal, Control = cboBioZCalEnVcal, Device = max30001 };
+            RegisterField calVmodeField = new RegisterField { Name = "CAL_VMODE", Register = 0x12, Index = 21, Width = 1, Descriptions = calVmodeOptions, Label = lblBioZCalVMode, Control = cboBioZCalVMode, Device = max30001 };
+            RegisterField calVmagField = new RegisterField { Name = "CAL_VMAG", Register = 0x12, Index = 20, Width = 1, Descriptions = calVmagOptions, Label = lblBioZCalVmag, Control = cboBioZCalVmag, Device = max30001 };
+            RegisterField calFcalField = new RegisterField { Name = "CAL_FCAL", Register = 0x12, Index = 12, Width = 3, Descriptions = calFcalOptions, Label = lblBioZCalFcal, Control = cboBioZCalFcal, Device = max30001 };
+            biozCalFiftyField = new RegisterField { Name = "CAL_FIFTY", Register = 0x12, Index = 11, Width = 1, Descriptions = calFiftyOptions, Label = lblBioZCalFifty, Control = cboBioZCalFifty, Device = max30001 };
+            RegisterField calThighField = new RegisterField { Name = "CAL_THIGH", Register = 0x12, Index = 3, Width = 8, Descriptions = calThighOptions, Label = lblBioZCalThigh, Control = cboBioZCalThigh, Device = max30001 };
+            bioZInputMuxField.Add(calEnVcalField);
+            bioZInputMuxField.Add(calVmodeField);
+            bioZInputMuxField.Add(calVmagField);
+            bioZInputMuxField.Add(calFcalField);
+            bioZInputMuxField.Add(biozCalFiftyField);
+            bioZInputMuxField.Add(calThighField);
+
+            RegisterField calPSelField = new RegisterField { Name = "BMUX_CALP_SEL", Register = 0x17, Index = 18, Width = 2, Descriptions = calPSelOptions, Label = lblBioZBmuxCalpSel, Control = cboBioZBmuxCalnSel, Device = max30001 };
+            RegisterField calNSelField = new RegisterField { Name = "BMUX_CALN_SEL", Register = 0x17, Index = 16, Width = 2, Descriptions = calNSelOptions, Label = lblBioZBmuxCalnSel, Control = cboBioZBmuxCalpSel, Device = max30001 };
+            bioZInputMuxField.Add(calPSelField);
+            bioZInputMuxField.Add(calNSelField);
+        }
+
+        void BioZInputMuxUpdateRegisters()
+        {
+            internalUpdate = true;
+            ReadComboBoxesRegisters(bioZInputMuxField);
+            internalUpdate = false;
+        }
+
+        private void cboBioZCalFifty_SelectedIndexChanged(object sender, EventArgs e)
+        {
+            if (cboCalFifty.SelectedIndex == 1)
+            {
+                cboCalThigh.Enabled = false;
+            }
+            else
+            {
+                cboCalThigh.Enabled = true;
+            }
+        }
+
+        private void cboBioZEnDcloff_SelectedIndexChanged(object sender, EventArgs e)
+        {
+            redrawBioZMuxImage();
+        }
+
+
+        private void cboBioZDcloffIpol_SelectedIndexChanged(object sender, EventArgs e)
+        {
+            redrawBioZMuxImage();
+        }
+
+        private void cboBmuxEnUlpLon_SelectedIndexChanged(object sender, EventArgs e)
+        {
+            redrawBioZMuxImage();
+        }
+
+        private void cboBioZBmuxOpenp_SelectedIndexChanged(object sender, EventArgs e)
+        {
+            redrawBioZMuxImage();
+        }
+
+        private void cboBioZBmuxOpenn_SelectedIndexChanged(object sender, EventArgs e)
+        {
+            redrawBioZMuxImage();
+        }
+
+        private void cboBioZEnRbias_SelectedIndexChanged(object sender, EventArgs e)
+        {
+            redrawBioZMuxImage();
+        }
+
+        private void cboBioZRbiasp_SelectedIndexChanged(object sender, EventArgs e)
+        {
+            redrawBioZMuxImage();
+        }
+
+        private void cboBioZRbiasn_SelectedIndexChanged(object sender, EventArgs e)
+        {
+            redrawBioZMuxImage();
+        }
+
+        private void cboBioZBmuxCalpSel_SelectedIndexChanged(object sender, EventArgs e)
+        {
+            redrawBioZMuxImage();
+        }
+
+        private void cboBioZBmuxCalnSel_SelectedIndexChanged(object sender, EventArgs e)
+        {
+            redrawBioZMuxImage();
+        }
+
+        private void cboBioZCalEnVcal_SelectedIndexChanged(object sender, EventArgs e)
+        {
+            redrawBioZMuxImage();
+        }
+
+
+        private void redrawBioZMuxImage()
+        {
+            //Lead Off Check
+            if (picLoff1.Image != null)
+                picLoff1.Image.Dispose();
+            if (picLoff2.Image != null)
+                picLoff2.Image.Dispose();
+            if (cboBioZEnDcloff.SelectedIndex == 2)
+            {
+                
+                if (cboBioZDcloffIpol.SelectedIndex == 0)
+                {
+                    picLoff1.Image = null;
+                    picLoff2.Image = Properties.Resources.bioz_input_muxloff2;
+                }
+                else
+                {
+                    picLoff1.Image = Properties.Resources.bioz_input_muxloff1;
+                    picLoff2.Image = null;
+                }
+            }
+            else
+            {
+                picLoff1.Image = null;
+                picLoff2.Image = null;
+            }
+
+            //Lead On Check Enable
+            if (picLeadOn.Image != null)
+                picLeadOn.Image.Dispose();
+            if (cboBmuxEnUlpLon.SelectedIndex == 2)
+            {
+                picLeadOn.Image = Properties.Resources.bioz_input_muxlon;
+            }
+            else
+            {
+                picLeadOn.Image = null;
+            }
+
+            //Switches
+            if (picBioZsw1.Image != null)
+                picBioZsw1.Image.Dispose();
+            if (picBioZsw2.Image != null)
+                picBioZsw2.Image.Dispose();
+            if (cboBioZBmuxOpenp.SelectedIndex == 0) //if BIP "Connected"
+            {
+                picBioZsw1.Image = Properties.Resources.bioz_input_muxsw1;
+            }
+            else
+            {
+                picBioZsw1.Image = null;
+            }
+            if (cboBioZBmuxOpenn.SelectedIndex == 0) //if BIN "Connected"
+            {
+                picBioZsw2.Image = Properties.Resources.bioz_input_muxsw2;
+            }
+            else
+            {
+                picBioZsw2.Image = null;
+            }
+
+            //Lead Bias
+            if (picLeadBias1.Image != null)
+                picLeadBias1.Image.Dispose();
+            if (picLeadBias2.Image != null)
+                picLeadBias2.Image.Dispose();
+            if (cboBioZEnRbias.SelectedIndex == 2)
+            {
+                if (cboBioZRbiasp.SelectedIndex == 1)
+                {
+                    picLeadBias1.Image = Properties.Resources.bioz_input_muxlb1;
+                }
+                else
+                {
+                    picLeadBias1.Image = null;
+                }
+
+                if (cboBioZRbiasn.SelectedIndex == 1)
+                {
+                    picLeadBias2.Image = Properties.Resources.bioz_input_muxlb2;
+                }
+                else
+                {
+                    picLeadBias2.Image = null;
+                }  
+            }
+            else
+            {
+                picLeadBias1.Image = null;
+                picLeadBias2.Image = null;
+            }
+
+            //Calibration
+            if (picBioZCal1.Image != null)
+                picBioZCal1.Image.Dispose();
+            if (picBioZCal2.Image != null)
+                picBioZCal2.Image.Dispose();
+            if (cboBioZCalEnVcal.SelectedIndex == 1)
+            {
+                if (cboBioZBmuxCalpSel.SelectedIndex == 1 | 
+                    cboBioZBmuxCalpSel.SelectedIndex == 2 |
+                    cboBioZBmuxCalpSel.SelectedIndex == 3)
+                {
+                    picBioZCal1.Image = Properties.Resources.bioz_input_muxcal1;
+                }
+                else
+                {
+                    picBioZCal1.Image = null;
+                }
+                if (cboBioZBmuxCalnSel.SelectedIndex == 1 |
+                    cboBioZBmuxCalnSel.SelectedIndex == 2 |
+                    cboBioZBmuxCalnSel.SelectedIndex == 3)
+                {
+                    picBioZCal2.Image = Properties.Resources.bioz_input_muxcal2;
+                }
+                else
+                {
+                    picBioZCal2.Image = null;
+                }
+            }
+            else
+            {
+                picBioZCal1.Image = null;
+                picBioZCal2.Image = null;
+            }
+
+
+        }
+
+
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HspGuiSourceV301/HSPGui/CustomControls/DoubleBufferTableLayoutPanel.Designer.cs	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,36 @@
+namespace HealthSensorPlatform.CustomControls
+{
+    partial class DoubleBufferTableLayoutPanel
+    {
+        /// <summary> 
+        /// Required designer variable.
+        /// </summary>
+        private System.ComponentModel.IContainer components = null;
+
+        /// <summary> 
+        /// Clean up any resources being used.
+        /// </summary>
+        /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
+        protected override void Dispose(bool disposing)
+        {
+            if (disposing && (components != null))
+            {
+                components.Dispose();
+            }
+            base.Dispose(disposing);
+        }
+
+        #region Component Designer generated code
+
+        /// <summary> 
+        /// Required method for Designer support - do not modify 
+        /// the contents of this method with the code editor.
+        /// </summary>
+        private void InitializeComponent()
+        {
+            components = new System.ComponentModel.Container();
+        }
+
+        #endregion
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HspGuiSourceV301/HSPGui/CustomControls/DoubleBufferTableLayoutPanel.cs	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,36 @@
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Drawing;
+using System.Data;
+using System.Linq;
+using System.Text;
+using System.Windows.Forms;
+
+namespace HealthSensorPlatform.CustomControls
+{
+    public partial class DoubleBufferTableLayoutPanel : TableLayoutPanel 
+    {
+        public DoubleBufferTableLayoutPanel()
+        {
+            InitializeComponent();
+        }
+
+        public DoubleBufferTableLayoutPanel(IContainer container)
+        {
+            container.Add(this);
+            InitializeComponent();
+        }
+
+        /// <summary>
+        /// Double buffer
+        /// </summary>
+        [Description("Double buffer")]
+        [DefaultValue(true)]
+        public bool dBuffer
+        {
+            get { return this.DoubleBuffered; }
+            set { this.DoubleBuffered = value; }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HspGuiSourceV301/HSPGui/CustomControls/EcgView.Designer.cs	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,561 @@
+namespace HealthSensorPlatform.CustomControls
+{
+    partial class EcgView
+    {
+        /// <summary> 
+        /// Required designer variable.
+        /// </summary>
+        private System.ComponentModel.IContainer components = null;
+
+        /// <summary> 
+        /// Clean up any resources being used.
+        /// </summary>
+        /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
+        protected override void Dispose(bool disposing)
+        {
+            if (disposing && (components != null))
+            {
+                components.Dispose();
+            }
+            base.Dispose(disposing);
+        }
+
+        #region Component Designer generated code
+
+        /// <summary> 
+        /// Required method for Designer support - do not modify 
+        /// the contents of this method with the code editor.
+        /// </summary>
+        private void InitializeComponent()
+        {
+            this.components = new System.ComponentModel.Container();
+            System.Windows.Forms.DataVisualization.Charting.ChartArea chartArea1 = new System.Windows.Forms.DataVisualization.Charting.ChartArea();
+            System.Windows.Forms.DataVisualization.Charting.Series series1 = new System.Windows.Forms.DataVisualization.Charting.Series();
+            System.Windows.Forms.DataVisualization.Charting.Title title1 = new System.Windows.Forms.DataVisualization.Charting.Title();
+            System.Windows.Forms.DataVisualization.Charting.ChartArea chartArea2 = new System.Windows.Forms.DataVisualization.Charting.ChartArea();
+            System.Windows.Forms.DataVisualization.Charting.Series series2 = new System.Windows.Forms.DataVisualization.Charting.Series();
+            System.Windows.Forms.DataVisualization.Charting.Title title2 = new System.Windows.Forms.DataVisualization.Charting.Title();
+            System.Windows.Forms.DataVisualization.Charting.ChartArea chartArea3 = new System.Windows.Forms.DataVisualization.Charting.ChartArea();
+            System.Windows.Forms.DataVisualization.Charting.Series series3 = new System.Windows.Forms.DataVisualization.Charting.Series();
+            System.Windows.Forms.DataVisualization.Charting.Title title3 = new System.Windows.Forms.DataVisualization.Charting.Title();
+            System.Windows.Forms.DataVisualization.Charting.ChartArea chartArea4 = new System.Windows.Forms.DataVisualization.Charting.ChartArea();
+            System.Windows.Forms.DataVisualization.Charting.Series series4 = new System.Windows.Forms.DataVisualization.Charting.Series();
+            System.Windows.Forms.DataVisualization.Charting.Series series5 = new System.Windows.Forms.DataVisualization.Charting.Series();
+            System.Windows.Forms.DataVisualization.Charting.Series series6 = new System.Windows.Forms.DataVisualization.Charting.Series();
+            System.Windows.Forms.DataVisualization.Charting.Series series7 = new System.Windows.Forms.DataVisualization.Charting.Series();
+            System.Windows.Forms.DataVisualization.Charting.Title title4 = new System.Windows.Forms.DataVisualization.Charting.Title();
+            this.chartPace = new System.Windows.Forms.DataVisualization.Charting.Chart();
+            this.chartRtoR = new System.Windows.Forms.DataVisualization.Charting.Chart();
+            this.btnMonitor = new MaximStyle.MaximButton();
+            this.btnStartTest = new System.Windows.Forms.Button();
+            this.grpBxBioZOverUnderRange = new MaximStyle.MaximGroupBox();
+            this.lblBioZACUnder = new System.Windows.Forms.Label();
+            this.lblBioZACOver = new System.Windows.Forms.Label();
+            this.maximGroupBox3 = new MaximStyle.MaximGroupBox();
+            this.label70 = new System.Windows.Forms.Label();
+            this.label69 = new System.Windows.Forms.Label();
+            this.grpBxDCLeadOff = new MaximStyle.MaximGroupBox();
+            this.lblLdoffNl = new System.Windows.Forms.Label();
+            this.lblLdoffNh = new System.Windows.Forms.Label();
+            this.lblLdoffPl = new System.Windows.Forms.Label();
+            this.lblLdoffPh = new System.Windows.Forms.Label();
+            this.maximGroupBox5 = new MaximStyle.MaximGroupBox();
+            this.label76 = new System.Windows.Forms.Label();
+            this.label75 = new System.Windows.Forms.Label();
+            this.tableLayoutPanelCharts = new System.Windows.Forms.TableLayoutPanel();
+            this.chartBioz = new System.Windows.Forms.DataVisualization.Charting.Chart();
+            this.chartECG = new System.Windows.Forms.DataVisualization.Charting.Chart();
+            this.flowLayoutPanelInterruptsControls = new System.Windows.Forms.FlowLayoutPanel();
+            this.grpBxHeartRate = new MaximStyle.MaximGroupBox();
+            this.lblHeartRateAverage10 = new System.Windows.Forms.Label();
+            this.lblHeartRateBeatToBeat = new System.Windows.Forms.Label();
+            this.label1 = new System.Windows.Forms.Label();
+            this.label2 = new System.Windows.Forms.Label();
+            this.panel1 = new System.Windows.Forms.Panel();
+            this.button1 = new System.Windows.Forms.Button();
+            this.timer1 = new System.Windows.Forms.Timer(this.components);
+            ((System.ComponentModel.ISupportInitialize)(this.chartPace)).BeginInit();
+            ((System.ComponentModel.ISupportInitialize)(this.chartRtoR)).BeginInit();
+            this.grpBxBioZOverUnderRange.SuspendLayout();
+            this.maximGroupBox3.SuspendLayout();
+            this.grpBxDCLeadOff.SuspendLayout();
+            this.maximGroupBox5.SuspendLayout();
+            this.tableLayoutPanelCharts.SuspendLayout();
+            ((System.ComponentModel.ISupportInitialize)(this.chartBioz)).BeginInit();
+            ((System.ComponentModel.ISupportInitialize)(this.chartECG)).BeginInit();
+            this.flowLayoutPanelInterruptsControls.SuspendLayout();
+            this.grpBxHeartRate.SuspendLayout();
+            this.panel1.SuspendLayout();
+            this.SuspendLayout();
+            // 
+            // chartPace
+            // 
+            chartArea1.AxisY.Title = "Pace (μs)";
+            chartArea1.Name = "ChartArea";
+            this.chartPace.ChartAreas.Add(chartArea1);
+            this.chartPace.Location = new System.Drawing.Point(3, 190);
+            this.chartPace.Name = "chartPace";
+            series1.ChartArea = "ChartArea";
+            series1.ChartType = System.Windows.Forms.DataVisualization.Charting.SeriesChartType.Line;
+            series1.Color = System.Drawing.Color.DarkRed;
+            series1.MarkerSize = 1;
+            series1.Name = "Series";
+            series1.XValueType = System.Windows.Forms.DataVisualization.Charting.ChartValueType.UInt32;
+            series1.YValueType = System.Windows.Forms.DataVisualization.Charting.ChartValueType.Int32;
+            this.chartPace.Series.Add(series1);
+            this.chartPace.Size = new System.Drawing.Size(400, 190);
+            this.chartPace.TabIndex = 35;
+            this.chartPace.Text = "chart1";
+            title1.Name = "Title1";
+            title1.Text = "Red";
+            title1.Visible = false;
+            this.chartPace.Titles.Add(title1);
+            // 
+            // chartRtoR
+            // 
+            chartArea2.AxisY.Title = "R-to-R (ms)";
+            chartArea2.Name = "ChartArea";
+            this.chartRtoR.ChartAreas.Add(chartArea2);
+            this.chartRtoR.Location = new System.Drawing.Point(415, 190);
+            this.chartRtoR.Name = "chartRtoR";
+            series2.ChartArea = "ChartArea";
+            series2.ChartType = System.Windows.Forms.DataVisualization.Charting.SeriesChartType.Line;
+            series2.Color = System.Drawing.Color.DarkRed;
+            series2.MarkerSize = 1;
+            series2.Name = "Series";
+            series2.XValueType = System.Windows.Forms.DataVisualization.Charting.ChartValueType.UInt32;
+            series2.YValueType = System.Windows.Forms.DataVisualization.Charting.ChartValueType.Int32;
+            this.chartRtoR.Series.Add(series2);
+            this.chartRtoR.Size = new System.Drawing.Size(400, 190);
+            this.chartRtoR.TabIndex = 37;
+            this.chartRtoR.Text = "chart3";
+            title2.Name = "Title1";
+            title2.Text = "Red";
+            title2.Visible = false;
+            this.chartRtoR.Titles.Add(title2);
+            // 
+            // btnMonitor
+            // 
+            this.btnMonitor.Location = new System.Drawing.Point(60, 25);
+            this.btnMonitor.Name = "btnMonitor";
+            this.btnMonitor.Size = new System.Drawing.Size(111, 23);
+            this.btnMonitor.TabIndex = 66;
+            this.btnMonitor.Text = "Start Monitor";
+            this.btnMonitor.UseVisualStyleBackColor = true;
+            this.btnMonitor.Click += new System.EventHandler(this.btnMonitor_Click);
+            // 
+            // btnStartTest
+            // 
+            this.btnStartTest.Location = new System.Drawing.Point(692, 625);
+            this.btnStartTest.Name = "btnStartTest";
+            this.btnStartTest.Size = new System.Drawing.Size(111, 23);
+            this.btnStartTest.TabIndex = 67;
+            this.btnStartTest.Text = "Start Test";
+            this.btnStartTest.UseVisualStyleBackColor = true;
+            this.btnStartTest.Click += new System.EventHandler(this.btnStartTest_Click);
+            // 
+            // grpBxBioZOverUnderRange
+            // 
+            this.grpBxBioZOverUnderRange.BackgroundColor = System.Drawing.Color.White;
+            this.grpBxBioZOverUnderRange.Controls.Add(this.lblBioZACUnder);
+            this.grpBxBioZOverUnderRange.Controls.Add(this.lblBioZACOver);
+            this.grpBxBioZOverUnderRange.Dock = System.Windows.Forms.DockStyle.Left;
+            this.grpBxBioZOverUnderRange.Location = new System.Drawing.Point(3, 3);
+            this.grpBxBioZOverUnderRange.Name = "grpBxBioZOverUnderRange";
+            this.grpBxBioZOverUnderRange.Size = new System.Drawing.Size(140, 72);
+            this.grpBxBioZOverUnderRange.TabIndex = 71;
+            this.grpBxBioZOverUnderRange.TabStop = false;
+            this.grpBxBioZOverUnderRange.Text = "BioZ";
+            // 
+            // lblBioZACUnder
+            // 
+            this.lblBioZACUnder.AutoSize = true;
+            this.lblBioZACUnder.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+            this.lblBioZACUnder.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(153)))), ((int)(((byte)(198)))), ((int)(((byte)(76)))));
+            this.lblBioZACUnder.Location = new System.Drawing.Point(9, 48);
+            this.lblBioZACUnder.Name = "lblBioZACUnder";
+            this.lblBioZACUnder.Size = new System.Drawing.Size(115, 13);
+            this.lblBioZACUnder.TabIndex = 1;
+            this.lblBioZACUnder.Text = "Code Under Range";
+            // 
+            // lblBioZACOver
+            // 
+            this.lblBioZACOver.AutoSize = true;
+            this.lblBioZACOver.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+            this.lblBioZACOver.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(153)))), ((int)(((byte)(198)))), ((int)(((byte)(76)))));
+            this.lblBioZACOver.Location = new System.Drawing.Point(9, 29);
+            this.lblBioZACOver.Name = "lblBioZACOver";
+            this.lblBioZACOver.Size = new System.Drawing.Size(108, 13);
+            this.lblBioZACOver.TabIndex = 0;
+            this.lblBioZACOver.Text = "Code Over Range";
+            // 
+            // maximGroupBox3
+            // 
+            this.maximGroupBox3.BackgroundColor = System.Drawing.Color.White;
+            this.maximGroupBox3.Controls.Add(this.label70);
+            this.maximGroupBox3.Controls.Add(this.label69);
+            this.maximGroupBox3.Enabled = false;
+            this.maximGroupBox3.Location = new System.Drawing.Point(152, 597);
+            this.maximGroupBox3.Name = "maximGroupBox3";
+            this.maximGroupBox3.Size = new System.Drawing.Size(148, 55);
+            this.maximGroupBox3.TabIndex = 72;
+            this.maximGroupBox3.TabStop = false;
+            // 
+            // label70
+            // 
+            this.label70.AutoSize = true;
+            this.label70.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+            this.label70.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(153)))), ((int)(((byte)(198)))), ((int)(((byte)(76)))));
+            this.label70.Location = new System.Drawing.Point(13, 33);
+            this.label70.Name = "label70";
+            this.label70.Size = new System.Drawing.Size(125, 13);
+            this.label70.TabIndex = 2;
+            this.label70.Text = "BioZ DRVN Lead Off";
+            // 
+            // label69
+            // 
+            this.label69.AutoSize = true;
+            this.label69.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+            this.label69.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(153)))), ((int)(((byte)(198)))), ((int)(((byte)(76)))));
+            this.label69.Location = new System.Drawing.Point(13, 14);
+            this.label69.Name = "label69";
+            this.label69.Size = new System.Drawing.Size(124, 13);
+            this.label69.TabIndex = 1;
+            this.label69.Text = "BioZ DRVP Lead Off";
+            // 
+            // grpBxDCLeadOff
+            // 
+            this.grpBxDCLeadOff.BackgroundColor = System.Drawing.Color.White;
+            this.grpBxDCLeadOff.Controls.Add(this.lblLdoffNl);
+            this.grpBxDCLeadOff.Controls.Add(this.lblLdoffNh);
+            this.grpBxDCLeadOff.Controls.Add(this.lblLdoffPl);
+            this.grpBxDCLeadOff.Controls.Add(this.lblLdoffPh);
+            this.grpBxDCLeadOff.Location = new System.Drawing.Point(149, 3);
+            this.grpBxDCLeadOff.Name = "grpBxDCLeadOff";
+            this.grpBxDCLeadOff.Size = new System.Drawing.Size(254, 72);
+            this.grpBxDCLeadOff.TabIndex = 73;
+            this.grpBxDCLeadOff.TabStop = false;
+            this.grpBxDCLeadOff.Text = "DC Lead Off";
+            // 
+            // lblLdoffNl
+            // 
+            this.lblLdoffNl.AutoSize = true;
+            this.lblLdoffNl.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+            this.lblLdoffNl.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(153)))), ((int)(((byte)(198)))), ((int)(((byte)(76)))));
+            this.lblLdoffNl.Location = new System.Drawing.Point(134, 47);
+            this.lblLdoffNl.Name = "lblLdoffNl";
+            this.lblLdoffNl.Size = new System.Drawing.Size(95, 13);
+            this.lblLdoffNl.TabIndex = 3;
+            this.lblLdoffNl.Text = "ECGN/BIN Low";
+            // 
+            // lblLdoffNh
+            // 
+            this.lblLdoffNh.AutoSize = true;
+            this.lblLdoffNh.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+            this.lblLdoffNh.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(153)))), ((int)(((byte)(198)))), ((int)(((byte)(76)))));
+            this.lblLdoffNh.Location = new System.Drawing.Point(134, 28);
+            this.lblLdoffNh.Name = "lblLdoffNh";
+            this.lblLdoffNh.Size = new System.Drawing.Size(98, 13);
+            this.lblLdoffNh.TabIndex = 2;
+            this.lblLdoffNh.Text = "ECGN/BIN High";
+            // 
+            // lblLdoffPl
+            // 
+            this.lblLdoffPl.AutoSize = true;
+            this.lblLdoffPl.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+            this.lblLdoffPl.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(153)))), ((int)(((byte)(198)))), ((int)(((byte)(76)))));
+            this.lblLdoffPl.Location = new System.Drawing.Point(15, 47);
+            this.lblLdoffPl.Name = "lblLdoffPl";
+            this.lblLdoffPl.Size = new System.Drawing.Size(93, 13);
+            this.lblLdoffPl.TabIndex = 1;
+            this.lblLdoffPl.Text = "ECGP/BIP Low";
+            // 
+            // lblLdoffPh
+            // 
+            this.lblLdoffPh.AutoSize = true;
+            this.lblLdoffPh.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+            this.lblLdoffPh.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(153)))), ((int)(((byte)(198)))), ((int)(((byte)(76)))));
+            this.lblLdoffPh.Location = new System.Drawing.Point(15, 28);
+            this.lblLdoffPh.Name = "lblLdoffPh";
+            this.lblLdoffPh.Size = new System.Drawing.Size(96, 13);
+            this.lblLdoffPh.TabIndex = 0;
+            this.lblLdoffPh.Text = "ECGP/BIP High";
+            // 
+            // maximGroupBox5
+            // 
+            this.maximGroupBox5.BackgroundColor = System.Drawing.Color.White;
+            this.maximGroupBox5.Controls.Add(this.label76);
+            this.maximGroupBox5.Controls.Add(this.label75);
+            this.maximGroupBox5.Enabled = false;
+            this.maximGroupBox5.Location = new System.Drawing.Point(13, 597);
+            this.maximGroupBox5.Name = "maximGroupBox5";
+            this.maximGroupBox5.Size = new System.Drawing.Size(124, 55);
+            this.maximGroupBox5.TabIndex = 74;
+            this.maximGroupBox5.TabStop = false;
+            // 
+            // label76
+            // 
+            this.label76.AutoSize = true;
+            this.label76.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+            this.label76.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(153)))), ((int)(((byte)(198)))), ((int)(((byte)(76)))));
+            this.label76.Location = new System.Drawing.Point(12, 33);
+            this.label76.Name = "label76";
+            this.label76.Size = new System.Drawing.Size(87, 13);
+            this.label76.TabIndex = 4;
+            this.label76.Text = "PLL Unlocked";
+            // 
+            // label75
+            // 
+            this.label75.AutoSize = true;
+            this.label75.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+            this.label75.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(153)))), ((int)(((byte)(198)))), ((int)(((byte)(76)))));
+            this.label75.Location = new System.Drawing.Point(12, 14);
+            this.label75.Name = "label75";
+            this.label75.Size = new System.Drawing.Size(118, 13);
+            this.label75.TabIndex = 3;
+            this.label75.Text = "ECG Fast Recovery";
+            // 
+            // tableLayoutPanelCharts
+            // 
+            this.tableLayoutPanelCharts.ColumnCount = 1;
+            this.tableLayoutPanelCharts.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F));
+            this.tableLayoutPanelCharts.Controls.Add(this.chartBioz, 0, 1);
+            this.tableLayoutPanelCharts.Controls.Add(this.chartECG, 0, 0);
+            this.tableLayoutPanelCharts.Dock = System.Windows.Forms.DockStyle.Fill;
+            this.tableLayoutPanelCharts.Location = new System.Drawing.Point(0, 0);
+            this.tableLayoutPanelCharts.Name = "tableLayoutPanelCharts";
+            this.tableLayoutPanelCharts.RowCount = 2;
+            this.tableLayoutPanelCharts.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F));
+            this.tableLayoutPanelCharts.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 0F));
+            this.tableLayoutPanelCharts.Size = new System.Drawing.Size(831, 464);
+            this.tableLayoutPanelCharts.TabIndex = 77;
+            // 
+            // chartBioz
+            // 
+            chartArea3.AxisX.Title = "Seconds (s)";
+            chartArea3.AxisY.Title = "Bioz (Ohm)";
+            chartArea3.Name = "ChartArea";
+            this.chartBioz.ChartAreas.Add(chartArea3);
+            this.chartBioz.Dock = System.Windows.Forms.DockStyle.Fill;
+            this.chartBioz.Location = new System.Drawing.Point(3, 467);
+            this.chartBioz.Name = "chartBioz";
+            series3.ChartArea = "ChartArea";
+            series3.ChartType = System.Windows.Forms.DataVisualization.Charting.SeriesChartType.Line;
+            series3.Color = System.Drawing.Color.FromArgb(((int)(((byte)(110)))), ((int)(((byte)(37)))), ((int)(((byte)(133)))));
+            series3.MarkerSize = 1;
+            series3.Name = "Series";
+            series3.XValueType = System.Windows.Forms.DataVisualization.Charting.ChartValueType.UInt32;
+            series3.YValueType = System.Windows.Forms.DataVisualization.Charting.ChartValueType.Int32;
+            this.chartBioz.Series.Add(series3);
+            this.chartBioz.Size = new System.Drawing.Size(825, 1);
+            this.chartBioz.TabIndex = 39;
+            this.chartBioz.Text = "chart2";
+            title3.Name = "Title1";
+            title3.Text = "Red";
+            title3.Visible = false;
+            this.chartBioz.Titles.Add(title3);
+            // 
+            // chartECG
+            // 
+            chartArea4.AxisX.Title = "Seconds (s)";
+            chartArea4.AxisY.Title = "ECG (mV)";
+            chartArea4.Name = "ChartArea";
+            this.chartECG.ChartAreas.Add(chartArea4);
+            this.chartECG.Dock = System.Windows.Forms.DockStyle.Fill;
+            this.chartECG.Location = new System.Drawing.Point(3, 3);
+            this.chartECG.Name = "chartECG";
+            series4.ChartArea = "ChartArea";
+            series4.ChartType = System.Windows.Forms.DataVisualization.Charting.SeriesChartType.Line;
+            series4.Color = System.Drawing.Color.FromArgb(((int)(((byte)(110)))), ((int)(((byte)(37)))), ((int)(((byte)(133)))));
+            series4.MarkerSize = 1;
+            series4.Name = "Series";
+            series4.XValueType = System.Windows.Forms.DataVisualization.Charting.ChartValueType.UInt32;
+            series4.YValueType = System.Windows.Forms.DataVisualization.Charting.ChartValueType.Int32;
+            series5.ChartArea = "ChartArea";
+            series5.ChartType = System.Windows.Forms.DataVisualization.Charting.SeriesChartType.FastPoint;
+            series5.Color = System.Drawing.Color.Transparent;
+            series5.MarkerBorderColor = System.Drawing.Color.FromArgb(((int)(((byte)(213)))), ((int)(((byte)(81)))), ((int)(((byte)(29)))));
+            series5.MarkerBorderWidth = 2;
+            series5.MarkerColor = System.Drawing.Color.Transparent;
+            series5.MarkerSize = 10;
+            series5.MarkerStyle = System.Windows.Forms.DataVisualization.Charting.MarkerStyle.Circle;
+            series5.Name = "SeriesRToR";
+            series6.ChartArea = "ChartArea";
+            series6.ChartType = System.Windows.Forms.DataVisualization.Charting.SeriesChartType.Point;
+            series6.MarkerImage = "PaceRisingImage";
+            series6.MarkerImageTransparentColor = System.Drawing.Color.White;
+            series6.Name = "SeriesPace";
+            series7.ChartArea = "ChartArea";
+            series7.ChartType = System.Windows.Forms.DataVisualization.Charting.SeriesChartType.Point;
+            series7.MarkerImage = "PaceFallingImage";
+            series7.MarkerImageTransparentColor = System.Drawing.Color.White;
+            series7.Name = "SeriesPaceFalling";
+            this.chartECG.Series.Add(series4);
+            this.chartECG.Series.Add(series5);
+            this.chartECG.Series.Add(series6);
+            this.chartECG.Series.Add(series7);
+            this.chartECG.Size = new System.Drawing.Size(825, 458);
+            this.chartECG.TabIndex = 37;
+            this.chartECG.Text = "chartECG";
+            title4.Name = "Title1";
+            title4.Text = "Red";
+            title4.Visible = false;
+            this.chartECG.Titles.Add(title4);
+            // 
+            // flowLayoutPanelInterruptsControls
+            // 
+            this.flowLayoutPanelInterruptsControls.BackColor = System.Drawing.Color.White;
+            this.flowLayoutPanelInterruptsControls.Controls.Add(this.grpBxBioZOverUnderRange);
+            this.flowLayoutPanelInterruptsControls.Controls.Add(this.grpBxDCLeadOff);
+            this.flowLayoutPanelInterruptsControls.Controls.Add(this.grpBxHeartRate);
+            this.flowLayoutPanelInterruptsControls.Controls.Add(this.panel1);
+            this.flowLayoutPanelInterruptsControls.Controls.Add(this.button1);
+            this.flowLayoutPanelInterruptsControls.Dock = System.Windows.Forms.DockStyle.Bottom;
+            this.flowLayoutPanelInterruptsControls.Location = new System.Drawing.Point(0, 464);
+            this.flowLayoutPanelInterruptsControls.Name = "flowLayoutPanelInterruptsControls";
+            this.flowLayoutPanelInterruptsControls.Size = new System.Drawing.Size(831, 81);
+            this.flowLayoutPanelInterruptsControls.TabIndex = 78;
+            // 
+            // grpBxHeartRate
+            // 
+            this.grpBxHeartRate.BackgroundColor = System.Drawing.Color.White;
+            this.grpBxHeartRate.Controls.Add(this.lblHeartRateAverage10);
+            this.grpBxHeartRate.Controls.Add(this.lblHeartRateBeatToBeat);
+            this.grpBxHeartRate.Controls.Add(this.label1);
+            this.grpBxHeartRate.Controls.Add(this.label2);
+            this.grpBxHeartRate.Location = new System.Drawing.Point(409, 3);
+            this.grpBxHeartRate.Name = "grpBxHeartRate";
+            this.grpBxHeartRate.Size = new System.Drawing.Size(166, 72);
+            this.grpBxHeartRate.TabIndex = 78;
+            this.grpBxHeartRate.TabStop = false;
+            this.grpBxHeartRate.Text = "Heart Rate (from R-to-R)";
+            // 
+            // lblHeartRateAverage10
+            // 
+            this.lblHeartRateAverage10.AutoSize = true;
+            this.lblHeartRateAverage10.Location = new System.Drawing.Point(113, 48);
+            this.lblHeartRateAverage10.Name = "lblHeartRateAverage10";
+            this.lblHeartRateAverage10.Size = new System.Drawing.Size(13, 13);
+            this.lblHeartRateAverage10.TabIndex = 3;
+            this.lblHeartRateAverage10.Text = "--";
+            // 
+            // lblHeartRateBeatToBeat
+            // 
+            this.lblHeartRateBeatToBeat.AutoSize = true;
+            this.lblHeartRateBeatToBeat.Location = new System.Drawing.Point(113, 29);
+            this.lblHeartRateBeatToBeat.Name = "lblHeartRateBeatToBeat";
+            this.lblHeartRateBeatToBeat.Size = new System.Drawing.Size(13, 13);
+            this.lblHeartRateBeatToBeat.TabIndex = 2;
+            this.lblHeartRateBeatToBeat.Text = "--";
+            // 
+            // label1
+            // 
+            this.label1.AutoSize = true;
+            this.label1.Location = new System.Drawing.Point(6, 29);
+            this.label1.Name = "label1";
+            this.label1.Size = new System.Drawing.Size(101, 13);
+            this.label1.TabIndex = 0;
+            this.label1.Text = "Beat to Beat (bpm): ";
+            // 
+            // label2
+            // 
+            this.label2.AutoSize = true;
+            this.label2.Location = new System.Drawing.Point(6, 48);
+            this.label2.Name = "label2";
+            this.label2.Size = new System.Drawing.Size(94, 13);
+            this.label2.TabIndex = 1;
+            this.label2.Text = "Average 10 (bpm):";
+            // 
+            // panel1
+            // 
+            this.panel1.Controls.Add(this.btnMonitor);
+            this.panel1.Dock = System.Windows.Forms.DockStyle.Right;
+            this.panel1.Location = new System.Drawing.Point(581, 3);
+            this.panel1.Name = "panel1";
+            this.panel1.Size = new System.Drawing.Size(220, 72);
+            this.panel1.TabIndex = 74;
+            // 
+            // button1
+            // 
+            this.button1.Location = new System.Drawing.Point(3, 81);
+            this.button1.Name = "button1";
+            this.button1.Size = new System.Drawing.Size(75, 23);
+            this.button1.TabIndex = 75;
+            this.button1.Text = "button1";
+            this.button1.UseVisualStyleBackColor = true;
+            this.button1.Visible = false;
+            this.button1.Click += new System.EventHandler(this.button1_Click);
+            // 
+            // timer1
+            // 
+            this.timer1.Interval = 200;
+            this.timer1.Tick += new System.EventHandler(this.timer1_Tick);
+            // 
+            // EcgView
+            // 
+            this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
+            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+            this.Controls.Add(this.tableLayoutPanelCharts);
+            this.Controls.Add(this.flowLayoutPanelInterruptsControls);
+            this.Controls.Add(this.maximGroupBox5);
+            this.Controls.Add(this.maximGroupBox3);
+            this.Controls.Add(this.btnStartTest);
+            this.Controls.Add(this.chartRtoR);
+            this.Controls.Add(this.chartPace);
+            this.Name = "EcgView";
+            this.Size = new System.Drawing.Size(831, 545);
+            this.Load += new System.EventHandler(this.EcgView_Load);
+            ((System.ComponentModel.ISupportInitialize)(this.chartPace)).EndInit();
+            ((System.ComponentModel.ISupportInitialize)(this.chartRtoR)).EndInit();
+            this.grpBxBioZOverUnderRange.ResumeLayout(false);
+            this.grpBxBioZOverUnderRange.PerformLayout();
+            this.maximGroupBox3.ResumeLayout(false);
+            this.maximGroupBox3.PerformLayout();
+            this.grpBxDCLeadOff.ResumeLayout(false);
+            this.grpBxDCLeadOff.PerformLayout();
+            this.maximGroupBox5.ResumeLayout(false);
+            this.maximGroupBox5.PerformLayout();
+            this.tableLayoutPanelCharts.ResumeLayout(false);
+            ((System.ComponentModel.ISupportInitialize)(this.chartBioz)).EndInit();
+            ((System.ComponentModel.ISupportInitialize)(this.chartECG)).EndInit();
+            this.flowLayoutPanelInterruptsControls.ResumeLayout(false);
+            this.grpBxHeartRate.ResumeLayout(false);
+            this.grpBxHeartRate.PerformLayout();
+            this.panel1.ResumeLayout(false);
+            this.ResumeLayout(false);
+
+        }
+
+        #endregion
+        private System.Windows.Forms.DataVisualization.Charting.Chart chartPace;
+        private System.Windows.Forms.DataVisualization.Charting.Chart chartRtoR;
+        private MaximStyle.MaximButton btnMonitor;
+        private System.Windows.Forms.Button btnStartTest;
+        private MaximStyle.MaximGroupBox grpBxBioZOverUnderRange;
+        private System.Windows.Forms.Label lblBioZACUnder;
+        private System.Windows.Forms.Label lblBioZACOver;
+        private MaximStyle.MaximGroupBox maximGroupBox3;
+        private MaximStyle.MaximGroupBox grpBxDCLeadOff;
+        private MaximStyle.MaximGroupBox maximGroupBox5;
+        private System.Windows.Forms.Label label70;
+        private System.Windows.Forms.Label label69;
+        private System.Windows.Forms.Label lblLdoffNl;
+        private System.Windows.Forms.Label lblLdoffNh;
+        private System.Windows.Forms.Label lblLdoffPl;
+        private System.Windows.Forms.Label lblLdoffPh;
+        private System.Windows.Forms.Label label76;
+        private System.Windows.Forms.Label label75;
+        private System.Windows.Forms.TableLayoutPanel tableLayoutPanelCharts;
+        private System.Windows.Forms.FlowLayoutPanel flowLayoutPanelInterruptsControls;
+        private System.Windows.Forms.Panel panel1;
+        private System.Windows.Forms.Button button1;
+        private System.Windows.Forms.Timer timer1;
+        private System.Windows.Forms.DataVisualization.Charting.Chart chartBioz;
+        private System.Windows.Forms.DataVisualization.Charting.Chart chartECG;
+        private System.Windows.Forms.Label label2;
+        private System.Windows.Forms.Label label1;
+        private MaximStyle.MaximGroupBox grpBxHeartRate;
+        private System.Windows.Forms.Label lblHeartRateAverage10;
+        private System.Windows.Forms.Label lblHeartRateBeatToBeat;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HspGuiSourceV301/HSPGui/CustomControls/EcgView.cs	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,1734 @@
+/*******************************************************************************
+* Copyright (C) 2016 Maxim Integrated Products, Inc., All rights Reserved.
+* 
+* This software is protected by copyright laws of the United States and
+* of foreign countries. This material may also be protected by patent laws
+* and technology transfer regulations of the United States and of foreign
+* countries. This software is furnished under a license agreement and/or a
+* nondisclosure agreement and may only be used or reproduced in accordance
+* with the terms of those agreements. Dissemination of this information to
+* any party or parties not specified in the license agreement and/or
+* nondisclosure agreement is expressly prohibited.
+*
+* The above copyright notice and this permission notice shall be included
+* in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+* OTHER DEALINGS IN THE SOFTWARE.
+*
+* Except as contained in this notice, the name of Maxim Integrated
+* Products, Inc. shall not be used except as stated in the Maxim Integrated
+* Products, Inc. Branding Policy.
+*
+* The mere transfer of this software does not imply any licenses
+* of trade secrets, proprietary technology, copyrights, patents,
+* trademarks, maskwork rights, or any other form of intellectual
+* property whatsoever. Maxim Integrated Products, Inc. retains all
+* ownership rights.
+*******************************************************************************
+*/
+
+//#define CES_DEMO
+//#define FILE_LOG
+
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Drawing;
+using System.Data;
+using System.Linq;
+using System.Text;
+using System.Windows.Forms;
+using System.Windows.Forms.DataVisualization.Charting;
+using RPCSupport.Streaming;
+using RPCSupport.Devices;
+
+using HealthSensorPlatform.View;
+using HealthSensorPlatform.Presenter;
+using HealthSensorPlatform.Model;
+
+#if CES_DEMO
+using System.Collections;
+#endif
+
+// DEBUG
+using System.IO;
+
+
+namespace HealthSensorPlatform.CustomControls
+{
+    public partial class EcgView : UserControl, IDeviceView, IEcgView
+    {
+        /* Constants */
+        const int Rbias_FMSTR_Init = 0;
+        const int CAL_init = 1;
+        const int ECG_InitStart = 2;
+        const int PACE_InitStart = 3;
+        const int BIOZ_InitStart = 4;
+        const int ECGFast_Init = 5;
+        const int RtoR_InitStart = 6;
+
+        const int RToRMaxValue = 0x3FFF;
+
+#if CES_DEMO
+        const int[] averageOptions = new int[] { 1, 2, 4, 8, 10 };
+#endif
+
+        /* Fields */
+        public InitArgs.RbiasInit rbiasInit;
+        public InitArgs.EcgInitStart ecgArgs;
+        public InitArgs.EcgFastInit ecgFastArgs;
+        public InitArgs.PACEInitStart paceArgs;
+        public InitArgs.BIOZInitStart biozArgs;
+        public InitArgs.RToRInitStart rtorArgs;
+        public InitArgs.CalInitStart calArgs;
+
+        public GetEcgInitArgs GetEcgInitArgsPointer;
+        public GetRToRInitArgs GetRToRInitArgsPointer;
+        public GetBioZInitArgs GetBioZInitArgsPointer;
+        public GetPaceInitArgs GetPaceInitArgsPointer;
+
+        /// <summary>
+        /// Number of R To R points which need to be removed from the chart
+        /// </summary>
+        int rToRRemoveOffset;
+
+        long lastRToRTime;
+
+        double timeResolution = 0.00001525878; 
+
+        double[] clockFreq = { 32768, 32000, 32000, 32768 * 640 / 656 }; // 31968.7804878 = 32768 * 640 / 656
+
+        int frequencyMasterField = 0;
+
+        public double masterClockFrequency = 32768;
+
+#if CES_DEMO
+        public int AverageECG = 1;
+#endif
+
+        private RPCSupport.RPCClient rpcClient;
+        private bool connected = false;
+        //private bool stream = true;
+
+        /// <summary>
+        /// Use to scale the bioZ chart data to milliohm range
+        /// </summary>
+        private int bioZRangeMultiplier = 1;
+
+        bool startedCal = false;
+        bool startedEcg = false;
+        bool startedPace = false;
+        bool startedBioz = false;
+        bool startedRtoR = false;
+
+        private bool enableECG = false;
+        private bool enableRToR = false;
+        private bool enableBioZ = false;
+        private bool enablePace = false;
+
+        int rToRInterval = -1;
+
+        ChartInfo ecgInfo;
+        ChartInfo rToRInfo;
+        ChartInfo bioZInfo; 
+        ChartInfo paceInfo;
+
+        Queue<int> paceTag = new Queue<int>();
+        public PaceData paceData; // TODO: public for testing only
+        RToRCalculator rToRCalculator;
+
+        List<double> heartRateList = new List<double>(10);
+
+        /* CES DEMO average feature, normal operation average is 1 */
+        //int averageEcgCount = 0;
+        //int averageEcgSum = 0;
+
+        StringBuilder fileLogData = new StringBuilder();
+
+		int[, ,] ecgDecimationDelay = new int[,,] { {{650, 1034}, {2922, 3690}, {3370, 4906}, {3370, 4906}}, 
+													{{650, 1034}, {2922, 3690}, {3370, 4906}, {3370, 4906}},
+													{{1242, 2202}, {1242, 2202}, {1242, 2202}, {1242, 2202}},
+													{{1242, 2202}, {1242, 2202}, {1242, 2202}, {1242, 2202}}
+                                                  };
+
+        public int RToRWindowField = 0;
+		
+#if CES_DEMO
+        FirFilter hpf;
+#endif
+
+#if FILE_LOG
+        // DEBUG
+        StreamWriter file; //= new StreamWriter("hsp_ecg_output_data.csv");
+#endif
+
+        /* Constructor */
+        public EcgView()
+        {
+            InitializeComponent();
+
+            //paceInfo = ecgInfo;
+
+            /*foreach(int item in averageOptions)
+            {
+                cboAverageEcg.Items.Add(item.ToString());
+            }*/
+            //cboAverageEcg.SelectedIndex = 0;
+            //cboMaxScale.SelectedIndex = 1;
+
+            chartRtoR.ChartAreas[0].AxisY.Maximum = 100;
+
+            ecgInfo = new ChartInfo
+            {
+                SampleRate = 128, // Power on defaults for ECG
+                Length = 10,
+                Average = 1,
+                Shift = 6,
+                Gain = 20,
+                // ECG is 18 bits, with MSB as sign bit
+                Threshold = 0x1ffff,
+                Offset = 0x40000,
+                Chart = chartECG,
+                SeriesName = "Series",
+            };
+            rToRInfo = new ChartInfo
+            {
+                SampleRate = 128,
+                Length = 10,
+                Chart = chartECG,
+                SeriesName = "SeriesRToR",
+            };
+            bioZInfo = new ChartInfo
+            {
+                SampleRate = 64,
+                Length = 10,
+                Shift = 4,
+                Gain = 20,
+                // BioZ is 20 bits, with MSB as sign bit
+                Threshold = 0x7ffff,
+                Offset = 0x100000,
+                Chart = chartBioz,
+                SeriesName = "Series",
+            };
+            paceInfo = new ChartInfo
+            {
+                SampleRate = 65536 * ecgInfo.SampleRate, // 2 * fMSTR
+                Length = 10,
+                Average = 1,
+                Shift = 0, // Keep tag info
+                Chart = chartECG,
+                SeriesName = "SeriesPace",
+            };
+
+            NamedImage paceFalling = new NamedImage("PaceFallingImage", HealthSensorPlatform.Properties.Resources.pace_falling);
+            chartECG.Images.Add(paceFalling);
+            NamedImage paceRising = new NamedImage("PaceRisingImage", HealthSensorPlatform.Properties.Resources.pace_rising);
+            chartECG.Images.Add(paceRising);
+#if CES_DEMO
+            //grpAverage.Visible = true;
+
+            hpf = new FirFilter();
+            //cboEcgHpf.SelectedIndex = 0;
+#endif
+        }
+
+        /* Delegates */
+        public delegate InitArgs.EcgInitStart GetEcgInitArgs();
+        public delegate InitArgs.RToRInitStart GetRToRInitArgs();
+        public delegate InitArgs.BIOZInitStart GetBioZInitArgs();
+        public delegate InitArgs.PACEInitStart GetPaceInitArgs();
+        //public delegate void StreamingStartStopEventHandler(StreamingStartStopEventArgs e);
+
+        /* Events */
+        /// <summary>
+        /// Streaming event 
+        /// </summary>
+        public event EventHandler<StreamingStartStopEventArgs> StreamingStartStop;
+
+        /* Enums */
+        public enum StreamDataType
+        {
+            Ecg,
+            RToR,
+            Pace,
+            BioZ
+        };
+
+        /* Properties */
+        public RPCSupport.RPCClient RPCClient
+        {
+            set
+            {
+                rpcClient = value;
+                //streamHandler = new EventHandler<PartialArrayIntAvailableEventArgs>(On_AppendChart);
+                //rpcClient.streaming.PartialArrayIntAvailable += streamHandler;
+            }
+        }
+        /*
+        public bool Stream
+        {
+            get
+            {
+                return stream;
+            }
+            set
+            {
+                stream = value;
+                if (stream == true)
+                    rpcClient.streaming.PartialArrayIntAvailable += streamHandler;
+                else
+                    rpcClient.streaming.PartialArrayIntAvailable -= streamHandler;
+            }
+        }
+*/
+        public bool Connected
+        {
+            get
+            {
+                return connected;
+            }
+            set
+            {
+                connected = value;
+            }
+        }
+        public bool EnableECG
+        {
+            get
+            {
+                return enableECG;
+            }
+            set
+            {
+                enableECG = value;
+                chartECG.Enabled = value;
+            }
+        }
+        public bool EnableRToR
+        {
+            get
+            {
+                return enableRToR;
+            }
+            set
+            {
+                enableRToR = value;
+                chartRtoR.Enabled = value;
+                grpBxHeartRate.Enabled = value;
+            }
+        }
+        public bool EnableBioZ
+        {
+            get
+            {
+                return enableBioZ;
+            }
+            set
+            {
+                enableBioZ = value;
+                chartBioz.Enabled = value;
+            }
+        }
+        public bool EnablePace
+        {
+            get
+            {
+                return enablePace;
+            }
+            set
+            {
+                enablePace = value;
+                chartPace.Enabled = value;
+            }
+        }
+        public bool EnableDCLeadOff
+        {
+            get
+            {
+                return grpBxDCLeadOff.Enabled;
+            }
+            set
+            {
+                grpBxDCLeadOff.Enabled = value;
+            }
+
+        }
+        public bool EnableEcgDCLeadOff { get; set; }
+        public bool EnableBioZOverUnderRange
+        {
+            get
+            {
+                return grpBxBioZOverUnderRange.Enabled;
+            }
+            set
+            {
+                grpBxBioZOverUnderRange.Enabled = value;
+            }
+        }
+
+        public bool BioZMilliOhmRange
+        {
+            get
+            {
+                return (bioZRangeMultiplier == 1000);
+            }
+
+            set
+            {
+                if (value)
+                {
+                    bioZRangeMultiplier = 1000;
+                    chartBioz.ChartAreas["ChartArea"].AxisY.Title = "Bioz (m‎Ω)";
+                }
+                else
+                {
+                    bioZRangeMultiplier = 1;
+                    chartBioz.ChartAreas["ChartArea"].AxisY.Title = "Bioz (‎Ω)";
+                }
+            }
+        }
+
+        public double SampleRateEcg // Human readable sample rate
+        {
+            get
+            {
+                return ecgInfo.SampleRate;
+            }
+            set
+            {
+                ecgInfo.SampleRate = value;
+                //rToRInfo.SampleRate = value;
+                paceInfo.SampleRate = MasterClockFrequency * 2 * value;
+            }
+        }
+        public double SampleRateBioZ // Human readable sample rate
+        {
+            get
+            {
+                return bioZInfo.SampleRate;
+            }
+            set
+            {
+                bioZInfo.SampleRate = value;
+            }
+        }
+        public int GainECG // Human readable gain
+        {
+            get
+            {
+                return ecgInfo.Gain;
+            }
+            set
+            {
+                ecgInfo.Gain = value;
+            }
+        }
+        public int GainBioZ // Human readable gain
+        {
+            get
+            {
+                return bioZInfo.Gain;
+            }
+            set
+            {
+                bioZInfo.Gain = value;
+            }
+        }
+        public int CurrentBioZ // Human readable bioZ current generator magnitude
+        {
+            get
+            {
+                return bioZInfo.CurrentGenerator;
+            }
+            set
+            {
+                bioZInfo.CurrentGenerator = value;
+            }
+        }
+        /// <summary>
+        /// This value is t_RES = 1 / (2 * fMSTR) = 1 / (2 * 32768). For R-to-R the LSB time is 512*t_RES, while for
+        /// PACE, the value is t_RES.
+        /// </summary>
+        public double TimeResolution
+        {
+            get
+            {
+                return timeResolution;
+            }
+        }
+
+        public ChartInfo EcgInfo { get { return ecgInfo; } }
+        public ChartInfo RToRInfo { get { return rToRInfo; } }
+        public ChartInfo BioZInfo { get { return bioZInfo; } }
+        public ChartInfo PaceInfo { get { return paceInfo; } }
+
+        public InitArgs.EcgInitStart EcgArgs { get { return ecgArgs; } }
+        public InitArgs.RToRInitStart RToRArgs { get { return rtorArgs; } }
+
+        public int MasterClockField { get { return frequencyMasterField; } }
+        public int FrequencyMasterField
+        {
+            get
+            {
+                return frequencyMasterField;
+            }
+
+            set
+            {
+                frequencyMasterField = value;
+                masterClockFrequency = clockFreq[frequencyMasterField];
+                paceInfo.SampleRate = 2 * masterClockFrequency;
+                rToRInfo.SampleRate = masterClockFrequency / 256.0;
+                timeResolution = 1.0 / (2 * masterClockFrequency);
+            }
+        }
+        public double MasterClockFrequency
+        {
+            get
+            {
+                return masterClockFrequency;
+            }
+            /*
+            set
+            {
+                masterClockFrequency = value;
+                paceInfo.SampleRate = 2 * value;
+                TimeResolution = 1 / (2 * value);
+            }*/
+        }
+
+        public int EcgDecimationDelay
+        {
+            get
+            {
+                int fmstr = frequencyMasterField;
+                int ecgRate = ecgArgs.Rate;
+                int lpf = ecgArgs.Dlpf > 0 ? 1 : 0;
+
+                return ecgDecimationDelay[fmstr, ecgRate, lpf];
+            }
+        }
+        public int RToRDelay
+        {
+            get
+            {
+
+                return 5376 + 3370 + 256 * RToRWindowField;
+            }
+        }
+
+        public Chart ChartECG { get { return chartECG; } } // Testing
+        public IHspSetting HspSetting
+        {
+            get;
+            set;
+        }
+
+        private void EcgView_Load(object sender, EventArgs e)
+        {
+            InitChart();
+        }
+
+        String ValueToBits(int value, int width)
+        {
+            String str = "";
+            String val = "";
+            int mask = 1;
+            for (int i = 0; i < width; i++)
+            {
+                if ((mask & value) == mask)
+                {
+                    val = "1";
+                }
+                else
+                {
+                    val = "0";
+                }
+                mask = mask << 1;
+                str = val + str;
+            }
+            return str;
+        }
+
+        String[] ValueToBitStringArray(int width)
+        {
+            List<String> stringList = new List<string>();
+            for (int i = 0; i < Math.Pow(2, width); i++)
+            {
+                stringList.Add(ValueToBits(i, width));
+            }
+            return stringList.ToArray();
+        }
+
+        private void InitChart()
+        {
+            // Reset Averaging
+            //averageEcgSum = 0;
+            //averageEcgCount = 0;
+
+            //ecgInfo.Average = averageOptions[cboAverageEcg.SelectedIndex];
+            ecgInfo.Average = 1; 
+
+            // Rest Pace Tags
+            paceTag.Clear();
+
+            //UpdateChart(chartPace, new int[] {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0});
+            //paceData = new PaceData(new int[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 });
+            //UpdateChart(StreamDataType.Ecg, new int[] {1});
+            DisplayEcg(new double[] { 0 }, null, null);
+            //UpdateChart(chartECG, "SeriesRToR", new int[] {0});
+            //UpdateChart(StreamDataType.BioZ, new int[] {0});
+            DisplayBioZ(new double[] { 0 });
+            UpdateChartAxis(chartECG);
+            //UpdateChartAxis(chartRtoR);
+            UpdateChartAxis(chartBioz);
+            //UpdateChartAxis(chartPace);
+
+            paceData = null;
+            
+            //chartRtoR.ChartAreas[0].AxisY.Maximum = 100;
+        }
+
+        private void ResetChart()
+        {
+            paceData = null;
+        }
+
+        private void UpdateChartAxis(System.Windows.Forms.DataVisualization.Charting.Chart chart)
+        {
+            ChartInfo chartInfo = new ChartInfo();
+
+            if (chart.Name == "chartECG")
+            {
+                chartInfo = ecgInfo;
+            }
+            else if (chart.Name == "chartBioz")
+            {
+                chartInfo = bioZInfo;
+            }
+            else if (chart.Name == "chartPace")
+            {
+                chartInfo = paceInfo;
+            }
+            else if (chart.Name == "chartRtoR")
+            {
+                chartInfo = rToRInfo;
+            }
+
+            chart.SuspendLayout();
+            chart.ChartAreas[0].AxisX.Minimum = 0;
+            chart.ChartAreas[0].AxisX.Maximum = chartInfo.Points; 
+            chart.ChartAreas[0].AxisX.Interval = (float)chartInfo.Points / chartInfo.Length;
+
+            if (chart.Name != "chartRtoR")
+            {
+                chart.ChartAreas[0].AxisX.CustomLabels.Clear();
+                // Set X-axis range in seconds
+                for (int i = 0; i < 11; i ++ )
+                {
+                    chart.ChartAreas[0].AxisX.CustomLabels.Add(Math.Ceiling(((float)chartInfo.SampleRate / chartInfo.Average) * (2 * i - 1) / 2), 
+                        Math.Floor(((float)chartInfo.SampleRate / chartInfo.Average) * (2 * i + 1) / 2), i.ToString());
+                }
+            }
+
+            chart.ResumeLayout();
+        }
+
+        public void DisplayEcg(double[] ecg, PacePoint[] pace, double[] rToR)
+        {
+            List<double> xList = new List<double>();
+            List<double> yList = new List<double>();
+            List<double> xListFalling = new List<double>();
+            List<double> yListFalling = new List<double>();
+
+            int offset = chartECG.Series["Series"].Points.Count; // Pace Offset
+
+            chartECG.SuspendLayout();
+
+            for(int i = 0; i < ecg.Length; i++ )
+            {
+                chartECG.Series["Series"].Points.Add(ecg[i]);
+            }
+
+            if (pace != null)
+            {
+                // Shift Old Points - Rising
+                for (int i = 0; i < chartECG.Series["SeriesPace"].Points.Count; i++)
+                {
+                    double xValue = chartECG.Series["SeriesPace"].Points[i].XValue;
+
+                    if (offset > ecgInfo.Points) // Do not shift until chart is full
+                        xValue -= ecg.Length;
+
+                    if (xValue >= 0)
+                    {
+                        xList.Add(xValue);
+                        yList.Add(chartECG.Series["SeriesPace"].Points[i].YValues[0]);
+                    }
+                }
+                // Shift Old Points - Falling
+                for (int i = 0; i < chartECG.Series["SeriesPaceFalling"].Points.Count; i++ )
+                {
+                    double xValueFalling = chartECG.Series["SeriesPaceFalling"].Points[i].XValue;
+
+                    if (offset > ecgInfo.Points)
+                        xValueFalling -= ecg.Length;
+
+                    if (xValueFalling >= 0)
+                    {
+                        xListFalling.Add(xValueFalling);
+                        yListFalling.Add(chartECG.Series["SeriesPaceFalling"].Points[i].YValues[0]);
+                    }
+                }
+
+                // Add New Points
+                for (int i = 0; i < pace.Length; i++)
+                {
+                    if (pace[i].Polarity == true)
+                    {
+                        //xList.Add(pace[i].Time + offset);
+                        //yList.Add(0.05);
+                        chartECG.Series["SeriesPace"].Points.AddXY(pace[i].Time + offset, 0.05*(0+1));
+                        //System.Diagnostics.Debug.Print("Rising: " + (pace[i].Time + offset));
+                    }
+                    else
+                    {
+                        //xListFalling.Add(pace[i].Time + offset);
+                        //yListFalling.Add(-0.05);
+                        chartECG.Series["SeriesPaceFalling"].Points.AddXY(pace[i].Time + offset, -0.08*(0+1));
+                        //System.Diagnostics.Debug.Print("Falling: " + (pace[i].Time + offset));
+                    }
+                }
+
+                // Bind data to chart
+                //chartECG.Series["SeriesPace"].Points.DataBindXY(xList, yList);
+                //chartECG.Series["SeriesPaceFalling"].Points.DataBindXY(xListFalling, yListFalling);
+            }
+
+            UpdateChartFormat(StreamDataType.Ecg, ecgInfo);
+            //if (rToR != null) // Remove extra points
+            //    UpdateChartFormat(StreamDataType.RToR, rToRInfo);
+            if (pace != null) // Not needed anymore due to new plot style
+                UpdateChartFormat(StreamDataType.Pace, PaceInfo, offset + ecg.Length - ecgInfo.Points);
+            chartECG.ResumeLayout();
+        }
+
+        public void DisplayBioZ(double[] bioZ)
+        {
+            chartBioz.SuspendLayout();
+
+            for(int i = 0; i < bioZ.Length; i++)
+            {
+                chartBioz.Series["Series"].Points.Add(bioZ[i] * bioZRangeMultiplier);
+            }
+
+            UpdateChartFormat(StreamDataType.BioZ, bioZInfo);
+
+            chartBioz.ResumeLayout();
+        }
+
+        public double DisplayRToR(int rToR)
+        {
+            double rate;
+            int rToREcg;
+
+            long now = DateTime.Now.Ticks;
+
+            if (rToR == RToRMaxValue) // Ignore the max value, counter overflow condition
+                return 0;
+
+            rate = rToRCalculator.BeatsPerMinute(rToR); // RToRBeatsPerMinute(rToR);
+
+            if (heartRateList.Count < 10)
+                heartRateList.Add(rate);
+            else if (heartRateList.Count == 10)
+            {
+                heartRateList.RemoveAt(0);
+                heartRateList.Add(rate);
+
+                double sum = 0;
+                foreach (double d in heartRateList)
+                    sum += d;
+
+                lblHeartRateAverage10.Text = (sum / 10).ToString("F1");
+
+            }
+
+            lblHeartRateBeatToBeat.Text = rate.ToString("F1");
+
+            if (heartRateList.Count != 1)
+            {
+                rToREcg = rToRCalculator.EcgPoints(rToR, false); // RToREcgPoints(rToR, false);
+            }
+            else
+            {
+                // First Point delay by Tdrtor_ecg
+                //rToREcg = RToREcgPoints(rToR, true) + 1; // DEBUG 3 extra 0x07 are sent from FW at start of stream, 1 extra point for GUI chart init
+                int rToRInEcg = rToRCalculator.EcgPoints(rToR, true);
+                rToREcg = rToRInEcg + 1;
+            }
+
+            if (lastRToRTime < 0)
+                lastRToRTime = now;
+            else
+            {
+                long diff = now - lastRToRTime;
+                TimeSpan elaspedTicks = new TimeSpan(diff);
+
+                int fullScaleTime = (int)(Math.Pow(2, 14) * 512 * TimeResolution + 0.5);
+
+                if (elaspedTicks.TotalSeconds > fullScaleTime)
+                {
+                    int overflowCount = (int)(elaspedTicks.TotalSeconds / fullScaleTime);
+
+                    for (int i = 0; i < overflowCount; i++ )
+                        rToREcg += rToRCalculator.EcgPoints(EcgDelay.RToRMaxValue, false); //RToREcgPoints(0x3FFF, false);
+                }
+
+                lastRToRTime = now;
+            }
+
+            for (int i = 1; i < rToREcg - rToRRemoveOffset; i++ )
+            {
+                chartECG.Series["SeriesRToR"].Points.Add(-5000);
+            }
+            int rToRCount = chartECG.Series["SeriesRToR"].Points.Count;
+
+            if (rToRCount < chartECG.Series["Series"].Points.Count)
+                chartECG.Series["SeriesRToR"].Points.Add(chartECG.Series["Series"].Points[rToRCount].YValues[0]); // R to R comes in after ECG
+            else
+                chartECG.Series["SeriesRToR"].Points.Add(0); // R to R comes in faster than ECG, add as 0 for now
+
+            rToRRemoveOffset = 0;
+
+            return rate;
+        }
+
+        public void BioZFunction(bool enable)
+        {
+            chartBioz.Visible = enable;
+
+            if (enable == false)
+            {
+                //tableLayoutPanelCharts.RowCount = 1;
+                tableLayoutPanelCharts.RowStyles[1] = new RowStyle(SizeType.Percent, 0);
+                tableLayoutPanelCharts.RowStyles[0] = new RowStyle(SizeType.Percent, 100);
+            }
+            else
+            {
+                tableLayoutPanelCharts.RowStyles[0] = new RowStyle(SizeType.Percent, 50);
+                tableLayoutPanelCharts.RowStyles[1] = new RowStyle(SizeType.Percent, 50);
+            }
+
+        }
+
+
+        /*
+        public double RToRBeatsPerMinute(int rToRCode)
+        {
+            return 60 * 1000/ RToRMillisecond(rToRCode);
+        }
+
+        public double RToRMillisecond(int rToRCode)
+        {
+            return rToRCode * 512.0 * 1000 / (2 * MasterClockFrequency);
+        }
+
+        public int RToREcgPoints(int rToR, bool first)
+        {
+            double sampleRateRToR = MasterClockFrequency / 256;
+            int rToRDifferentialDelay = RToRDelay - EcgDecimationDelay;
+
+            double rToRInEcgSamples;
+            int rToRInEcgSamplesInt;
+
+            if (first)
+            {
+                rToRInEcgSamples = (rToR - rToRDifferentialDelay / 256.0) * (SampleRateECG / sampleRateRToR);
+                rToRInEcgSamplesInt = (int)(rToRInEcgSamples + 0.5);
+
+                rToRInEcgSampleError = rToRInEcgSamplesInt - rToRInEcgSamples;
+
+                return rToRInEcgSamplesInt;
+            }
+            else
+            {
+                rToRInEcgSamples = rToR * (SampleRateECG / sampleRateRToR) - rToRInEcgSampleError;
+                rToRInEcgSamplesInt = (int)(rToRInEcgSamples + 0.5);
+
+                rToRInEcgSampleError = rToRInEcgSamplesInt - rToRInEcgSamples;
+
+                return rToRInEcgSamplesInt;
+
+            }
+        }
+        */
+
+        private double[] UpdateChartFormat(StreamDataType dataType, ChartInfo chartInfo)
+        {
+            Chart chart = null;
+            String series = "";
+            double[] chartData;
+            int minRound = 0, maxRound = 0;
+            double min = Double.MaxValue, max = Double.MinValue;
+            int count;
+            
+            switch (dataType)
+            {
+                case StreamDataType.Ecg:
+                    chart = chartECG;
+                    series = "Series";
+                    break;
+                case StreamDataType.BioZ:
+                    chart = chartBioz;
+                    series = "Series";
+                    break;
+                case StreamDataType.RToR:
+                    chart = chartECG;
+                    series = "SeriesRToR";
+                    break;
+                case StreamDataType.Pace:
+                    chart = chartECG;
+                    series = "SeriesPace";
+                    break;
+
+            }
+            
+            count = chart.Series[series].Points.Count;
+
+            // Remove extra points
+            while (count > chartInfo.Points)
+            {
+                chart.Series[series].Points.RemoveAt(0);
+                if (dataType == StreamDataType.Ecg && EnableRToR) // Scroll R To R with ECG
+                    if (chart.Series["SeriesRToR"].Points.Count > 0) // TODO
+                        chart.Series["SeriesRToR"].Points.RemoveAt(0);
+                    else
+                        rToRRemoveOffset++;
+
+                count = chart.Series[series].Points.Count;
+            }
+
+            chartData = new double[chart.Series[series].Points.Count];
+
+            // Copy data points and find min/max value
+            for (int i = count / 2; i < count; i++) // Autoscale on last half of data only
+            {
+                chartData[i] = chart.Series[series].Points[i].YValues[0];
+
+                if (chartData[i] < min)
+                    min = chartData[i];
+                if (chartData[i] > max)
+                    max = chartData[i];
+            }
+
+            if (min == max) // prevent any invalid ranges
+                max = max + 1;
+
+            if (chartInfo == ecgInfo)
+            {
+                // Round to 1mV for ECG
+                minRound = ((int)(min / 1) - 1) * 1;
+                maxRound = ((int)(max / 1) + 1) * 1;
+
+                if (minRound == -1 && maxRound == 1) // Manual control of auto interval
+                    chart.ChartAreas[0].AxisY.Interval = 0.5;
+                else
+                    chart.ChartAreas[0].AxisY.Interval = 0;
+            }
+            else if (chartInfo == bioZInfo)
+            {
+                // Round to 100's for automatic axis scaling - for raw codes
+                minRound = (((int)min / 100 - 1) * 100);
+                maxRound = (((int)max / 100 + 1) * 100);
+            }
+            /*else if (chartInfo == rToRInfo)
+            {
+                // Round to 100ms
+                minRound = 0; // R to R rate should never be negative;
+                maxRound = ((int)(max / 100) + 1) * 100;
+            }
+            else
+            {
+                // Round to 100's for automatic axis scaling - for us of Pace length
+                minRound = (((int)min / 100 - 1) * 100);
+                maxRound = (((int)max / 100 + 1) * 100);
+            }*/
+
+            if (chartInfo == ecgInfo || chartInfo == bioZInfo)
+            {
+                // Set full Y-axis range
+                chart.ChartAreas[0].AxisY.Minimum = minRound;
+                chart.ChartAreas[0].AxisY.Maximum = maxRound;
+            }
+
+            return chartData;
+        }
+
+        private double[] UpdateChartFormat(StreamDataType dataType, ChartInfo chartInfo, int shift)
+        {
+            List<double> xList = new List<double>();
+            List<double> yList = new List<double>();
+            List<double> xListFalling = new List<double>();
+            List<double> yListFalling = new List<double>();
+
+            int offset = chartECG.Series["Series"].Points.Count; // Pace Offset
+
+            // Shift Old Points - Rising
+            for (int i = 0; i < chartECG.Series["SeriesPace"].Points.Count; i++)
+            {
+                double xValue = chartECG.Series["SeriesPace"].Points[i].XValue;
+
+                if (offset >= ecgInfo.Points) // Do not shift until chart is full
+                    xValue -= shift;
+
+                if (xValue >= 0)
+                {
+                    xList.Add(xValue);
+                    yList.Add(chartECG.Series["SeriesPace"].Points[i].YValues[0]);
+                }
+            }
+            // Shift Old Points - Falling
+            for (int i = 0; i < chartECG.Series["SeriesPaceFalling"].Points.Count; i++)
+            {
+                double xValueFalling = chartECG.Series["SeriesPaceFalling"].Points[i].XValue;
+
+                if (offset >= ecgInfo.Points)
+                    xValueFalling -= shift;
+
+                if (xValueFalling >= 0)
+                {
+                    xListFalling.Add(xValueFalling);
+                    yListFalling.Add(chartECG.Series["SeriesPaceFalling"].Points[i].YValues[0]);
+                }
+            }
+
+            chartECG.Series["SeriesPace"].Points.DataBindXY(xList, yList);
+            chartECG.Series["SeriesPaceFalling"].Points.DataBindXY(xListFalling, yListFalling);
+
+            return yList.ToArray();
+        }
+
+        /*
+        public EcgFifo[] ConvertEcg(int[] data)
+        {
+            EcgFifo[] voltage = new EcgFifo[data.Length];
+            ChartInfo chartInfo = ecgInfo;
+            int dataShift;
+
+            for (int i = 0; i < data.Length; i++ )
+            {
+                dataShift = data[i] >> chartInfo.Shift;
+
+                // Two's Complement Conversions
+                if (dataShift > chartInfo.Threshold)
+                {
+                    dataShift -= chartInfo.Offset;
+                }
+
+                voltage[i].Data = 1000 * 7.62939453125e-6 * dataShift / chartInfo.Gain;
+                voltage[i].PTag = data[i] & 0x07;
+                voltage[i].ETag = (data[i] >> 3) & 0x07;
+            }
+
+            return voltage;
+        }
+
+        public BioZFifo[] ConvertBioZ(int[] data)
+        {
+            BioZFifo[] impedence = new BioZFifo[data.Length];
+            ChartInfo chartInfo = bioZInfo;
+            int dataShift;
+            int dataPoint;
+
+            for (int i = 0; i < data.Length; i ++)
+            {
+                dataShift = data[i] >> chartInfo.Shift;
+
+                // Two's Complement Conversions
+                if (dataShift > chartInfo.Threshold)
+                {
+                    dataShift -= chartInfo.Offset;
+                }
+
+                // 1.9734 = 1/2^19 * 1e-6
+                impedence[i].Data = dataShift * bioZRangeMultiplier * 1.9073486328125 / 
+                    (chartInfo.Gain * ((chartInfo.CurrentGenerator == 0) ? 1 : chartInfo.CurrentGenerator));
+                impedence[i].BTag = data[i] & 0x07;
+            }
+
+            return impedence;
+        }
+
+        public PaceData ConvertPace(int[] data)
+        {
+            paceData = new PaceData(data);
+
+            return paceData;
+        }
+
+        public double ConvertRToR(int data)
+        {
+            rToRInterval = data;
+
+            return rToRInterval;
+        }
+         */
+
+        int[] ProcessRToR(int[] ecgData)
+        {
+            int[] rToRArray;
+
+            rToRArray = new int[ecgData.Length];
+            for (int i = 0; i < rToRArray.Length; i++)
+                rToRArray[i] = Int32.MinValue;
+
+            if (rToRInterval > 0) // Valid R to R
+            {
+                var ecgCode = EcgMaximumCode(ecgData);
+                rToRArray[ecgCode.Item1] = ecgCode.Item2;
+            }
+
+            return rToRArray;
+        }
+
+        public Tuple<int, int> EcgMaximumCode(int[] data)
+        {
+            int i;
+            int max = Int32.MinValue;
+            int maxCode = 0;
+            int maxIndex = 0;
+            int point;
+
+            for (i = 0; i < data.Length; i++ )
+            {
+                point = data[i] >> ecgInfo.Shift;
+                if (data[i] > ecgInfo.Threshold)
+                    point -= ecgInfo.Offset;
+
+                if (point > max) // Two's complement offset
+                {
+                    max = point;
+                    maxCode = data[i];
+                    maxIndex = i;
+                }
+            }
+
+            return new Tuple<int, int>(maxIndex, maxCode);
+        }
+
+        private bool LeadOffBit(int value, int bit)
+        {
+            int state;
+            int mask = 1 << bit;
+            state = ((value & mask) == mask) ? 1 : 0;
+            return state == 1;
+        }
+
+        //public void On_AppendChart(object sender, PartialArrayIntAvailableEventArgs e)
+        //{
+            /*
+            int leadOffState;
+
+            if (e.array1.Length > 0) // Occurs with streaming from flash
+            {
+                leadOffState = e.array1[0];
+
+                switch (e.reportID)
+                {
+                    case PartialArrayIntAvailableEventArgs.PACKET_MAX30001_LEADOFF_DC:
+                        if (LeadOffBit(leadOffState, 8)) // check for ECG
+                        {
+                            UpdateLeadOffState(lblLdoffPh, LeadOffBit(leadOffState, 3));
+                            UpdateLeadOffState(lblLdoffPl, LeadOffBit(leadOffState, 2));
+                            UpdateLeadOffState(lblLdoffNh, LeadOffBit(leadOffState, 1));
+                            UpdateLeadOffState(lblLdoffNl, LeadOffBit(leadOffState, 0));
+                        }
+                        if (LeadOffBit(leadOffState, 9)) // check for BIOZ
+                        {
+                            UpdateLeadOffState(lblLdoffPh, LeadOffBit(leadOffState, 3));
+                            UpdateLeadOffState(lblLdoffPl, LeadOffBit(leadOffState, 2));
+                            UpdateLeadOffState(lblLdoffNh, LeadOffBit(leadOffState, 1));
+                            UpdateLeadOffState(lblLdoffNl, LeadOffBit(leadOffState, 0));
+                        }
+                        break;
+                    case PartialArrayIntAvailableEventArgs.PACKET_MAX30001_LEADOFF_AC:
+                        UpdateLeadOffState(lblBioZACOver, LeadOffBit(leadOffState, 0));
+                        UpdateLeadOffState(lblBioZACUnder, LeadOffBit(leadOffState, 1));
+                        break;
+                }
+            }
+            */
+            /*
+            StringBuilder outputData = new StringBuilder();
+
+            if (e.reportID == PartialArrayIntAvailableEventArgs.PACKET_MAX30001_ECG)
+            {
+                if (e.array1.Length != 0)
+                {
+                    if (ecgBuffer != null)
+                    { 
+                        UpdateChart(StreamDataType.Ecg, ecgBuffer);
+
+                        if (EnableRToR)
+                        {
+                            int[] rToRArray = ProcessRToR(ecgBuffer);
+
+                            UpdateChart(StreamDataType.RToR, rToRArray);
+                            rToRInterval = -1; // R to R processed reset value
+                        }
+                    }
+
+                    ecgBuffer = ecgBuffer1;
+                    ecgBuffer1 = e.array1; 
+                    // DEBUG
+                    foreach (int data in e.array1)
+                    {
+                        outputData.Append(data.ToString());
+                        outputData.Append(Environment.NewLine);
+                    }
+
+                    file.Write(outputData.ToString());
+
+                    ConvertEcg(e.array1);
+                }
+            }
+            if (e.reportID == PartialArrayIntAvailableEventArgs.PACKET_MAX30001_PACE)
+            {
+                if (e.array1.Length != 0)
+                {
+                    // Store Pace data for update with ECG PTAGs
+                    ConvertPace(e.array1);
+                }
+            }
+            if (e.reportID == PartialArrayIntAvailableEventArgs.PACKET_MAX30001_RTOR)
+            {
+                if (e.array1.Length != 0)
+                {
+                    ConvertRToR(e.array1[0]);
+                }
+            }
+            if (e.reportID == PartialArrayIntAvailableEventArgs.PACKET_MAX30001_BIOZ)
+            {
+                if (e.array1.Length != 0)
+                {
+                    ConvertBioZ(e.array1);
+                    //UpdateChart(StreamDataType.BioZ, e.array1);
+                }
+            }*/
+        //}
+
+        private void Start()
+        {
+            //ParseRbiasArgs();
+            /*rpcClient.MAX30001.Rbias_FMSTR_Init(
+                rbiasInit.En_rbias,
+                rbiasInit.Rbias,
+                rbiasInit.Rbiasp,
+                rbiasInit.Rbiasn,
+                rbiasInit.Fmstr
+            );*/
+
+
+            //if (ckbxCal.Checked)
+            /*{
+                startedCal = true;
+                //ParseCalArgs();
+                calArgs.En_Vcal = 0;
+                calArgs.Vmode = 0;
+                calArgs.Vmag = 1;
+                calArgs.Fcal = 3;
+                calArgs.Thigh = 0x1F;
+                calArgs.Fifty = 0;
+                rpcClient.MAX30001.CAL_InitStart(
+                    calArgs.En_Vcal,
+                    calArgs.Vmode,
+                    calArgs.Vmag,
+                    calArgs.Fcal,
+                    calArgs.Thigh,
+                    calArgs.Fifty);
+            }*/
+
+            /*
+            rpcClient.MAX30001.INT_assignment(MAX30001.max30001_intrpt_Location.MAX30001_INT_B, MAX30001.max30001_intrpt_Location.MAX30001_NO_INT, MAX30001.max30001_intrpt_Location.MAX30001_NO_INT,  //  en_enint_loc,      en_eovf_loc,   en_fstint_loc,
+                       MAX30001.max30001_intrpt_Location.MAX30001_INT_2B, MAX30001.max30001_intrpt_Location.MAX30001_INT_B, MAX30001.max30001_intrpt_Location.MAX30001_NO_INT,  //  en_dcloffint_loc,  en_bint_loc,   en_bovf_loc,
+                       MAX30001.max30001_intrpt_Location.MAX30001_INT_2B, MAX30001.max30001_intrpt_Location.MAX30001_INT_2B, MAX30001.max30001_intrpt_Location.MAX30001_NO_INT,  //  en_bover_loc,      en_bundr_loc,  en_bcgmon_loc,
+                       MAX30001.max30001_intrpt_Location.MAX30001_INT_B, MAX30001.max30001_intrpt_Location.MAX30001_NO_INT, MAX30001.max30001_intrpt_Location.MAX30001_NO_INT,  //  en_pint_loc,       en_povf_loc,   en_pedge_loc,
+                       MAX30001.max30001_intrpt_Location.MAX30001_INT_2B, MAX30001.max30001_intrpt_Location.MAX30001_INT_B, MAX30001.max30001_intrpt_Location.MAX30001_NO_INT,  //  en_lonint_loc,     en_rrint_loc,  en_samp_loc,
+                       MAX30001.max30001_intrpt_type.MAX30001_INT_ODNR, MAX30001.max30001_intrpt_type.MAX30001_INT_ODNR);                //  intb_Type,         int2b_Type)
+            */
+            if (connected)
+            {
+                rpcClient.MAX30001.WriteReg(0x02, 0x03); // Stop Interrupts
+                rpcClient.MAX30001.WriteReg(0x03, 0x03); // Stop Interrupts
+            }
+
+            if (enableECG)    
+            {
+                startedEcg = true;
+                if (GetEcgInitArgsPointer != null)
+                {
+                    ecgArgs = GetEcgInitArgsPointer();
+                    rpcClient.MAX30001.ECG_InitStart(
+                        ecgArgs.En_ecg,
+                        ecgArgs.Openp,
+                        ecgArgs.Openn,
+                        ecgArgs.Pol,
+                        ecgArgs.Calp_sel,
+                        ecgArgs.Caln_sel,
+                        ecgArgs.E_fit,
+                        ecgArgs.Rate,
+                        ecgArgs.Gain,
+                        ecgArgs.Dhpf,
+                        ecgArgs.Dlpf);
+                }
+
+ /*               rpcClient.MAX30001.ECGFast_Init(
+                    ecgFastArgs.Clr_Fast,
+                    ecgFastArgs.Fast,
+                    ecgFastArgs.Fast_Th);*/
+            }
+
+            if (enablePace)
+            {
+                startedPace = true;
+                if (GetPaceInitArgsPointer != null)
+                {
+                    paceArgs = GetPaceInitArgsPointer();
+                    rpcClient.MAX30001.PACE_InitStart(
+                        paceArgs.En_pace,
+                        paceArgs.Clr_pedge,
+                        paceArgs.Pol,
+                        paceArgs.Gn_diff_off,
+                        paceArgs.Gain,
+                        paceArgs.Aout_lbw,
+                        paceArgs.Aout,
+                        paceArgs.Dacp,
+                        paceArgs.Dacn);
+                }
+            }
+            if (enableBioZ)
+            {
+                startedBioz = true;
+                if (GetBioZInitArgsPointer != null)
+                {
+                    biozArgs = GetBioZInitArgsPointer();
+                    rpcClient.MAX30001.BIOZ_InitStart(
+                        biozArgs.En_bioz,
+                        biozArgs.Openp,
+                        biozArgs.Openn,
+                        biozArgs.Calp_sel,
+                        biozArgs.Caln_sel,
+                        biozArgs.CG_mode,
+                        biozArgs.B_fit,
+                        biozArgs.Rate,
+                        biozArgs.Ahpf,
+                        biozArgs.Ext_rbias,
+                        biozArgs.Gain,
+                        biozArgs.Dhpf,
+                        biozArgs.Dlpf,
+                        biozArgs.Fcgen,
+                        biozArgs.Cgmon,
+                        biozArgs.Cgmag,
+                        biozArgs.Phoff);
+                }
+            }
+            if (enableRToR)
+            {
+                startedRtoR = true;
+                if (GetRToRInitArgsPointer != null)
+                {
+                    rtorArgs = GetRToRInitArgsPointer();
+                    rpcClient.MAX30001.RtoR_InitStart(
+                        rtorArgs.En_rtor,
+                        rtorArgs.Wndw,
+                        rtorArgs.Gain,
+                        rtorArgs.Pavg,
+                        rtorArgs.Ptsf,
+                        rtorArgs.Hoff,
+                        rtorArgs.Ravg,
+                        rtorArgs.Rhsf,
+                        rtorArgs.Clr_rrint);
+                }
+
+                rToRCalculator = new RToRCalculator(frequencyMasterField, ecgArgs.Rate, ecgArgs.Dlpf, rtorArgs.Wndw);
+            }
+
+            /*rpcClient.MAX30001.Rbias_FMSTR_Init(
+                0,
+                0,
+                0,
+                0,
+                0);*/
+
+            rpcClient.MAX30001.INT_assignment(MAX30001.max30001_intrpt_Location.MAX30001_INT_B, MAX30001.max30001_intrpt_Location.MAX30001_NO_INT, MAX30001.max30001_intrpt_Location.MAX30001_NO_INT,  //  en_enint_loc,      en_eovf_loc,   en_fstint_loc,
+                      MAX30001.max30001_intrpt_Location.MAX30001_INT_2B, MAX30001.max30001_intrpt_Location.MAX30001_INT_B, MAX30001.max30001_intrpt_Location.MAX30001_NO_INT,  //  en_dcloffint_loc,  en_bint_loc,   en_bovf_loc,
+                      MAX30001.max30001_intrpt_Location.MAX30001_INT_2B, MAX30001.max30001_intrpt_Location.MAX30001_INT_2B, MAX30001.max30001_intrpt_Location.MAX30001_NO_INT,  //  en_bover_loc,      en_bundr_loc,  en_bcgmon_loc,
+                      MAX30001.max30001_intrpt_Location.MAX30001_INT_B, MAX30001.max30001_intrpt_Location.MAX30001_NO_INT, MAX30001.max30001_intrpt_Location.MAX30001_NO_INT,  //  en_pint_loc,       en_povf_loc,   en_pedge_loc,
+                      MAX30001.max30001_intrpt_Location.MAX30001_INT_2B, MAX30001.max30001_intrpt_Location.MAX30001_INT_B, MAX30001.max30001_intrpt_Location.MAX30001_NO_INT,  //  en_lonint_loc,     en_rrint_loc,  en_samp_loc,
+                      MAX30001.max30001_intrpt_type.MAX30001_INT_ODNR, MAX30001.max30001_intrpt_type.MAX30001_INT_ODNR);                //  intb_Type,         int2b_Type)
+
+            if (startedEcg | startedCal | startedPace | startedBioz | startedRtoR)
+            {
+                rpcClient.MAX30001.StartStreaming();
+            }
+
+            // Clear Lead Off
+            UpdateLeadOffState(lblLdoffPh, false);
+            UpdateLeadOffState(lblLdoffPl, false);
+            UpdateLeadOffState(lblLdoffNh, false);
+            UpdateLeadOffState(lblLdoffNl, false);
+            UpdateLeadOffState(lblBioZACOver, false);
+            UpdateLeadOffState(lblBioZACUnder, false); 
+
+            // Clear Charts 
+            chartECG.Series["Series"].Points.Clear();
+            chartECG.Series["SeriesRToR"].Points.Clear();
+            chartECG.Series["SeriesPace"].Points.Clear();
+            chartECG.Series["SeriesPaceFalling"].Points.Clear();
+            //chartRtoR.Series["Series"].Points.Clear();
+            chartBioz.Series["Series"].Points.Clear();
+            //chartPace.Series["Series"].Points.Clear();
+            InitChart();
+            fileLogData.Clear(); // Clear initiation points
+
+            // Reset R To R state
+            rToRRemoveOffset = 0;
+            lastRToRTime = -1;
+
+            // Clear Heart Rate
+            heartRateList = new List<double>(10);
+            lblHeartRateAverage10.Text = "--";
+            lblHeartRateBeatToBeat.Text = "--";
+
+#if CES_DEMO
+            hpf.Reset();
+#endif
+            btnMonitor.Text = "Stop Monitor";
+            if (StreamingStartStop != null)
+            {
+                StreamingStartStop(this, new StreamingStartStopEventArgs() { state = true });
+            }
+#if FILE_LOG
+            // Debug
+            DateTime localDate = DateTime.Now;
+
+            file = new StreamWriter("hsp_ecg_output_data.csv");
+            file.WriteLine("# " + localDate.ToString() + ", Sample Rate Register Setting: " + ecgArgs.Rate);
+            file.WriteLine(@"# ECG (μV)     Raw Integer");
+#endif
+
+            // DEBUG - simulate the "first" R To R value as a > 10 second value to see what happens
+            //DisplayRToR(0x600);
+        }
+        private void btnMonitor_Click(object sender, EventArgs e)
+        {
+            if (btnMonitor.Text == "Start Monitor")
+            {
+                if (Connected)
+                {
+                    //if (ckbxEcg.Checked | ckbxPace.Checked | ckbxBioz.Checked | ckbxRtoR.Checked)
+                    if (EnableECG | EnableBioZ)
+                        Start();
+                    else if (EnableRToR)
+                        MessageBox.Show("Also enable ECG for R-to-R streaming", "Streaming");
+                    else
+                        MessageBox.Show("Enable ECG or BioZ before starting streaming", "Streaming");
+                }
+            }
+            else
+            {
+                Stop();
+            }
+        }
+
+        private void Stop()
+        {
+            if (startedEcg | startedCal | startedPace | startedBioz | startedRtoR)
+            {
+                rpcClient.MAX30001.StopStreaming(connected);
+
+                //rpcClient.MAX30001.WriteReg(0x02, 0);
+                //rpcClient.MAX30001.WriteReg(0x03, 0);
+            }
+
+            startedCal = false;
+            startedEcg = false;
+            startedPace = false;
+            startedBioz = false;
+            startedRtoR = false;
+
+            btnMonitor.Text = "Start Monitor";
+            if (StreamingStartStop != null)
+                StreamingStartStop(this, new StreamingStartStopEventArgs() { state = false });
+
+#if FILE_LOG
+            // Debug
+            file.Close();
+#endif
+        }
+
+        // Clean up streaming 
+        public void Close()
+        {
+            // Disable streaming if enabled
+            if (StreamingStartStop != null && btnMonitor.Text == "Stop Monitor")
+            {
+                StreamingStartStop(this, new StreamingStartStopEventArgs() { state = false });
+                Stop();
+            }
+        }
+
+
+        private void chkbxCheckedChanged(object sender, EventArgs e)
+        {
+            /*
+            EnableDisableControls(CAL_init, ckbxCal.Checked);
+            EnableDisableControls(ECG_InitStart, ckbxEcg.Checked);
+            EnableDisableControls(PACE_InitStart, ckbxPace.Checked);
+            EnableDisableControls(BIOZ_InitStart, ckbxBioz.Checked);
+            EnableDisableControls(ECGFast_Init, ckbxEcg.Checked);
+            EnableDisableControls(RtoR_InitStart, ckbxRtoR.Checked);
+            */
+        }
+
+        private void btnStartTest_Click(object sender, EventArgs e)
+        {
+            System.Windows.Forms.DataVisualization.Charting.Chart test = chartECG;
+
+            double ymin = test.ChartAreas[0].AxisY.Minimum;  
+            double ymax = test.ChartAreas[0].AxisY.Maximum;
+            if (btnStartTest.Text == "Start Test")
+            {
+                rpcClient.MAX30001.StartTest();
+                btnStartTest.Text = "Stop Test";
+            }
+            else
+            {
+                Stop();
+                btnStartTest.Text = "Start Test";
+            }
+
+        }
+
+        public void SetDCLeadOff(int leadOffState)
+        {
+            if (LeadOffBit(leadOffState, 8)) // check for ECG
+            {
+                UpdateLeadOffState(lblLdoffPh, LeadOffBit(leadOffState, 3));
+                UpdateLeadOffState(lblLdoffPl, LeadOffBit(leadOffState, 2));
+                UpdateLeadOffState(lblLdoffNh, LeadOffBit(leadOffState, 1));
+                UpdateLeadOffState(lblLdoffNl, LeadOffBit(leadOffState, 0));
+            }
+            if (LeadOffBit(leadOffState, 9)) // check for BIOZ
+            {
+                UpdateLeadOffState(lblLdoffPh, LeadOffBit(leadOffState, 3));
+                UpdateLeadOffState(lblLdoffPl, LeadOffBit(leadOffState, 2));
+                UpdateLeadOffState(lblLdoffNh, LeadOffBit(leadOffState, 1));
+                UpdateLeadOffState(lblLdoffNl, LeadOffBit(leadOffState, 0));
+            }
+        }
+
+        public void SetACLeadOff(int leadOffState)
+        {
+            UpdateLeadOffState(lblBioZACOver, LeadOffBit(leadOffState, 0));
+            UpdateLeadOffState(lblBioZACUnder, LeadOffBit(leadOffState, 1));
+        }
+
+        //
+        // Update LeadOff GUI State
+        //
+        private void UpdateLeadOffState(TextBox tb, bool state)
+        {
+            tb.Text = (state == true) ? "1" : "0";
+            if (state == true) tb.BackColor = Color.LightGreen;
+            else tb.BackColor = Color.Yellow;
+        }
+
+        private void UpdateLeadOffState(Label lbl, bool state)
+        {
+            lbl.ForeColor = (state == true) ? MaximStyle.MaximColor.Red : MaximStyle.MaximColor.Green;
+        }
+
+        /* Inner Classes of EcgView */
+
+
+
+        /// <summary>
+        /// Information used to generate the X-axis of a chart
+        /// </summary>
+        public class ChartInfo
+        {
+            /// <summary>
+            /// Sample Rate
+            /// </summary>
+            private double sampleRate = 0;
+            public double SampleRate
+            {
+                get
+                {
+                    return sampleRate;
+                }
+                set
+                {
+                    sampleRate = value;
+                    points = Convert.ToInt32(length * sampleRate / average);
+                }
+            }
+
+            /// <summary>
+            /// Length of chart in seconds
+            /// </summary>
+            private int length = 1;
+            public int Length
+            {
+                get
+                {
+                    return length;
+                }
+                set
+                {
+                    length = value;
+                    points = Convert.ToInt32(length * sampleRate / average);
+                }
+            }
+
+            /// <summary>
+            /// Number of total points in chart
+            /// </summary>
+            private int points = 1;
+            public int Points
+            {
+                get
+                {
+                    return points;
+                }
+            }
+
+            public int Gain;
+
+            private int average = 1;
+            public int Average
+            {
+                get
+                {
+                    return average;
+                }
+                set
+                {
+                    average = value;
+                    points = Convert.ToInt32(length * sampleRate / average);
+                }
+            }
+
+            /// <summary>
+            /// Value passed the threshold is negative
+            /// </summary>
+            private int threshold = Int32.MaxValue;
+            public int Threshold
+            {
+                get
+                {
+                    return threshold;
+                }
+                set
+                {
+                    threshold = value;
+                }
+            }
+
+            /// <summary>
+            /// Amount to offset value by to convert to negative 
+            /// </summary>
+            private int offset = 0;
+            public int Offset
+            {
+                get
+                {
+                    return offset;
+                }
+                set
+                {
+                    offset = value;
+                }
+            }
+
+            /// <summary>
+            /// Number of bits to shift raw data by
+            /// </summary>
+            public int Shift;
+
+
+            /// <summary>
+            /// Current generator for BioZ
+            /// </summary>
+            public int CurrentGenerator;
+
+            public Chart Chart;
+
+            public String SeriesName;
+        }
+
+        public class PacePoint
+        {
+            public double Time;
+            public bool Polarity;
+
+            public PacePoint(double time, bool polarity)
+            {
+                this.Time = time;
+                this.Polarity = polarity;
+            }
+        }
+
+        // DEBUG
+        int offsetTest = 0;
+        private void button1_Click(object sender, EventArgs e)
+        {
+            //timer1.Enabled = !timer1.Enabled;
+            chartECG.Series["SeriesPace"].Points.AddXY(1.99354553222656 + offsetTest, 0.05 * (1));
+            chartECG.Series["SeriesPaceFalling"].Points.AddXY(1.99455261230469 + offsetTest, -0.08 * (1));
+
+            offsetTest += 100;
+        }
+
+        // DEBUG
+        private void timer1_Tick(object sender, EventArgs e)
+        {
+            /*
+            PartialArrayIntAvailableEventArgs ecg1 = new PartialArrayIntAvailableEventArgs();
+            PartialArrayIntAvailableEventArgs ecg2 = new PartialArrayIntAvailableEventArgs();
+            PartialArrayIntAvailableEventArgs rr1 = new PartialArrayIntAvailableEventArgs();
+
+            ecg1.array1 = new int[] { 0x00, 0x00, 0x00, 0x00, 0xfffff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
+            ecg2.array1 = new int[] { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
+            rr1.array1 = new int[] { 0x88 };
+
+            ecg1.reportID = PartialArrayIntAvailableEventArgs.PACKET_MAX30001_ECG;
+            ecg2.reportID = PartialArrayIntAvailableEventArgs.PACKET_MAX30001_ECG;
+            rr1.reportID = PartialArrayIntAvailableEventArgs.PACKET_MAX30001_RTOR;
+
+            if (clicks % 15 == 0)
+            {
+                On_AppendChart(this, ecg2);
+            }
+            else if (clicks % 5 == 0)
+            {
+                On_AppendChart(this, ecg1);
+                On_AppendChart(this, rr1);
+            }
+            else
+                On_AppendChart(this, ecg2);
+
+            clicks++;
+            */
+            DisplayEcg(new double[] { 0, 0, 0, 0, 1, 2, 3, 4, 5 }, null, new double[] {-10, -10, -10, -10, -10, -10, 4, -10, -10});
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HspGuiSourceV301/HSPGui/CustomControls/EcgView.resx	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,123 @@
+<?xml version="1.0" encoding="utf-8"?>
+<root>
+  <!-- 
+    Microsoft ResX Schema 
+    
+    Version 2.0
+    
+    The primary goals of this format is to allow a simple XML format 
+    that is mostly human readable. The generation and parsing of the 
+    various data types are done through the TypeConverter classes 
+    associated with the data types.
+    
+    Example:
+    
+    ... ado.net/XML headers & schema ...
+    <resheader name="resmimetype">text/microsoft-resx</resheader>
+    <resheader name="version">2.0</resheader>
+    <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+    <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+    <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
+    <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+    <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+        <value>[base64 mime encoded serialized .NET Framework object]</value>
+    </data>
+    <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+        <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
+        <comment>This is a comment</comment>
+    </data>
+                
+    There are any number of "resheader" rows that contain simple 
+    name/value pairs.
+    
+    Each data row contains a name, and value. The row also contains a 
+    type or mimetype. Type corresponds to a .NET class that support 
+    text/value conversion through the TypeConverter architecture. 
+    Classes that don't support this are serialized and stored with the 
+    mimetype set.
+    
+    The mimetype is used for serialized objects, and tells the 
+    ResXResourceReader how to depersist the object. This is currently not 
+    extensible. For a given mimetype the value must be set accordingly:
+    
+    Note - application/x-microsoft.net.object.binary.base64 is the format 
+    that the ResXResourceWriter will generate, however the reader can 
+    read any of the formats listed below.
+    
+    mimetype: application/x-microsoft.net.object.binary.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
+            : and then encoded with base64 encoding.
+    
+    mimetype: application/x-microsoft.net.object.soap.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+            : and then encoded with base64 encoding.
+
+    mimetype: application/x-microsoft.net.object.bytearray.base64
+    value   : The object must be serialized into a byte array 
+            : using a System.ComponentModel.TypeConverter
+            : and then encoded with base64 encoding.
+    -->
+  <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+    <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
+    <xsd:element name="root" msdata:IsDataSet="true">
+      <xsd:complexType>
+        <xsd:choice maxOccurs="unbounded">
+          <xsd:element name="metadata">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" />
+              </xsd:sequence>
+              <xsd:attribute name="name" use="required" type="xsd:string" />
+              <xsd:attribute name="type" type="xsd:string" />
+              <xsd:attribute name="mimetype" type="xsd:string" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="assembly">
+            <xsd:complexType>
+              <xsd:attribute name="alias" type="xsd:string" />
+              <xsd:attribute name="name" type="xsd:string" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="data">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+                <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
+              <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+              <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="resheader">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" />
+            </xsd:complexType>
+          </xsd:element>
+        </xsd:choice>
+      </xsd:complexType>
+    </xsd:element>
+  </xsd:schema>
+  <resheader name="resmimetype">
+    <value>text/microsoft-resx</value>
+  </resheader>
+  <resheader name="version">
+    <value>2.0</value>
+  </resheader>
+  <resheader name="reader">
+    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <resheader name="writer">
+    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <metadata name="timer1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
+    <value>17, 17</value>
+  </metadata>
+</root>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HspGuiSourceV301/HSPGui/CustomControls/IDataLoggingView.cs	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,76 @@
+/*******************************************************************************
+* Copyright (C) 2016 Maxim Integrated Products, Inc., All rights Reserved.
+* 
+* This software is protected by copyright laws of the United States and
+* of foreign countries. This material may also be protected by patent laws
+* and technology transfer regulations of the United States and of foreign
+* countries. This software is furnished under a license agreement and/or a
+* nondisclosure agreement and may only be used or reproduced in accordance
+* with the terms of those agreements. Dissemination of this information to
+* any party or parties not specified in the license agreement and/or
+* nondisclosure agreement is expressly prohibited.
+*
+* The above copyright notice and this permission notice shall be included
+* in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+* OTHER DEALINGS IN THE SOFTWARE.
+*
+* Except as contained in this notice, the name of Maxim Integrated
+* Products, Inc. shall not be used except as stated in the Maxim Integrated
+* Products, Inc. Branding Policy.
+*
+* The mere transfer of this software does not imply any licenses
+* of trade secrets, proprietary technology, copyrights, patents,
+* trademarks, maskwork rights, or any other form of intellectual
+* property whatsoever. Maxim Integrated Products, Inc. retains all
+* ownership rights.
+*******************************************************************************
+*/
+
+using System;
+namespace HealthSensorPlatform.CustomControls
+{
+    public interface IDataLoggingView
+    {
+        int AccelSampleRate { get; }
+        InitArgs.BIOZInitStart BioZArgs { get; set; }
+        void BioZFunction(bool enable);
+        bool Connected { get; set; }
+        InitArgs.EcgInitStart EcgArgs { get; set; }
+        bool EnableAccelerometer { get; set; }
+        bool EnableBioz { get; set; }
+        bool EnableEcg { get; set; }
+        bool EnableFMSTR { get; }
+        bool EnableOpticalHR { get; set; }
+        bool EnableOpticalMulti { get; set; }
+        bool EnableOpticalSpO2 { get; set; }
+        bool EnablePace { get; set; }
+        bool EnablePressure { get; set; }
+        bool EnableRToR { get; set; }
+        bool EnableTemperature1 { get; set; }
+        bool EnableTemperature2 { get; set; }
+        InitArgs.FMSTRInitStart FMSTRArgs { get; set; }
+        InitArgs.HRModeInitStart HRModeArgs { get; set; }
+        event EventHandler<EventArgs> LogDownloadStart;
+        event DataLoggingView.LoggingParametersHandler LoggingParametersChanged;
+        event EventHandler<EventArgs> MissionErase;
+        event EventHandler<EventArgs> MissionRead;
+        event EventHandler<EventArgs> MissionWrite;
+        InitArgs.MultiModeInitStart MultiModeArgs { get; set; }
+        InitArgs.PACEInitStart PaceArgs { get; set; }
+        void PaceFunction(bool enable);
+        bool ProcessGuiElements();
+        RPCSupport.RPCClient RPCClient { set; }
+        InitArgs.RToRInitStart RToRArgs { get; set; }
+        InitArgs.SpO2HRModeInitStart SpO2HRModeArgs { get; set; }
+        void UpdateArgs();
+        void UpdateGuiElements(HealthSensorPlatform.Model.Mission missionSettings);
+        bool ValidateGuiElements();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HspGuiSourceV301/HSPGui/CustomControls/IDeviceView.cs	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,57 @@
+/*******************************************************************************
+* Copyright (C) 2016 Maxim Integrated Products, Inc., All rights Reserved.
+* 
+* This software is protected by copyright laws of the United States and
+* of foreign countries. This material may also be protected by patent laws
+* and technology transfer regulations of the United States and of foreign
+* countries. This software is furnished under a license agreement and/or a
+* nondisclosure agreement and may only be used or reproduced in accordance
+* with the terms of those agreements. Dissemination of this information to
+* any party or parties not specified in the license agreement and/or
+* nondisclosure agreement is expressly prohibited.
+*
+* The above copyright notice and this permission notice shall be included
+* in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+* OTHER DEALINGS IN THE SOFTWARE.
+*
+* Except as contained in this notice, the name of Maxim Integrated
+* Products, Inc. shall not be used except as stated in the Maxim Integrated
+* Products, Inc. Branding Policy.
+*
+* The mere transfer of this software does not imply any licenses
+* of trade secrets, proprietary technology, copyrights, patents,
+* trademarks, maskwork rights, or any other form of intellectual
+* property whatsoever. Maxim Integrated Products, Inc. retains all
+* ownership rights.
+*******************************************************************************
+*/
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace HealthSensorPlatform.CustomControls
+{
+    /// <summary>
+    /// Device View Interface
+    /// </summary>
+    interface IDeviceView
+    {
+        /// <summary>
+        /// Accessor Connected for determining if the View can attempt to write/read to the part
+        /// </summary>
+        bool Connected
+        {
+            get;
+            set;
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HspGuiSourceV301/HSPGui/CustomControls/IEcgView.cs	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,81 @@
+/*******************************************************************************
+* Copyright (C) 2016 Maxim Integrated Products, Inc., All rights Reserved.
+* 
+* This software is protected by copyright laws of the United States and
+* of foreign countries. This material may also be protected by patent laws
+* and technology transfer regulations of the United States and of foreign
+* countries. This software is furnished under a license agreement and/or a
+* nondisclosure agreement and may only be used or reproduced in accordance
+* with the terms of those agreements. Dissemination of this information to
+* any party or parties not specified in the license agreement and/or
+* nondisclosure agreement is expressly prohibited.
+*
+* The above copyright notice and this permission notice shall be included
+* in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+* OTHER DEALINGS IN THE SOFTWARE.
+*
+* Except as contained in this notice, the name of Maxim Integrated
+* Products, Inc. shall not be used except as stated in the Maxim Integrated
+* Products, Inc. Branding Policy.
+*
+* The mere transfer of this software does not imply any licenses
+* of trade secrets, proprietary technology, copyrights, patents,
+* trademarks, maskwork rights, or any other form of intellectual
+* property whatsoever. Maxim Integrated Products, Inc. retains all
+* ownership rights.
+*******************************************************************************
+*/
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+using HealthSensorPlatform.View;
+
+namespace HealthSensorPlatform.CustomControls
+{
+    public interface IEcgView
+    {
+        EcgView.ChartInfo EcgInfo { get; }
+        EcgView.ChartInfo BioZInfo { get; }
+
+        // For R To R calculator
+        InitArgs.EcgInitStart EcgArgs { get; }
+        InitArgs.RToRInitStart RToRArgs { get; }
+        int MasterClockField { get; }
+
+        // For time increment calculation
+        double SampleRateEcg { get; }
+        double SampleRateBioZ { get; }
+
+        bool EnableECG { get; }
+        bool EnableBioZ { get; }
+        bool EnableRToR { get; }
+        bool EnablePace { get; }
+
+        bool EnableDCLeadOff { get; set; }
+        bool EnableEcgDCLeadOff { get; set; }
+        bool EnableBioZOverUnderRange { get; set; }
+
+        IHspSetting HspSetting { get; set; }
+
+        double MasterClockFrequency { get; }
+
+        double TimeResolution { get; }
+
+        event EventHandler<StreamingStartStopEventArgs> StreamingStartStop;
+
+        //int RToREcgPoints(int rToR, bool first);
+
+        //double RToRMillisecond(int rToR);
+
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HspGuiSourceV301/HSPGui/CustomControls/IFileLogView.cs	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,87 @@
+/*******************************************************************************
+* Copyright (C) 2016 Maxim Integrated Products, Inc., All rights Reserved.
+* 
+* This software is protected by copyright laws of the United States and
+* of foreign countries. This material may also be protected by patent laws
+* and technology transfer regulations of the United States and of foreign
+* countries. This software is furnished under a license agreement and/or a
+* nondisclosure agreement and may only be used or reproduced in accordance
+* with the terms of those agreements. Dissemination of this information to
+* any party or parties not specified in the license agreement and/or
+* nondisclosure agreement is expressly prohibited.
+*
+* The above copyright notice and this permission notice shall be included
+* in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+* OTHER DEALINGS IN THE SOFTWARE.
+*
+* Except as contained in this notice, the name of Maxim Integrated
+* Products, Inc. shall not be used except as stated in the Maxim Integrated
+* Products, Inc. Branding Policy.
+*
+* The mere transfer of this software does not imply any licenses
+* of trade secrets, proprietary technology, copyrights, patents,
+* trademarks, maskwork rights, or any other form of intellectual
+* property whatsoever. Maxim Integrated Products, Inc. retains all
+* ownership rights.
+*******************************************************************************
+*/
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+//using Maxim.Global;
+
+namespace MAX30205EVKit.View
+{
+    //public delegate void StartStopHandler(object sender, EventArgs e);
+
+    /// <summary>
+    /// View Interface which supports streaming data
+    /// </summary>
+    public interface IFileLogView
+    {
+        bool Enable { get; set; } // Some views can be disabled such as file
+
+        /// <summary>
+        /// Set start time for data
+        /// </summary>
+        DateTime StartTime { set; }
+
+        /// <summary>
+        /// Occurs when error from hardware
+        /// </summary>
+//        event EventHandler<ErrorEventArgs> Error;
+
+        //event EventHandler<PartialArrayIntAvailableEventArgs> PartialArrayIntAvailable;
+
+        bool SelectCSVFile(string fileName);
+
+        bool SelectCSVFile(string fileName, DateTime time);
+
+        /// <summary>
+        /// Notify the start or stop of streaming
+        /// </summary>
+        void StreamStartStop(int channelCount);
+
+        /// <summary>
+        /// Write string to file
+        /// </summary>
+        /// <param name="str"></param>
+        void WriteLine(string str);
+
+        /// <summary>
+        /// Write Temperature Data to CSV file
+        /// </summary>
+        void WriteTemp(double time, double tempr);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HspGuiSourceV301/HSPGui/CustomControls/ITemperatureView.cs	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,82 @@
+/*******************************************************************************
+* Copyright (C) 2016 Maxim Integrated Products, Inc., All rights Reserved.
+* 
+* This software is protected by copyright laws of the United States and
+* of foreign countries. This material may also be protected by patent laws
+* and technology transfer regulations of the United States and of foreign
+* countries. This software is furnished under a license agreement and/or a
+* nondisclosure agreement and may only be used or reproduced in accordance
+* with the terms of those agreements. Dissemination of this information to
+* any party or parties not specified in the license agreement and/or
+* nondisclosure agreement is expressly prohibited.
+*
+* The above copyright notice and this permission notice shall be included
+* in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+* OTHER DEALINGS IN THE SOFTWARE.
+*
+* Except as contained in this notice, the name of Maxim Integrated
+* Products, Inc. shall not be used except as stated in the Maxim Integrated
+* Products, Inc. Branding Policy.
+*
+* The mere transfer of this software does not imply any licenses
+* of trade secrets, proprietary technology, copyrights, patents,
+* trademarks, maskwork rights, or any other form of intellectual
+* property whatsoever. Maxim Integrated Products, Inc. retains all
+* ownership rights.
+*******************************************************************************
+*/
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+using System.Windows.Forms;
+using HealthSensorPlatform;
+
+namespace MAX30205EVKit.View
+{
+    interface ITemperatureView
+    {
+        bool UnitsCelsius { get; }
+
+        int RefreshRate { get; set; }
+
+        event EventHandler<EventArgs> ReadAll;
+        event EventHandler<EventArgs> UnitsChanged;
+        event EventHandler<TemperatureEventArgs> OverTemperatureChanged;
+        event EventHandler<TemperatureEventArgs> HystersisChanged;
+        event EventHandler<DataFormatEventArgs> DataFormatChanged;
+        event EventHandler<WriteRegisterEventArgs> WriteRegister;
+        event EventHandler<EventArgs> RequestReadTemperature;
+
+        void DisplayTemperature(int index, TemperatureValue temperature);
+        void DisplayOverTemperature(int index, TemperatureValue temperature);
+        void DisplayHysteresis(int index, TemperatureValue temperature);
+        void DisplayConfigurationRegister(int index, int hex);
+
+        void DisplayError(Control control, string message);
+    }
+
+    public class WriteRegisterEventArgs : EventArgs
+    {
+        public int Index;
+        public int Register;
+        public int Data;
+    }
+
+    public class TemperatureEventArgs : EventArgs
+    {
+        public int Index;
+        public double Temperature;
+        public TextBox Control;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HspGuiSourceV301/HSPGui/CustomControls/InitArgs.cs	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,576 @@
+/*******************************************************************************
+* Copyright (C) 2016 Maxim Integrated Products, Inc., All rights Reserved.
+* 
+* This software is protected by copyright laws of the United States and
+* of foreign countries. This material may also be protected by patent laws
+* and technology transfer regulations of the United States and of foreign
+* countries. This software is furnished under a license agreement and/or a
+* nondisclosure agreement and may only be used or reproduced in accordance
+* with the terms of those agreements. Dissemination of this information to
+* any party or parties not specified in the license agreement and/or
+* nondisclosure agreement is expressly prohibited.
+*
+* The above copyright notice and this permission notice shall be included
+* in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+* OTHER DEALINGS IN THE SOFTWARE.
+*
+* Except as contained in this notice, the name of Maxim Integrated
+* Products, Inc. shall not be used except as stated in the Maxim Integrated
+* Products, Inc. Branding Policy.
+*
+* The mere transfer of this software does not imply any licenses
+* of trade secrets, proprietary technology, copyrights, patents,
+* trademarks, maskwork rights, or any other form of intellectual
+* property whatsoever. Maxim Integrated Products, Inc. retains all
+* ownership rights.
+*******************************************************************************
+*/
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace HealthSensorPlatform.CustomControls
+{
+    /// <summary>
+    /// Data for initializing streaming or flash logging
+    /// </summary>
+    public class InitArgs
+    {
+        interface IInitArgs
+        {
+            string ToCommandString();
+            //IInitArgs FromIntArray(int[] array); 
+        }
+
+        public struct RbiasInit
+        {
+            public int En_rbias;
+            public int Rbias;
+            public int Rbiasp;
+            public int Rbiasn;
+            public int Fmstr;
+        }
+
+        public class EcgInitStart : IInitArgs
+        {
+            public int En_ecg;
+            public int Openp;
+            public int Openn;
+            public int Pol;
+            public int Calp_sel;
+            public int Caln_sel;
+            public int E_fit;
+            public int Rate;
+            public int Gain;
+            public int Dhpf;
+            public int Dlpf;
+
+            public string ToCommandString()
+            {
+                StringBuilder command = new StringBuilder();
+                command.Append(En_ecg.ToString("X2")).Append(" ");
+                command.Append(Openp.ToString("X2")).Append(" ");
+                command.Append(Openn.ToString("X2")).Append(" ");
+                command.Append(Pol.ToString("X2")).Append(" ");
+                command.Append(Calp_sel.ToString("X2")).Append(" ");
+                command.Append(Caln_sel.ToString("X2")).Append(" ");
+                command.Append(E_fit.ToString("X2")).Append(" ");
+                command.Append(Rate.ToString("X2")).Append(" ");
+                command.Append(Gain.ToString("X2")).Append(" ");
+                command.Append(Dhpf.ToString("X2")).Append(" ");
+                command.Append(Dlpf.ToString("X2"));
+
+                return command.ToString();
+            }
+
+            public int[] ToArray()
+            {
+                int[] array = new int[11];
+
+                array[0] = En_ecg;
+                array[1] = Openp;
+                array[2] = Openn;
+                array[3] = Pol;
+                array[4] = Calp_sel;
+                array[5] = Caln_sel;
+                array[6] = E_fit;
+                array[7] = Rate;
+                array[8] = Gain;
+                array[9] = Dhpf;
+                array[10] = Dlpf;
+
+                return array;
+            }
+
+            public EcgInitStart FromIntArray(int[] array)
+            {
+                if (array.Length == 11)
+                {
+                    En_ecg = array[0];
+                    Openp = array[1];
+                    Openn = array[2];
+                    Pol = array[3];
+                    Calp_sel = array[4];
+                    Caln_sel = array[5];
+                    E_fit = array[6];
+                    Rate = array[7];
+                    Gain = array[8];
+                    Dhpf = array[9];
+                    Dlpf = array[10];
+                }
+                else
+                {
+                    throw new InvalidOperationException("Array length incorrect");
+                }
+
+                return this;
+            }
+        } 
+
+        public struct EcgFastInit
+        {
+            public int Clr_Fast;
+            public int Fast;
+            public int Fast_Th;
+        }
+
+        public class FMSTRInitStart : IInitArgs
+        {
+            public int En_rbias;
+            public int Rbiasv;
+            public int Rbiasp;
+            public int Rbiasn;
+            public int Fmstr;
+
+            public string ToCommandString()
+            {
+                StringBuilder command = new StringBuilder();
+                command.Append(En_rbias.ToString("X2")).Append(" ");
+                command.Append(Rbiasv.ToString("X2")).Append(" ");
+                command.Append(Rbiasp.ToString("X2")).Append(" ");
+                command.Append(Rbiasn.ToString("X2")).Append(" ");
+                command.Append(Fmstr.ToString("X2"));
+
+                return command.ToString();
+            }
+
+            public FMSTRInitStart FromIntArray(int[] array)
+            {
+                if (array.Length == 5)
+                {
+                    En_rbias = array[0];
+                    Rbiasv = array[1];
+                    Rbiasp = array[2];
+                    Rbiasn = array[3];
+                    Fmstr = array[4];
+                }
+                else
+                {
+                    throw new InvalidOperationException("Array length incorrect");
+                }
+
+                return this;
+            }
+        }
+
+        public class PACEInitStart : IInitArgs
+        {
+            public int En_pace;
+            public int Clr_pedge;
+            public int Pol;
+            public int Gn_diff_off;
+            public int Gain;
+            public int Aout_lbw;
+            public int Aout;
+            public int Dacp;
+            public int Dacn;
+
+            public string ToCommandString()
+            {
+                StringBuilder command = new StringBuilder();
+                command.Append(En_pace.ToString("X2")).Append(" ");
+                command.Append(Clr_pedge.ToString("X2")).Append(" ");
+                command.Append(Gn_diff_off.ToString("X2")).Append(" ");
+                command.Append(Gain.ToString("X2")).Append(" ");
+                command.Append(Aout_lbw.ToString("X2")).Append(" ");
+                command.Append(Aout.ToString("X2")).Append(" ");
+                command.Append(Dacp.ToString("X2")).Append(" ");
+                command.Append(Dacn.ToString("X2"));
+
+                return command.ToString();
+            }
+
+            public int[] ToArray()
+            {
+                int[] array = new int[9];
+
+                array[0] = En_pace;
+                array[1] = Clr_pedge;
+                array[2] = Pol;
+                array[3] = Gn_diff_off;
+                array[4] = Gain;
+                array[5] = Aout_lbw;
+                array[6] = Aout;
+                array[7] = Dacp;
+                array[8] = Dacn;
+
+                return array;
+            }
+
+            public PACEInitStart FromIntArray(int[] array)
+            {
+                if (array.Length == 8)
+                {
+                    En_pace = array[0];
+                    Clr_pedge = array[1];
+                    Pol = array[2];
+                    Gn_diff_off = array[3];
+                    Gain = array[4];
+                    Aout_lbw = array[5];
+                    Dacp = array[6];
+                    Dacn = array[7];
+                }
+                else
+                {
+                    throw new InvalidOperationException("Array length incorrect");
+                }
+
+                return this;
+            }
+        }
+
+        public class BIOZInitStart : IInitArgs
+        {
+            public int En_bioz;
+            public int Openp;
+            public int Openn;
+            public int Calp_sel;
+            public int Caln_sel;
+            public int CG_mode;
+            public int B_fit;
+            public int Rate;
+            public int Ahpf;
+            public int Ext_rbias;
+            public int Gain;
+            public int Dhpf;
+            public int Dlpf;
+            public int Fcgen;
+            public int Cgmon;
+            public int Cgmag;
+            public int Phoff;
+
+            public string ToCommandString()
+            {
+                StringBuilder command = new StringBuilder();
+                command.Append(En_bioz.ToString("X2")).Append(" ");
+                command.Append(Openp.ToString("X2")).Append(" ");
+                command.Append(Openn.ToString("X2")).Append(" ");
+                command.Append(Calp_sel.ToString("X2")).Append(" ");
+                command.Append(Caln_sel.ToString("X2")).Append(" ");
+                command.Append(CG_mode.ToString("X2")).Append(" ");
+                command.Append(B_fit.ToString("X2")).Append(" ");
+                command.Append(Rate.ToString("X2")).Append(" ");
+                command.Append(Ahpf.ToString("X2")).Append(" ");
+                command.Append(Ext_rbias.ToString("X2")).Append(" ");
+                command.Append(Gain.ToString("X2")).Append(" ");
+                command.Append(Dhpf.ToString("X2")).Append(" ");
+                command.Append(Dlpf.ToString("X2")).Append(" ");
+                command.Append(Fcgen.ToString("X2")).Append(" ");
+                command.Append(Cgmon.ToString("X2")).Append(" ");
+                command.Append(Cgmag.ToString("X2")).Append(" ");
+                command.Append(Phoff.ToString("X2"));
+
+                return command.ToString();
+            }
+
+            public int[] ToArray()
+            {
+                int[] array = new int[17];
+
+                array[0] = En_bioz;
+                array[1] = Openp;
+                array[2] = Openn;
+                array[3] = Calp_sel;
+                array[4] = Caln_sel;
+                array[5] = CG_mode;
+                array[6] = B_fit;
+                array[7] = Rate;
+                array[8] = Ahpf;
+                array[9] = Ext_rbias;
+                array[10] = Gain;
+                array[11] = Dhpf;
+                array[12] = Dlpf;
+                array[13] = Fcgen;
+                array[14] = Cgmon;
+                array[15] = Cgmag;
+                array[16] = Phoff;
+
+                return array;
+            }
+
+            public BIOZInitStart FromIntArray(int[] array)
+            {
+                if (array.Length == 17)
+                {
+                    En_bioz = array[0];
+                    Openp = array[1];
+                    Openn = array[2];
+                    Calp_sel = array[3];
+                    Caln_sel = array[4];
+                    CG_mode = array[5];
+                    B_fit = array[6];
+                    Rate = array[7];
+                    Ahpf = array[8];
+                    Ext_rbias = array[9];
+                    Gain = array[10];
+                    Dhpf = array[11];
+                    Dlpf = array[12];
+                    Fcgen = array[13];
+                    Cgmon = array[14];
+                    Cgmag = array[15];
+                    Phoff = array[16];
+                }
+                else
+                {
+                    throw new InvalidOperationException("Array size incorrect");
+                }
+
+                return this;
+            }
+        }
+
+        public class RToRInitStart : IInitArgs
+        {
+            public int En_rtor;
+            public int Wndw;
+            public int Gain;
+            public int Pavg;
+            public int Ptsf;
+            public int Hoff;
+            public int Ravg;
+            public int Rhsf;
+            public int Clr_rrint;
+
+            public string ToCommandString()
+            {
+                StringBuilder command = new StringBuilder();
+                command.Append(En_rtor.ToString("X2")).Append(" ");
+                command.Append(Wndw.ToString("X2")).Append(" ");
+                command.Append(Gain.ToString("X2")).Append(" ");
+                command.Append(Pavg.ToString("X2")).Append(" ");
+                command.Append(Ptsf.ToString("X2")).Append(" ");
+                command.Append(Hoff.ToString("X2")).Append(" ");
+                command.Append(Ravg.ToString("X2")).Append(" ");
+                command.Append(Rhsf.ToString("X2")).Append(" ");
+                command.Append(Clr_rrint.ToString("X2"));
+
+                return command.ToString();
+            }
+
+            public int[] ToArray()
+            {
+                int[] array = new int[9];
+
+                array[0] = En_rtor;
+                array[1] = Wndw;
+                array[2] = Gain;
+                array[3] = Pavg;
+                array[4] = Ptsf;
+                array[5] = Hoff;
+                array[6] = Ravg;
+                array[7] = Rhsf;
+                array[8] = Clr_rrint;
+
+                return array;
+            }
+
+            public RToRInitStart FromIntArray(int[] array)
+            {
+                if (array.Length == 9)
+                {
+                    En_rtor = array[0];
+                    Wndw = array[1];
+                    Gain = array[2];
+                    Pavg = array[3];
+                    Ptsf = array[4];
+                    Hoff = array[5];
+                    Ravg = array[6];
+                    Rhsf = array[7];
+                    Clr_rrint = array[8];
+                }
+                else
+                {
+                    throw new InvalidOperationException("Array size incorrect");
+                }
+
+                return this;
+            }
+        }
+
+        public struct CalInitStart
+        {
+            public int Vmode;
+            public int Vmag;
+            public int Fcal;
+            public int Thigh;
+            public int Fifty;
+            public int En_Vcal;
+        }
+
+        public class SpO2HRModeInitStart : IInitArgs
+        {
+            public int FifoWaterlevelMark;
+            public int SampleAverage;
+            public int SampleRate;
+            public int PulseWidth;
+            public int RedLedCurrent;
+            public int IRLedCurrent;
+
+            public string ToCommandString()
+            {
+                StringBuilder command = new StringBuilder();
+                command.Append(FifoWaterlevelMark.ToString("X2")).Append(" ");
+                command.Append(SampleAverage.ToString("X2")).Append(" ");
+                command.Append(SampleRate.ToString("X2")).Append(" ");
+                command.Append(PulseWidth.ToString("X2")).Append(" ");
+                command.Append(RedLedCurrent.ToString("X2")).Append(" ");
+                command.Append(IRLedCurrent.ToString("X2"));
+
+                return command.ToString();
+            }
+
+            public SpO2HRModeInitStart FromIntArray(int[] array)
+            {
+                if (array.Length == 6)
+                {
+                    FifoWaterlevelMark = array[0];
+                    SampleAverage = array[1];
+                    SampleRate = array[2];
+                    PulseWidth = array[3];
+                    RedLedCurrent = array[4];
+                    IRLedCurrent = array[5];
+                }
+                else if (array.Length == 5)
+                {
+                    FifoWaterlevelMark = array[0];
+                    SampleAverage = array[1];
+                    SampleRate = array[2];
+                    PulseWidth = array[3];
+                    RedLedCurrent = array[4];
+                }
+                else
+                {
+                    throw new InvalidOperationException("Array size incorrect");
+                }
+
+                return this;
+            }
+        }
+
+        public class HRModeInitStart : IInitArgs
+        {
+            public int FifoWaterlevelMark;
+            public int SampleAverage;
+            public int SampleRate;
+            public int PulseWidth;
+            public int RedLedCurrent;
+            public int IRLedCurrent;
+
+            public string ToCommandString()
+            {
+                StringBuilder command = new StringBuilder();
+                command.Append(FifoWaterlevelMark.ToString("X2")).Append(" ");
+                command.Append(SampleAverage.ToString("X2")).Append(" ");
+                command.Append(SampleRate.ToString("X2")).Append(" ");
+                command.Append(PulseWidth.ToString("X2")).Append(" ");
+                command.Append(RedLedCurrent.ToString("X2"));
+
+                return command.ToString();
+            }
+
+            public HRModeInitStart FromIntArray(int[] array)
+            {
+                if (array.Length == 5)
+                {
+                    FifoWaterlevelMark = array[0];
+                    SampleAverage = array[1];
+                    SampleRate = array[2];
+                    PulseWidth = array[3];
+                    RedLedCurrent = array[4];
+                }
+                else
+                {
+                    throw new InvalidOperationException("Array size incorrect");
+                }
+
+                return this;
+            }
+        }
+
+        public class MultiModeInitStart : IInitArgs
+        {
+            public int FifoWaterlevelMark;
+            public int SampleAverage;
+            public int SampleRate;
+            public int PulseWidth;
+            public int RedLedCurrent;
+            public int IRLedCurrent;
+            public int GreenLedCurrent;
+            public int Slot1;
+            public int Slot2;
+            public int Slot3;
+            public int Slot4;
+
+            public string ToCommandString()
+            {
+                StringBuilder command = new StringBuilder();
+                command.Append(FifoWaterlevelMark.ToString("X2")).Append(" ");
+                command.Append(SampleAverage.ToString("X2")).Append(" ");
+                command.Append(SampleRate.ToString("X2")).Append(" ");
+                command.Append(PulseWidth.ToString("X2")).Append(" ");
+                command.Append(RedLedCurrent.ToString("X2")).Append(" ");
+                command.Append(IRLedCurrent.ToString("X2")).Append(" ");
+                command.Append(GreenLedCurrent.ToString("X2")).Append(" ");
+                command.Append(Slot1.ToString("X2")).Append(" ");
+                command.Append(Slot2.ToString("X2")).Append(" ");
+                command.Append(Slot3.ToString("X2")).Append(" ");
+                command.Append(Slot4.ToString("X2"));
+
+                return command.ToString();
+            }
+
+            public MultiModeInitStart FromIntArray(int[] array)
+            {
+                if (array.Length == 11)
+                {
+                    FifoWaterlevelMark = array[0];
+                    SampleAverage = array[1];
+                    SampleRate = array[2];
+                    PulseWidth = array[3];
+                    RedLedCurrent = array[4];
+                    IRLedCurrent = array[5];
+                    GreenLedCurrent = array[6];
+                    Slot1 = array[7];
+                    Slot2 = array[8];
+                    Slot3 = array[9];
+                    Slot4 = array[10];
+                }
+                else
+                {
+                    throw new InvalidOperationException("Array size incorrect");
+                }
+
+                return this;
+            }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HspGuiSourceV301/HSPGui/CustomControls/LoggingView.Designer.cs	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,903 @@
+namespace HealthSensorPlatform.CustomControls
+{
+    partial class DataLoggingView
+    {
+        /// <summary> 
+        /// Required designer variable.
+        /// </summary>
+        private System.ComponentModel.IContainer components = null;
+
+        /// <summary> 
+        /// Clean up any resources being used.
+        /// </summary>
+        /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
+        protected override void Dispose(bool disposing)
+        {
+            if (disposing && (components != null))
+            {
+                components.Dispose();
+            }
+            base.Dispose(disposing);
+        }
+
+        #region Component Designer generated code
+
+        /// <summary> 
+        /// Required method for Designer support - do not modify 
+        /// the contents of this method with the code editor.
+        /// </summary>
+        private void InitializeComponent()
+        {
+            this.components = new System.ComponentModel.Container();
+            this.btnRead = new MaximStyle.MaximButton();
+            this.btnErase = new MaximStyle.MaximButton();
+            this.btnWrite = new MaximStyle.MaximButton();
+            this.ckbxRtoR = new MaximStyle.MaximCheckBox();
+            this.ckbxBioz = new MaximStyle.MaximCheckBox();
+            this.ckbxPace = new MaximStyle.MaximCheckBox();
+            this.ckbxEcg = new MaximStyle.MaximCheckBox();
+            this.ckbxTemp1 = new MaximStyle.MaximCheckBox();
+            this.ckbxTemp2 = new MaximStyle.MaximCheckBox();
+            this.tbRtoRParameters = new System.Windows.Forms.TextBox();
+            this.tbBiozParameters = new System.Windows.Forms.TextBox();
+            this.tbPaceParameters = new System.Windows.Forms.TextBox();
+            this.tbEcgParameters = new System.Windows.Forms.TextBox();
+            this.txtTemp2SampleTime = new System.Windows.Forms.TextBox();
+            this.txtTemp1SampleTime = new System.Windows.Forms.TextBox();
+            this.txtPressureSampleTime = new System.Windows.Forms.TextBox();
+            this.ckbxPressure = new MaximStyle.MaximCheckBox();
+            this.ckbxAccel = new MaximStyle.MaximCheckBox();
+            this.groupBox4 = new System.Windows.Forms.GroupBox();
+            this.label6 = new System.Windows.Forms.Label();
+            this.rbMulti = new System.Windows.Forms.RadioButton();
+            this.rbHR = new System.Windows.Forms.RadioButton();
+            this.rbSPO2 = new System.Windows.Forms.RadioButton();
+            this.ckbxOpticalSensor = new System.Windows.Forms.CheckBox();
+            this.tbMultiParameters = new System.Windows.Forms.TextBox();
+            this.tbHRParameters = new System.Windows.Forms.TextBox();
+            this.tbSpO2Parameters = new System.Windows.Forms.TextBox();
+            this.btnTestMission = new System.Windows.Forms.Button();
+            this.btnTestWriteLogMemory = new System.Windows.Forms.Button();
+            this.btnTestReadLogMemory = new System.Windows.Forms.Button();
+            this.btnBulkErase = new System.Windows.Forms.Button();
+            this.btnLogSectorsErase = new System.Windows.Forms.Button();
+            this.grpPrePostCommands = new MaximStyle.MaximGroupBox();
+            this.label8 = new System.Windows.Forms.Label();
+            this.label7 = new System.Windows.Forms.Label();
+            this.tbPostCmd = new System.Windows.Forms.TextBox();
+            this.tbPreCmd = new System.Windows.Forms.TextBox();
+            this.maximGroupBox1 = new MaximStyle.MaximGroupBox();
+            this.maximGroupBox2 = new MaximStyle.MaximGroupBox();
+            this.cboAccelSampleRate = new MaximStyle.MaximComboBox();
+            this.label14 = new System.Windows.Forms.Label();
+            this.label13 = new System.Windows.Forms.Label();
+            this.label12 = new System.Windows.Forms.Label();
+            this.label11 = new System.Windows.Forms.Label();
+            this.label10 = new System.Windows.Forms.Label();
+            this.label9 = new System.Windows.Forms.Label();
+            this.maximGroupBox3 = new MaximStyle.MaximGroupBox();
+            this.cboOpticalMode = new MaximStyle.MaximComboBox();
+            this.label15 = new System.Windows.Forms.Label();
+            this.grpParameters = new MaximStyle.MaximGroupBox();
+            this.tbFMSTRParameters = new System.Windows.Forms.TextBox();
+            this.label23 = new System.Windows.Forms.Label();
+            this.label21 = new System.Windows.Forms.Label();
+            this.label20 = new System.Windows.Forms.Label();
+            this.label1 = new System.Windows.Forms.Label();
+            this.lblRToR = new System.Windows.Forms.Label();
+            this.lblBioZ = new System.Windows.Forms.Label();
+            this.lblPace = new System.Windows.Forms.Label();
+            this.label16 = new System.Windows.Forms.Label();
+            this.btnAdvanced = new MaximStyle.MaximButton();
+            this.btnSaveToFile = new MaximStyle.MaximButton();
+            this.maximGroupBox4 = new MaximStyle.MaximGroupBox();
+            this.label22 = new System.Windows.Forms.Label();
+            this.toolTip1 = new System.Windows.Forms.ToolTip(this.components);
+            this.groupBox4.SuspendLayout();
+            this.grpPrePostCommands.SuspendLayout();
+            this.maximGroupBox1.SuspendLayout();
+            this.maximGroupBox2.SuspendLayout();
+            this.maximGroupBox3.SuspendLayout();
+            this.grpParameters.SuspendLayout();
+            this.maximGroupBox4.SuspendLayout();
+            this.SuspendLayout();
+            // 
+            // btnRead
+            // 
+            this.btnRead.Location = new System.Drawing.Point(43, 179);
+            this.btnRead.Name = "btnRead";
+            this.btnRead.Size = new System.Drawing.Size(75, 23);
+            this.btnRead.TabIndex = 0;
+            this.btnRead.Text = "Read";
+            this.toolTip1.SetToolTip(this.btnRead, "Read mission settings and apply settings to device registers");
+            this.btnRead.UseVisualStyleBackColor = true;
+            this.btnRead.Click += new System.EventHandler(this.btnRead_Click);
+            // 
+            // btnErase
+            // 
+            this.btnErase.Location = new System.Drawing.Point(156, 179);
+            this.btnErase.Name = "btnErase";
+            this.btnErase.Size = new System.Drawing.Size(75, 23);
+            this.btnErase.TabIndex = 1;
+            this.btnErase.Text = "Erase";
+            this.toolTip1.SetToolTip(this.btnErase, "Erase mission");
+            this.btnErase.UseVisualStyleBackColor = true;
+            this.btnErase.Click += new System.EventHandler(this.btnErase_Click);
+            // 
+            // btnWrite
+            // 
+            this.btnWrite.Location = new System.Drawing.Point(271, 179);
+            this.btnWrite.Name = "btnWrite";
+            this.btnWrite.Size = new System.Drawing.Size(75, 23);
+            this.btnWrite.TabIndex = 2;
+            this.btnWrite.Text = "Write";
+            this.toolTip1.SetToolTip(this.btnWrite, "Write mission settings to flash and erase flash memory");
+            this.btnWrite.UseVisualStyleBackColor = true;
+            this.btnWrite.Click += new System.EventHandler(this.btnWrite_Click);
+            // 
+            // ckbxRtoR
+            // 
+            this.ckbxRtoR.AutoSize = true;
+            this.ckbxRtoR.Enabled = false;
+            this.ckbxRtoR.Location = new System.Drawing.Point(121, 64);
+            this.ckbxRtoR.Name = "ckbxRtoR";
+            this.ckbxRtoR.Size = new System.Drawing.Size(57, 17);
+            this.ckbxRtoR.TabIndex = 68;
+            this.ckbxRtoR.Text = "R-to-R";
+            this.ckbxRtoR.UseVisualStyleBackColor = true;
+            this.ckbxRtoR.CheckedChanged += new System.EventHandler(this.ckbxBioz_CheckedChanged);
+            // 
+            // ckbxBioz
+            // 
+            this.ckbxBioz.AutoSize = true;
+            this.ckbxBioz.Location = new System.Drawing.Point(121, 32);
+            this.ckbxBioz.Name = "ckbxBioz";
+            this.ckbxBioz.Size = new System.Drawing.Size(48, 17);
+            this.ckbxBioz.TabIndex = 67;
+            this.ckbxBioz.Text = "BioZ";
+            this.ckbxBioz.UseVisualStyleBackColor = true;
+            this.ckbxBioz.CheckedChanged += new System.EventHandler(this.ckbxBioz_CheckedChanged);
+            // 
+            // ckbxPace
+            // 
+            this.ckbxPace.AutoSize = true;
+            this.ckbxPace.Location = new System.Drawing.Point(22, 64);
+            this.ckbxPace.Name = "ckbxPace";
+            this.ckbxPace.Size = new System.Drawing.Size(51, 17);
+            this.ckbxPace.TabIndex = 66;
+            this.ckbxPace.Text = "Pace";
+            this.ckbxPace.UseVisualStyleBackColor = true;
+            this.ckbxPace.CheckedChanged += new System.EventHandler(this.ckbxBioz_CheckedChanged);
+            // 
+            // ckbxEcg
+            // 
+            this.ckbxEcg.AutoSize = true;
+            this.ckbxEcg.Location = new System.Drawing.Point(22, 32);
+            this.ckbxEcg.Name = "ckbxEcg";
+            this.ckbxEcg.Size = new System.Drawing.Size(48, 17);
+            this.ckbxEcg.TabIndex = 65;
+            this.ckbxEcg.Text = "ECG";
+            this.ckbxEcg.UseVisualStyleBackColor = true;
+            this.ckbxEcg.CheckedChanged += new System.EventHandler(this.ckbxBioz_CheckedChanged);
+            // 
+            // ckbxTemp1
+            // 
+            this.ckbxTemp1.AutoSize = true;
+            this.ckbxTemp1.Location = new System.Drawing.Point(18, 50);
+            this.ckbxTemp1.Name = "ckbxTemp1";
+            this.ckbxTemp1.Size = new System.Drawing.Size(95, 17);
+            this.ckbxTemp1.TabIndex = 69;
+            this.ckbxTemp1.Text = "Temperature 1";
+            this.ckbxTemp1.UseVisualStyleBackColor = true;
+            // 
+            // ckbxTemp2
+            // 
+            this.ckbxTemp2.AutoSize = true;
+            this.ckbxTemp2.Location = new System.Drawing.Point(18, 77);
+            this.ckbxTemp2.Name = "ckbxTemp2";
+            this.ckbxTemp2.Size = new System.Drawing.Size(95, 17);
+            this.ckbxTemp2.TabIndex = 70;
+            this.ckbxTemp2.Text = "Temperature 2";
+            this.ckbxTemp2.UseVisualStyleBackColor = true;
+            // 
+            // tbRtoRParameters
+            // 
+            this.tbRtoRParameters.Location = new System.Drawing.Point(76, 100);
+            this.tbRtoRParameters.Name = "tbRtoRParameters";
+            this.tbRtoRParameters.ReadOnly = true;
+            this.tbRtoRParameters.Size = new System.Drawing.Size(350, 20);
+            this.tbRtoRParameters.TabIndex = 80;
+            this.tbRtoRParameters.Text = "01 03 0F 00 03 01 00 00 01";
+            this.tbRtoRParameters.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
+            // 
+            // tbBiozParameters
+            // 
+            this.tbBiozParameters.Location = new System.Drawing.Point(76, 75);
+            this.tbBiozParameters.Name = "tbBiozParameters";
+            this.tbBiozParameters.ReadOnly = true;
+            this.tbBiozParameters.Size = new System.Drawing.Size(350, 20);
+            this.tbBiozParameters.TabIndex = 79;
+            this.tbBiozParameters.Text = "01 01 01 02 03 00 07 00 07 00 02 00 00 01 00 07 00";
+            this.tbBiozParameters.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
+            // 
+            // tbPaceParameters
+            // 
+            this.tbPaceParameters.Location = new System.Drawing.Point(76, 50);
+            this.tbPaceParameters.Name = "tbPaceParameters";
+            this.tbPaceParameters.ReadOnly = true;
+            this.tbPaceParameters.Size = new System.Drawing.Size(350, 20);
+            this.tbPaceParameters.TabIndex = 78;
+            this.tbPaceParameters.Text = "01 00 00 01 00 00 00 00 00";
+            this.tbPaceParameters.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
+            // 
+            // tbEcgParameters
+            // 
+            this.tbEcgParameters.Location = new System.Drawing.Point(76, 25);
+            this.tbEcgParameters.Name = "tbEcgParameters";
+            this.tbEcgParameters.ReadOnly = true;
+            this.tbEcgParameters.Size = new System.Drawing.Size(350, 20);
+            this.tbEcgParameters.TabIndex = 76;
+            this.tbEcgParameters.Text = "01 01 01 00 02 03 1F 00 02 00 01";
+            this.tbEcgParameters.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
+            // 
+            // txtTemp2SampleTime
+            // 
+            this.txtTemp2SampleTime.Location = new System.Drawing.Point(126, 75);
+            this.txtTemp2SampleTime.Name = "txtTemp2SampleTime";
+            this.txtTemp2SampleTime.Size = new System.Drawing.Size(52, 20);
+            this.txtTemp2SampleTime.TabIndex = 77;
+            this.txtTemp2SampleTime.Text = "10";
+            this.txtTemp2SampleTime.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
+            // 
+            // txtTemp1SampleTime
+            // 
+            this.txtTemp1SampleTime.Location = new System.Drawing.Point(126, 49);
+            this.txtTemp1SampleTime.Name = "txtTemp1SampleTime";
+            this.txtTemp1SampleTime.Size = new System.Drawing.Size(52, 20);
+            this.txtTemp1SampleTime.TabIndex = 75;
+            this.txtTemp1SampleTime.Text = "10";
+            this.txtTemp1SampleTime.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
+            // 
+            // txtPressureSampleTime
+            // 
+            this.txtPressureSampleTime.Location = new System.Drawing.Point(126, 101);
+            this.txtPressureSampleTime.Name = "txtPressureSampleTime";
+            this.txtPressureSampleTime.Size = new System.Drawing.Size(52, 20);
+            this.txtPressureSampleTime.TabIndex = 79;
+            this.txtPressureSampleTime.Text = "30";
+            this.txtPressureSampleTime.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
+            // 
+            // ckbxPressure
+            // 
+            this.ckbxPressure.AutoSize = true;
+            this.ckbxPressure.Location = new System.Drawing.Point(18, 103);
+            this.ckbxPressure.Name = "ckbxPressure";
+            this.ckbxPressure.Size = new System.Drawing.Size(74, 17);
+            this.ckbxPressure.TabIndex = 72;
+            this.ckbxPressure.Text = "Barometer";
+            this.ckbxPressure.UseVisualStyleBackColor = true;
+            // 
+            // ckbxAccel
+            // 
+            this.ckbxAccel.AutoSize = true;
+            this.ckbxAccel.Location = new System.Drawing.Point(18, 129);
+            this.ckbxAccel.Name = "ckbxAccel";
+            this.ckbxAccel.Size = new System.Drawing.Size(94, 17);
+            this.ckbxAccel.TabIndex = 71;
+            this.ckbxAccel.Text = "Accelerometer";
+            this.ckbxAccel.UseVisualStyleBackColor = true;
+            // 
+            // groupBox4
+            // 
+            this.groupBox4.Controls.Add(this.label6);
+            this.groupBox4.Controls.Add(this.rbMulti);
+            this.groupBox4.Controls.Add(this.rbHR);
+            this.groupBox4.Controls.Add(this.rbSPO2);
+            this.groupBox4.Controls.Add(this.ckbxOpticalSensor);
+            this.groupBox4.Location = new System.Drawing.Point(24, 568);
+            this.groupBox4.Name = "groupBox4";
+            this.groupBox4.Size = new System.Drawing.Size(538, 128);
+            this.groupBox4.TabIndex = 74;
+            this.groupBox4.TabStop = false;
+            this.groupBox4.Text = "Optical";
+            this.groupBox4.Visible = false;
+            // 
+            // label6
+            // 
+            this.label6.AutoSize = true;
+            this.label6.Location = new System.Drawing.Point(215, 22);
+            this.label6.Name = "label6";
+            this.label6.Size = new System.Drawing.Size(60, 13);
+            this.label6.TabIndex = 81;
+            this.label6.Text = "Parameters";
+            // 
+            // rbMulti
+            // 
+            this.rbMulti.AutoSize = true;
+            this.rbMulti.Location = new System.Drawing.Point(130, 88);
+            this.rbMulti.Name = "rbMulti";
+            this.rbMulti.Size = new System.Drawing.Size(77, 17);
+            this.rbMulti.TabIndex = 75;
+            this.rbMulti.TabStop = true;
+            this.rbMulti.Text = "Multi Mode";
+            this.rbMulti.UseVisualStyleBackColor = true;
+            // 
+            // rbHR
+            // 
+            this.rbHR.AutoSize = true;
+            this.rbHR.Location = new System.Drawing.Point(130, 65);
+            this.rbHR.Name = "rbHR";
+            this.rbHR.Size = new System.Drawing.Size(71, 17);
+            this.rbHR.TabIndex = 74;
+            this.rbHR.TabStop = true;
+            this.rbHR.Text = "HR Mode";
+            this.rbHR.UseVisualStyleBackColor = true;
+            // 
+            // rbSPO2
+            // 
+            this.rbSPO2.AutoSize = true;
+            this.rbSPO2.Location = new System.Drawing.Point(130, 42);
+            this.rbSPO2.Name = "rbSPO2";
+            this.rbSPO2.Size = new System.Drawing.Size(82, 17);
+            this.rbSPO2.TabIndex = 73;
+            this.rbSPO2.TabStop = true;
+            this.rbSPO2.Text = "SpO2 Mode";
+            this.rbSPO2.UseVisualStyleBackColor = true;
+            // 
+            // ckbxOpticalSensor
+            // 
+            this.ckbxOpticalSensor.AutoSize = true;
+            this.ckbxOpticalSensor.Location = new System.Drawing.Point(18, 22);
+            this.ckbxOpticalSensor.Name = "ckbxOpticalSensor";
+            this.ckbxOpticalSensor.Size = new System.Drawing.Size(95, 17);
+            this.ckbxOpticalSensor.TabIndex = 72;
+            this.ckbxOpticalSensor.Text = "Optical Sensor";
+            this.ckbxOpticalSensor.UseVisualStyleBackColor = true;
+            // 
+            // tbMultiParameters
+            // 
+            this.tbMultiParameters.Location = new System.Drawing.Point(76, 200);
+            this.tbMultiParameters.Name = "tbMultiParameters";
+            this.tbMultiParameters.ReadOnly = true;
+            this.tbMultiParameters.Size = new System.Drawing.Size(350, 20);
+            this.tbMultiParameters.TabIndex = 83;
+            this.tbMultiParameters.Text = "00 02 01 02 7F 7F 7F 03 01 03 02";
+            this.tbMultiParameters.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
+            // 
+            // tbHRParameters
+            // 
+            this.tbHRParameters.Location = new System.Drawing.Point(76, 175);
+            this.tbHRParameters.Name = "tbHRParameters";
+            this.tbHRParameters.ReadOnly = true;
+            this.tbHRParameters.Size = new System.Drawing.Size(350, 20);
+            this.tbHRParameters.TabIndex = 82;
+            this.tbHRParameters.Text = "00 02 01 02 1F";
+            this.tbHRParameters.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
+            // 
+            // tbSpO2Parameters
+            // 
+            this.tbSpO2Parameters.Location = new System.Drawing.Point(76, 150);
+            this.tbSpO2Parameters.Name = "tbSpO2Parameters";
+            this.tbSpO2Parameters.ReadOnly = true;
+            this.tbSpO2Parameters.Size = new System.Drawing.Size(350, 20);
+            this.tbSpO2Parameters.TabIndex = 81;
+            this.tbSpO2Parameters.Text = "0F 02 01 02 1F 1F";
+            this.tbSpO2Parameters.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
+            // 
+            // btnTestMission
+            // 
+            this.btnTestMission.Location = new System.Drawing.Point(579, 404);
+            this.btnTestMission.Name = "btnTestMission";
+            this.btnTestMission.Size = new System.Drawing.Size(135, 23);
+            this.btnTestMission.TabIndex = 75;
+            this.btnTestMission.Text = "Test Mission";
+            this.btnTestMission.UseVisualStyleBackColor = true;
+            this.btnTestMission.Visible = false;
+            this.btnTestMission.Click += new System.EventHandler(this.btnTestMission_Click);
+            // 
+            // btnTestWriteLogMemory
+            // 
+            this.btnTestWriteLogMemory.Location = new System.Drawing.Point(579, 433);
+            this.btnTestWriteLogMemory.Name = "btnTestWriteLogMemory";
+            this.btnTestWriteLogMemory.Size = new System.Drawing.Size(135, 23);
+            this.btnTestWriteLogMemory.TabIndex = 76;
+            this.btnTestWriteLogMemory.Text = "Test Write Log Memory";
+            this.btnTestWriteLogMemory.UseVisualStyleBackColor = true;
+            this.btnTestWriteLogMemory.Visible = false;
+            this.btnTestWriteLogMemory.Click += new System.EventHandler(this.btnTestWriteLogMemory_Click);
+            // 
+            // btnTestReadLogMemory
+            // 
+            this.btnTestReadLogMemory.Location = new System.Drawing.Point(579, 462);
+            this.btnTestReadLogMemory.Name = "btnTestReadLogMemory";
+            this.btnTestReadLogMemory.Size = new System.Drawing.Size(135, 23);
+            this.btnTestReadLogMemory.TabIndex = 77;
+            this.btnTestReadLogMemory.Text = "Test Read Log Memory";
+            this.btnTestReadLogMemory.UseVisualStyleBackColor = true;
+            this.btnTestReadLogMemory.Visible = false;
+            this.btnTestReadLogMemory.Click += new System.EventHandler(this.btnTestReadLogMemory_Click);
+            // 
+            // btnBulkErase
+            // 
+            this.btnBulkErase.Location = new System.Drawing.Point(579, 491);
+            this.btnBulkErase.Name = "btnBulkErase";
+            this.btnBulkErase.Size = new System.Drawing.Size(135, 23);
+            this.btnBulkErase.TabIndex = 78;
+            this.btnBulkErase.Text = "Bulk Erase";
+            this.btnBulkErase.UseVisualStyleBackColor = true;
+            this.btnBulkErase.Visible = false;
+            this.btnBulkErase.Click += new System.EventHandler(this.btnBulkErase_Click);
+            // 
+            // btnLogSectorsErase
+            // 
+            this.btnLogSectorsErase.Location = new System.Drawing.Point(579, 520);
+            this.btnLogSectorsErase.Name = "btnLogSectorsErase";
+            this.btnLogSectorsErase.Size = new System.Drawing.Size(135, 23);
+            this.btnLogSectorsErase.TabIndex = 79;
+            this.btnLogSectorsErase.Text = "Log Sectors Erase";
+            this.btnLogSectorsErase.UseVisualStyleBackColor = true;
+            this.btnLogSectorsErase.Visible = false;
+            this.btnLogSectorsErase.Click += new System.EventHandler(this.btnLogSectorsErase_Click);
+            // 
+            // grpPrePostCommands
+            // 
+            this.grpPrePostCommands.BackgroundColor = System.Drawing.Color.White;
+            this.grpPrePostCommands.Controls.Add(this.label8);
+            this.grpPrePostCommands.Controls.Add(this.label7);
+            this.grpPrePostCommands.Controls.Add(this.tbPostCmd);
+            this.grpPrePostCommands.Controls.Add(this.tbPreCmd);
+            this.grpPrePostCommands.Location = new System.Drawing.Point(15, 440);
+            this.grpPrePostCommands.Name = "grpPrePostCommands";
+            this.grpPrePostCommands.Size = new System.Drawing.Size(462, 74);
+            this.grpPrePostCommands.TabIndex = 80;
+            this.grpPrePostCommands.TabStop = false;
+            this.grpPrePostCommands.Text = "Pre/Post RPC Commands";
+            this.grpPrePostCommands.Visible = false;
+            // 
+            // label8
+            // 
+            this.label8.AutoSize = true;
+            this.label8.Location = new System.Drawing.Point(6, 53);
+            this.label8.Name = "label8";
+            this.label8.Size = new System.Drawing.Size(33, 13);
+            this.label8.TabIndex = 85;
+            this.label8.Text = "Suffix";
+            // 
+            // label7
+            // 
+            this.label7.AutoSize = true;
+            this.label7.Location = new System.Drawing.Point(6, 27);
+            this.label7.Name = "label7";
+            this.label7.Size = new System.Drawing.Size(33, 13);
+            this.label7.TabIndex = 79;
+            this.label7.Text = "Prefix";
+            // 
+            // tbPostCmd
+            // 
+            this.tbPostCmd.Location = new System.Drawing.Point(76, 50);
+            this.tbPostCmd.Name = "tbPostCmd";
+            this.tbPostCmd.Size = new System.Drawing.Size(350, 20);
+            this.tbPostCmd.TabIndex = 84;
+            this.tbPostCmd.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
+            // 
+            // tbPreCmd
+            // 
+            this.tbPreCmd.Location = new System.Drawing.Point(76, 24);
+            this.tbPreCmd.Name = "tbPreCmd";
+            this.tbPreCmd.Size = new System.Drawing.Size(350, 20);
+            this.tbPreCmd.TabIndex = 82;
+            this.tbPreCmd.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
+            // 
+            // maximGroupBox1
+            // 
+            this.maximGroupBox1.BackgroundColor = System.Drawing.Color.White;
+            this.maximGroupBox1.Controls.Add(this.ckbxEcg);
+            this.maximGroupBox1.Controls.Add(this.ckbxPace);
+            this.maximGroupBox1.Controls.Add(this.ckbxBioz);
+            this.maximGroupBox1.Controls.Add(this.ckbxRtoR);
+            this.maximGroupBox1.Location = new System.Drawing.Point(21, 5);
+            this.maximGroupBox1.Name = "maximGroupBox1";
+            this.maximGroupBox1.Size = new System.Drawing.Size(220, 100);
+            this.maximGroupBox1.TabIndex = 81;
+            this.maximGroupBox1.TabStop = false;
+            this.maximGroupBox1.Text = "ECG Channel Log Enable";
+            // 
+            // maximGroupBox2
+            // 
+            this.maximGroupBox2.BackgroundColor = System.Drawing.Color.White;
+            this.maximGroupBox2.Controls.Add(this.cboAccelSampleRate);
+            this.maximGroupBox2.Controls.Add(this.label14);
+            this.maximGroupBox2.Controls.Add(this.label13);
+            this.maximGroupBox2.Controls.Add(this.label12);
+            this.maximGroupBox2.Controls.Add(this.label11);
+            this.maximGroupBox2.Controls.Add(this.ckbxAccel);
+            this.maximGroupBox2.Controls.Add(this.txtPressureSampleTime);
+            this.maximGroupBox2.Controls.Add(this.label10);
+            this.maximGroupBox2.Controls.Add(this.label9);
+            this.maximGroupBox2.Controls.Add(this.ckbxPressure);
+            this.maximGroupBox2.Controls.Add(this.ckbxTemp1);
+            this.maximGroupBox2.Controls.Add(this.txtTemp2SampleTime);
+            this.maximGroupBox2.Controls.Add(this.ckbxTemp2);
+            this.maximGroupBox2.Controls.Add(this.txtTemp1SampleTime);
+            this.maximGroupBox2.Location = new System.Drawing.Point(247, 5);
+            this.maximGroupBox2.Name = "maximGroupBox2";
+            this.maximGroupBox2.Size = new System.Drawing.Size(230, 168);
+            this.maximGroupBox2.TabIndex = 82;
+            this.maximGroupBox2.TabStop = false;
+            this.maximGroupBox2.Text = "Other Channel Log Enable";
+            // 
+            // cboAccelSampleRate
+            // 
+            this.cboAccelSampleRate.BackColor = System.Drawing.Color.White;
+            this.cboAccelSampleRate.DropDownHeight = 200;
+            this.cboAccelSampleRate.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
+            this.cboAccelSampleRate.DropDownWidth = 52;
+            this.cboAccelSampleRate.Items.AddRange(new object[] {
+            "1",
+            "10",
+            "25",
+            "50",
+            "100",
+            "200",
+            "400"});
+            this.cboAccelSampleRate.Location = new System.Drawing.Point(126, 127);
+            this.cboAccelSampleRate.Name = "cboAccelSampleRate";
+            this.cboAccelSampleRate.Size = new System.Drawing.Size(52, 21);
+            this.cboAccelSampleRate.TabIndex = 86;
+            this.cboAccelSampleRate.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
+            this.cboAccelSampleRate.TextAlignDropDownList = System.Windows.Forms.HorizontalAlignment.Left;
+            // 
+            // label14
+            // 
+            this.label14.AutoSize = true;
+            this.label14.Location = new System.Drawing.Point(184, 130);
+            this.label14.Name = "label14";
+            this.label14.Size = new System.Drawing.Size(20, 13);
+            this.label14.TabIndex = 83;
+            this.label14.Text = "Hz";
+            // 
+            // label13
+            // 
+            this.label13.AutoSize = true;
+            this.label13.Location = new System.Drawing.Point(184, 104);
+            this.label13.Name = "label13";
+            this.label13.Size = new System.Drawing.Size(12, 13);
+            this.label13.TabIndex = 82;
+            this.label13.Text = "s";
+            // 
+            // label12
+            // 
+            this.label12.AutoSize = true;
+            this.label12.Location = new System.Drawing.Point(184, 80);
+            this.label12.Name = "label12";
+            this.label12.Size = new System.Drawing.Size(12, 13);
+            this.label12.TabIndex = 81;
+            this.label12.Text = "s";
+            // 
+            // label11
+            // 
+            this.label11.AutoSize = true;
+            this.label11.Location = new System.Drawing.Point(184, 52);
+            this.label11.Name = "label11";
+            this.label11.Size = new System.Drawing.Size(12, 13);
+            this.label11.TabIndex = 80;
+            this.label11.Text = "s";
+            // 
+            // label10
+            // 
+            this.label10.AutoSize = true;
+            this.label10.Location = new System.Drawing.Point(123, 26);
+            this.label10.Name = "label10";
+            this.label10.Size = new System.Drawing.Size(30, 13);
+            this.label10.TabIndex = 79;
+            this.label10.Text = "Rate";
+            // 
+            // label9
+            // 
+            this.label9.AutoSize = true;
+            this.label9.Location = new System.Drawing.Point(30, 26);
+            this.label9.Name = "label9";
+            this.label9.Size = new System.Drawing.Size(40, 13);
+            this.label9.TabIndex = 78;
+            this.label9.Text = "Sensor";
+            // 
+            // maximGroupBox3
+            // 
+            this.maximGroupBox3.BackgroundColor = System.Drawing.Color.White;
+            this.maximGroupBox3.Controls.Add(this.cboOpticalMode);
+            this.maximGroupBox3.Controls.Add(this.label15);
+            this.maximGroupBox3.Location = new System.Drawing.Point(21, 111);
+            this.maximGroupBox3.Name = "maximGroupBox3";
+            this.maximGroupBox3.Size = new System.Drawing.Size(220, 62);
+            this.maximGroupBox3.TabIndex = 83;
+            this.maximGroupBox3.TabStop = false;
+            this.maximGroupBox3.Text = "Optical Log Enable";
+            // 
+            // cboOpticalMode
+            // 
+            this.cboOpticalMode.BackColor = System.Drawing.Color.White;
+            this.cboOpticalMode.DropDownHeight = 200;
+            this.cboOpticalMode.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
+            this.cboOpticalMode.DropDownWidth = 95;
+            this.cboOpticalMode.Items.AddRange(new object[] {
+            "None",
+            "SpO2",
+            "HR",
+            "Multi"});
+            this.cboOpticalMode.Location = new System.Drawing.Point(86, 28);
+            this.cboOpticalMode.Name = "cboOpticalMode";
+            this.cboOpticalMode.Size = new System.Drawing.Size(95, 21);
+            this.cboOpticalMode.TabIndex = 1;
+            this.cboOpticalMode.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
+            this.cboOpticalMode.TextAlignDropDownList = System.Windows.Forms.HorizontalAlignment.Left;
+            this.cboOpticalMode.SelectedIndexChanged += new System.EventHandler(this.cboOpticalMode_SelectedIndexChanged);
+            // 
+            // label15
+            // 
+            this.label15.AutoSize = true;
+            this.label15.Location = new System.Drawing.Point(19, 31);
+            this.label15.Name = "label15";
+            this.label15.Size = new System.Drawing.Size(34, 13);
+            this.label15.TabIndex = 0;
+            this.label15.Text = "Mode";
+            // 
+            // grpParameters
+            // 
+            this.grpParameters.BackgroundColor = System.Drawing.Color.White;
+            this.grpParameters.Controls.Add(this.tbFMSTRParameters);
+            this.grpParameters.Controls.Add(this.label23);
+            this.grpParameters.Controls.Add(this.label21);
+            this.grpParameters.Controls.Add(this.tbMultiParameters);
+            this.grpParameters.Controls.Add(this.label20);
+            this.grpParameters.Controls.Add(this.tbHRParameters);
+            this.grpParameters.Controls.Add(this.label1);
+            this.grpParameters.Controls.Add(this.lblRToR);
+            this.grpParameters.Controls.Add(this.lblBioZ);
+            this.grpParameters.Controls.Add(this.tbSpO2Parameters);
+            this.grpParameters.Controls.Add(this.lblPace);
+            this.grpParameters.Controls.Add(this.tbRtoRParameters);
+            this.grpParameters.Controls.Add(this.label16);
+            this.grpParameters.Controls.Add(this.tbBiozParameters);
+            this.grpParameters.Controls.Add(this.tbEcgParameters);
+            this.grpParameters.Controls.Add(this.tbPaceParameters);
+            this.grpParameters.Location = new System.Drawing.Point(15, 209);
+            this.grpParameters.Name = "grpParameters";
+            this.grpParameters.Size = new System.Drawing.Size(462, 229);
+            this.grpParameters.TabIndex = 84;
+            this.grpParameters.TabStop = false;
+            this.grpParameters.Text = "Parameters";
+            this.grpParameters.Visible = false;
+            // 
+            // tbFMSTRParameters
+            // 
+            this.tbFMSTRParameters.Location = new System.Drawing.Point(76, 125);
+            this.tbFMSTRParameters.Name = "tbFMSTRParameters";
+            this.tbFMSTRParameters.ReadOnly = true;
+            this.tbFMSTRParameters.Size = new System.Drawing.Size(350, 20);
+            this.tbFMSTRParameters.TabIndex = 88;
+            this.tbFMSTRParameters.Text = "00 02 01 01 00";
+            this.tbFMSTRParameters.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
+            // 
+            // label23
+            // 
+            this.label23.AutoSize = true;
+            this.label23.Location = new System.Drawing.Point(14, 128);
+            this.label23.Name = "label23";
+            this.label23.Size = new System.Drawing.Size(44, 13);
+            this.label23.TabIndex = 87;
+            this.label23.Text = "FMSTR";
+            // 
+            // label21
+            // 
+            this.label21.AutoSize = true;
+            this.label21.Location = new System.Drawing.Point(14, 203);
+            this.label21.Name = "label21";
+            this.label21.Size = new System.Drawing.Size(29, 13);
+            this.label21.TabIndex = 86;
+            this.label21.Text = "Multi";
+            // 
+            // label20
+            // 
+            this.label20.AutoSize = true;
+            this.label20.Location = new System.Drawing.Point(14, 178);
+            this.label20.Name = "label20";
+            this.label20.Size = new System.Drawing.Size(23, 13);
+            this.label20.TabIndex = 85;
+            this.label20.Text = "HR";
+            // 
+            // label1
+            // 
+            this.label1.AutoSize = true;
+            this.label1.Location = new System.Drawing.Point(14, 153);
+            this.label1.Name = "label1";
+            this.label1.Size = new System.Drawing.Size(34, 13);
+            this.label1.TabIndex = 84;
+            this.label1.Text = "SpO2";
+            // 
+            // lblRToR
+            // 
+            this.lblRToR.AutoSize = true;
+            this.lblRToR.Location = new System.Drawing.Point(14, 103);
+            this.lblRToR.Name = "lblRToR";
+            this.lblRToR.Size = new System.Drawing.Size(38, 13);
+            this.lblRToR.TabIndex = 83;
+            this.lblRToR.Text = "R-to-R";
+            // 
+            // lblBioZ
+            // 
+            this.lblBioZ.AutoSize = true;
+            this.lblBioZ.Location = new System.Drawing.Point(14, 78);
+            this.lblBioZ.Name = "lblBioZ";
+            this.lblBioZ.Size = new System.Drawing.Size(29, 13);
+            this.lblBioZ.TabIndex = 82;
+            this.lblBioZ.Text = "BioZ";
+            // 
+            // lblPace
+            // 
+            this.lblPace.AutoSize = true;
+            this.lblPace.Location = new System.Drawing.Point(14, 53);
+            this.lblPace.Name = "lblPace";
+            this.lblPace.Size = new System.Drawing.Size(32, 13);
+            this.lblPace.TabIndex = 81;
+            this.lblPace.Text = "Pace";
+            // 
+            // label16
+            // 
+            this.label16.AutoSize = true;
+            this.label16.Location = new System.Drawing.Point(14, 28);
+            this.label16.Name = "label16";
+            this.label16.Size = new System.Drawing.Size(29, 13);
+            this.label16.TabIndex = 0;
+            this.label16.Text = "ECG";
+            // 
+            // btnAdvanced
+            // 
+            this.btnAdvanced.Location = new System.Drawing.Point(382, 179);
+            this.btnAdvanced.Name = "btnAdvanced";
+            this.btnAdvanced.Size = new System.Drawing.Size(75, 23);
+            this.btnAdvanced.TabIndex = 85;
+            this.btnAdvanced.Text = "Advanced";
+            this.toolTip1.SetToolTip(this.btnAdvanced, "Show raw parameters");
+            this.btnAdvanced.UseVisualStyleBackColor = true;
+            this.btnAdvanced.Click += new System.EventHandler(this.btnAdvanced_Click);
+            // 
+            // btnSaveToFile
+            // 
+            this.btnSaveToFile.Location = new System.Drawing.Point(70, 64);
+            this.btnSaveToFile.Name = "btnSaveToFile";
+            this.btnSaveToFile.Size = new System.Drawing.Size(75, 23);
+            this.btnSaveToFile.TabIndex = 86;
+            this.btnSaveToFile.Text = "Save to File";
+            this.toolTip1.SetToolTip(this.btnSaveToFile, "Download data to csv file.");
+            this.btnSaveToFile.UseVisualStyleBackColor = true;
+            this.btnSaveToFile.Click += new System.EventHandler(this.btnSaveToFile_Click);
+            // 
+            // maximGroupBox4
+            // 
+            this.maximGroupBox4.BackgroundColor = System.Drawing.Color.White;
+            this.maximGroupBox4.Controls.Add(this.label22);
+            this.maximGroupBox4.Controls.Add(this.btnSaveToFile);
+            this.maximGroupBox4.Location = new System.Drawing.Point(483, 5);
+            this.maximGroupBox4.Name = "maximGroupBox4";
+            this.maximGroupBox4.Size = new System.Drawing.Size(220, 168);
+            this.maximGroupBox4.TabIndex = 87;
+            this.maximGroupBox4.TabStop = false;
+            this.maximGroupBox4.Text = "Log Export";
+            // 
+            // label22
+            // 
+            this.label22.Location = new System.Drawing.Point(6, 26);
+            this.label22.Name = "label22";
+            this.label22.Size = new System.Drawing.Size(208, 35);
+            this.label22.TabIndex = 87;
+            this.label22.Text = "Download data from flash memory.";
+            // 
+            // DataLoggingView
+            // 
+            this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
+            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+            this.BackColor = System.Drawing.Color.White;
+            this.Controls.Add(this.maximGroupBox4);
+            this.Controls.Add(this.btnAdvanced);
+            this.Controls.Add(this.grpParameters);
+            this.Controls.Add(this.maximGroupBox3);
+            this.Controls.Add(this.maximGroupBox2);
+            this.Controls.Add(this.maximGroupBox1);
+            this.Controls.Add(this.grpPrePostCommands);
+            this.Controls.Add(this.btnLogSectorsErase);
+            this.Controls.Add(this.btnBulkErase);
+            this.Controls.Add(this.btnTestReadLogMemory);
+            this.Controls.Add(this.btnTestWriteLogMemory);
+            this.Controls.Add(this.btnTestMission);
+            this.Controls.Add(this.groupBox4);
+            this.Controls.Add(this.btnWrite);
+            this.Controls.Add(this.btnErase);
+            this.Controls.Add(this.btnRead);
+            this.Name = "DataLoggingView";
+            this.Size = new System.Drawing.Size(714, 558);
+            this.Load += new System.EventHandler(this.LoggingView_Load);
+            this.groupBox4.ResumeLayout(false);
+            this.groupBox4.PerformLayout();
+            this.grpPrePostCommands.ResumeLayout(false);
+            this.grpPrePostCommands.PerformLayout();
+            this.maximGroupBox1.ResumeLayout(false);
+            this.maximGroupBox1.PerformLayout();
+            this.maximGroupBox2.ResumeLayout(false);
+            this.maximGroupBox2.PerformLayout();
+            this.maximGroupBox3.ResumeLayout(false);
+            this.maximGroupBox3.PerformLayout();
+            this.grpParameters.ResumeLayout(false);
+            this.grpParameters.PerformLayout();
+            this.maximGroupBox4.ResumeLayout(false);
+            this.ResumeLayout(false);
+
+        }
+
+        #endregion
+
+        private MaximStyle.MaximButton btnRead;
+        private MaximStyle.MaximButton btnErase;
+        private MaximStyle.MaximButton btnWrite;
+        private MaximStyle.MaximCheckBox ckbxRtoR;
+        private MaximStyle.MaximCheckBox ckbxBioz;
+        private MaximStyle.MaximCheckBox ckbxPace;
+        private MaximStyle.MaximCheckBox ckbxEcg;
+        private MaximStyle.MaximCheckBox ckbxTemp1;
+        private MaximStyle.MaximCheckBox ckbxTemp2;
+        private System.Windows.Forms.GroupBox groupBox4;
+        private System.Windows.Forms.CheckBox ckbxOpticalSensor;
+        private System.Windows.Forms.TextBox txtTemp1SampleTime;
+        private System.Windows.Forms.TextBox txtTemp2SampleTime;
+        private System.Windows.Forms.TextBox txtPressureSampleTime;
+        private System.Windows.Forms.Button btnTestMission;
+        private System.Windows.Forms.Button btnTestWriteLogMemory;
+        private System.Windows.Forms.Button btnTestReadLogMemory;
+        private System.Windows.Forms.Button btnBulkErase;
+        private System.Windows.Forms.Button btnLogSectorsErase;
+        private System.Windows.Forms.RadioButton rbMulti;
+        private System.Windows.Forms.RadioButton rbHR;
+        private System.Windows.Forms.RadioButton rbSPO2;
+        private System.Windows.Forms.TextBox tbRtoRParameters;
+        private System.Windows.Forms.TextBox tbBiozParameters;
+        private System.Windows.Forms.TextBox tbPaceParameters;
+        private System.Windows.Forms.TextBox tbEcgParameters;
+        private System.Windows.Forms.Label label6;
+        private System.Windows.Forms.TextBox tbMultiParameters;
+        private System.Windows.Forms.TextBox tbHRParameters;
+        private System.Windows.Forms.TextBox tbSpO2Parameters;
+        private System.Windows.Forms.TextBox tbPostCmd;
+        private System.Windows.Forms.TextBox tbPreCmd;
+        private System.Windows.Forms.Label label8;
+        private System.Windows.Forms.Label label7;
+        private MaximStyle.MaximGroupBox maximGroupBox1;
+        private MaximStyle.MaximCheckBox ckbxAccel;
+        private MaximStyle.MaximCheckBox ckbxPressure;
+        private MaximStyle.MaximGroupBox maximGroupBox2;
+        private System.Windows.Forms.Label label14;
+        private System.Windows.Forms.Label label13;
+        private System.Windows.Forms.Label label12;
+        private System.Windows.Forms.Label label11;
+        private System.Windows.Forms.Label label10;
+        private System.Windows.Forms.Label label9;
+        private MaximStyle.MaximGroupBox maximGroupBox3;
+        private MaximStyle.MaximComboBox cboOpticalMode;
+        private System.Windows.Forms.Label label15;
+        private MaximStyle.MaximGroupBox grpParameters;
+        private System.Windows.Forms.Label label21;
+        private System.Windows.Forms.Label label20;
+        private System.Windows.Forms.Label label1;
+        private System.Windows.Forms.Label lblRToR;
+        private System.Windows.Forms.Label lblBioZ;
+        private System.Windows.Forms.Label lblPace;
+        private System.Windows.Forms.Label label16;
+        private MaximStyle.MaximGroupBox grpPrePostCommands;
+        private MaximStyle.MaximButton btnAdvanced;
+        private MaximStyle.MaximComboBox cboAccelSampleRate;
+        private MaximStyle.MaximButton btnSaveToFile;
+        private MaximStyle.MaximGroupBox maximGroupBox4;
+        private System.Windows.Forms.Label label22;
+        private System.Windows.Forms.TextBox tbFMSTRParameters;
+        private System.Windows.Forms.Label label23;
+        private System.Windows.Forms.ToolTip toolTip1;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HspGuiSourceV301/HSPGui/CustomControls/LoggingView.cs	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,933 @@
+/*******************************************************************************
+* Copyright (C) 2016 Maxim Integrated Products, Inc., All rights Reserved.
+* 
+* This software is protected by copyright laws of the United States and
+* of foreign countries. This material may also be protected by patent laws
+* and technology transfer regulations of the United States and of foreign
+* countries. This software is furnished under a license agreement and/or a
+* nondisclosure agreement and may only be used or reproduced in accordance
+* with the terms of those agreements. Dissemination of this information to
+* any party or parties not specified in the license agreement and/or
+* nondisclosure agreement is expressly prohibited.
+*
+* The above copyright notice and this permission notice shall be included
+* in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+* OTHER DEALINGS IN THE SOFTWARE.
+*
+* Except as contained in this notice, the name of Maxim Integrated
+* Products, Inc. shall not be used except as stated in the Maxim Integrated
+* Products, Inc. Branding Policy.
+*
+* The mere transfer of this software does not imply any licenses
+* of trade secrets, proprietary technology, copyrights, patents,
+* trademarks, maskwork rights, or any other form of intellectual
+* property whatsoever. Maxim Integrated Products, Inc. retains all
+* ownership rights.
+*******************************************************************************
+*/
+
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Drawing;
+using System.Data;
+using System.Linq;
+using System.Text;
+using System.Windows.Forms;
+using System.Globalization;
+
+using HealthSensorPlatform.Model;
+
+namespace HealthSensorPlatform.CustomControls
+{
+    public partial class DataLoggingView : UserControl, IDeviceView, IDataLoggingView
+    {
+        /* Fields */
+        public GetEcgInitArgs GetEcgInitArgsPointer;
+        public GetRToRInitArgs GetRToRInitArgsPointer;
+        public GetBioZInitArgs GetBioZInitArgsPointer;
+        public GetPaceInitArgs GetPaceInitArgsPointer;
+        public GetFMSTRInitArgs GetFMSTRInitArgsPointer;
+        public GetHRModeInitArgs GetHRModeInitArgsPointer;
+        public GetSpO2HRModeInitArgs GetSpO2HRModeInitArgsPointer;
+        public GetMultiModeInitArgs GetMultiModeInitArgsPointer;
+
+        private RPCSupport.RPCClient rpcClient;
+
+        private InitArgs.EcgInitStart ecgArgs;
+        private InitArgs.BIOZInitStart bioZArgs;
+        private InitArgs.RToRInitStart rToRArgs;
+        private InitArgs.PACEInitStart paceArgs;
+        private InitArgs.FMSTRInitStart fmstrArgs;
+        private InitArgs.HRModeInitStart hrModeArgs;
+        private InitArgs.SpO2HRModeInitStart spO2HRModeArgs;
+        private InitArgs.MultiModeInitStart multiModeArgs;
+
+        private Model.DataLogModel dataLogModel;
+        bool internalUpdate = false;
+
+        /* Constructor */
+        public DataLoggingView()
+        {
+            InitializeComponent();
+
+            dataLogModel = new Model.DataLogModel(rpcClient);
+            dataLogModel.LogStreamDone += new EventHandler<EventArgs>(OnLogStreamDone);
+        }
+
+        /* Events */
+        public event EventHandler<EventArgs> LogDownloadStart;
+        public event EventHandler<EventArgs> MissionWrite;
+        public event EventHandler<EventArgs> MissionRead;
+        public event EventHandler<EventArgs> MissionErase;
+
+        /* Properties */
+        public RPCSupport.RPCClient RPCClient
+        {
+            set
+            {
+                rpcClient = value;
+            }
+        }
+
+        public bool Connected { get; set; }
+
+        public InitArgs.EcgInitStart EcgArgs
+        {
+            get
+            {
+                return ecgArgs;
+            }
+            set
+            {
+                ecgArgs = value;
+                if (ecgArgs != null)
+                    tbEcgParameters.Text = ecgArgs.ToCommandString();
+                else
+                    tbEcgParameters.Text = "";
+            }
+        }
+        public InitArgs.BIOZInitStart BioZArgs
+        {
+            get
+            {
+                return bioZArgs;
+            }
+            set
+            {
+                bioZArgs = value;
+                if (bioZArgs != null)
+                    tbBiozParameters.Text = bioZArgs.ToCommandString();
+                else
+                    tbBiozParameters.Text = "";
+            }
+        }
+        public InitArgs.RToRInitStart RToRArgs
+        {
+            get
+            {
+                return rToRArgs;
+            }
+            set
+            {
+                rToRArgs = value;
+                if (rToRArgs != null)
+                    tbRtoRParameters.Text = rToRArgs.ToCommandString();
+                else
+                    tbRtoRParameters.Text = "";
+            }
+        }
+        public InitArgs.PACEInitStart PaceArgs
+        {
+            get
+            {
+                return paceArgs;
+            }
+            set
+            {
+                paceArgs = value;
+                if (paceArgs != null)
+                    tbPaceParameters.Text = paceArgs.ToCommandString();
+                else
+                    tbPaceParameters.Text = "";
+            }
+        }
+        public InitArgs.FMSTRInitStart FMSTRArgs
+        {
+            get
+            {
+                return fmstrArgs;
+            }
+            set
+            {
+                fmstrArgs = value;
+                if (fmstrArgs != null && (ecgArgs != null || bioZArgs != null || rToRArgs != null || paceArgs != null))
+                    tbFMSTRParameters.Text = fmstrArgs.ToCommandString();
+                else
+                    tbFMSTRParameters.Text = "";
+            }
+        }
+        public InitArgs.SpO2HRModeInitStart SpO2HRModeArgs
+        {
+            get
+            {
+                return spO2HRModeArgs;
+            }
+            set
+            {
+                spO2HRModeArgs = value;
+                if (spO2HRModeArgs == null)
+                    tbSpO2Parameters.Text = "";
+                else 
+                    tbSpO2Parameters.Text = spO2HRModeArgs.ToCommandString();
+            }
+        }
+        public InitArgs.HRModeInitStart HRModeArgs
+        {
+            get
+            {
+                return hrModeArgs;
+            }
+            set
+            {
+                hrModeArgs = value;
+                if (hrModeArgs == null)
+                    tbHRParameters.Text = "";
+                else
+                    tbHRParameters.Text = hrModeArgs.ToCommandString();
+            }
+        }
+        public InitArgs.MultiModeInitStart MultiModeArgs
+        {
+            get
+            {
+                return multiModeArgs;
+            }
+            set
+            {
+                multiModeArgs = value;
+                if (multiModeArgs != null)
+                    tbMultiParameters.Text = multiModeArgs.ToCommandString();
+                else
+                    tbMultiParameters.Text = "";
+            }
+        }
+
+        /* Setters and Getters attempting to disconnect the GUI controls from the internal code */
+        public bool EnableEcg 
+        { 
+            get 
+            { 
+                return ckbxEcg.Checked; 
+            } 
+            set
+            {
+                ckbxEcg.Checked = value;
+            }
+        }
+        public bool EnablePace 
+        { 
+            get 
+            { 
+                return ckbxPace.Checked; 
+            } 
+            set
+            {
+                ckbxPace.Checked = value;
+            }
+        }
+        public bool EnableBioz 
+        { 
+            get 
+            { 
+                return ckbxBioz.Checked; 
+            } 
+            set
+            {
+                ckbxBioz.Checked = value;
+            }
+        }
+        public bool EnableRToR 
+        { 
+            get 
+            { 
+                return ckbxRtoR.Checked; 
+            } 
+            set
+            {
+                ckbxRtoR.Checked = value;
+            }
+        }
+        public bool EnableFMSTR
+        {
+            get
+            {
+                return EnableEcg || EnableBioz || EnablePace || EnableRToR;
+            }
+        }
+        public bool EnableOpticalSpO2 
+        { 
+            get 
+            {
+                return (string)cboOpticalMode.SelectedItem == "SpO2";
+            } 
+            set
+            {
+                if (value)
+                    cboOpticalMode.SelectedItem = "SpO2";
+            }
+        }
+        public bool EnableOpticalHR 
+        { 
+            get 
+            {
+                return (string)cboOpticalMode.SelectedItem == "HR";
+            } 
+            set
+            {
+                if (value)
+                    cboOpticalMode.SelectedItem = "HR";
+            }
+        }
+        public bool EnableOpticalMulti 
+        { 
+            get 
+            {
+                return (string)cboOpticalMode.SelectedItem == "Multi";
+            }
+            set
+            {
+                if (value)
+                    cboOpticalMode.SelectedItem = "Multi";
+            }
+        }
+        public bool EnableTemperature1 
+        { 
+            get 
+            { 
+                return ckbxTemp1.Checked; 
+            } 
+            set
+            {
+                ckbxTemp1.Checked = value;
+            }
+        }
+        public bool EnableTemperature2 
+        { 
+            get 
+            { 
+                return ckbxTemp2.Checked; 
+            } 
+            set
+            {
+                ckbxTemp2.Checked = value;
+            }
+        }
+        public bool EnableAccelerometer 
+        { 
+            get 
+            { 
+                return ckbxAccel.Checked; 
+            } 
+            set
+            {
+                ckbxAccel.Checked = value;
+            }
+        }
+        public bool EnablePressure 
+        { 
+            get 
+            { 
+                return ckbxPressure.Checked; 
+            } 
+            set
+            {
+                ckbxPressure.Checked = value;
+            }
+        }
+
+        public int AccelSampleRate
+        {
+            get
+            {
+                return Int32.Parse((string)cboAccelSampleRate.SelectedItem);
+            }
+        }
+
+        /* Delegates */
+        public delegate InitArgs.EcgInitStart GetEcgInitArgs();
+        public delegate InitArgs.RToRInitStart GetRToRInitArgs();
+        public delegate InitArgs.BIOZInitStart GetBioZInitArgs();
+        public delegate InitArgs.PACEInitStart GetPaceInitArgs();
+        public delegate InitArgs.FMSTRInitStart GetFMSTRInitArgs();
+        public delegate InitArgs.HRModeInitStart GetHRModeInitArgs();
+        public delegate InitArgs.SpO2HRModeInitStart GetSpO2HRModeInitArgs();
+        public delegate InitArgs.MultiModeInitStart GetMultiModeInitArgs();
+
+        public delegate void LoggingParametersHandler(object sender, EventArgs e);
+
+        /* Events */
+        public event LoggingParametersHandler LoggingParametersChanged;
+
+        private void LoggingView_Load(object sender, EventArgs e)
+        {
+            cboOpticalMode.SelectedIndex = 0;
+            cboAccelSampleRate.SelectedIndex = 0;
+        }
+
+        private void btnRead_Click(object sender, EventArgs e)
+        {
+            if (MissionRead != null)
+                MissionRead(this, e);
+
+            if (Connected)
+            {
+                if (LoggingParametersChanged != null)
+                    LoggingParametersChanged(this, EventArgs.Empty);
+
+                //btnWrite.Enabled = false;
+            }
+        }
+
+        private void btnErase_Click(object sender, EventArgs e)
+        {
+            if (MissionErase != null)
+            {
+                MissionErase(this, e);
+            }
+        }
+
+        private void btnWrite_Click(object sender, EventArgs e)
+        {
+            if (MissionWrite != null)
+            {
+                MissionWrite(this, e);
+            }
+        }
+
+        private void btnTestMission_Click(object sender, EventArgs e)
+        {
+            rpcClient.DataLogging.TestMission();
+        }
+
+        private void btnTestWriteLogMemory_Click(object sender, EventArgs e)
+        {
+            //Process
+            //rpcClient.DataLogging.TestWriteLog();
+        }
+
+        private void btnTestReadLogMemory_Click(object sender, EventArgs e)
+        {
+            rpcClient.DataLogging.TestReadLog();
+        }
+
+        private void btnBulkErase_Click(object sender, EventArgs e)
+        {
+            rpcClient.DataLogging.TestBulkErase();
+        }
+
+        private void btnLogSectorsErase_Click(object sender, EventArgs e)
+        {
+            rpcClient.DataLogging.TestLogSectorsErase();
+        }
+
+        private int[] ParseHexString(String hexStr)
+        {
+            int val;
+            List<int> intList = new List<int>();
+            String[] strings = hexStr.Split(new char[] { ' ' });
+            foreach (String str in strings)
+            {
+                if (int.TryParse(str, NumberStyles.HexNumber, CultureInfo.CurrentCulture, out val))
+                {
+                    intList.Add(val);
+                }
+                else
+                {
+                    throw new Exception(String.Format("Error In hex string \"{0}\" in \"{1}\"", str, hexStr));
+                }
+            }
+            return intList.ToArray();
+        }
+
+        /// <summary>
+        /// Write GUI elements to flash
+        /// Call ValidateGuiElements() to verify user input acceptable before calling ProcessGuiElements()
+        /// </summary>
+        public bool ProcessGuiElements()
+        {
+            int[] temperature1 = new int[1] {10};
+            int[] temperature2 = new int[1] {10};
+            int[] barometer = new int[1];
+
+            if (EnableTemperature1)
+                temperature1[0] = Int32.Parse(txtTemp1SampleTime.Text.Trim());
+            if (EnableTemperature2)
+                temperature2[0] = Int32.Parse(txtTemp2SampleTime.Text.Trim());
+            if (EnablePressure)
+                barometer[0] = Int32.Parse(txtPressureSampleTime.Text.Trim());
+
+            // Pre Commands
+            rpcClient.DataLogging.PreCommand.Define(tbPreCmd.Text.Trim());
+            rpcClient.DataLogging.MissionAppend(rpcClient.DataLogging.PreCommand);
+            // ecg
+            if (EnableEcg)
+            {
+                InitArgs.EcgInitStart ecgArgs = GetEcgInitArgsPointer();
+                //rpcClient.DataLogging.MAX30001_Ecg.AssignByIntArray(ParseHexString(tbEcgParameters.Text));
+                rpcClient.DataLogging.MAX30001_Ecg.AssignByValue(
+                    1, //ecgArgs.En_ecg,
+                    ecgArgs.Openp,
+                    ecgArgs.Openn,
+                    ecgArgs.Pol,
+                    ecgArgs.Calp_sel,
+                    ecgArgs.Caln_sel,
+                    ecgArgs.E_fit,
+                    ecgArgs.Rate,
+                    ecgArgs.Gain,
+                    ecgArgs.Dhpf,
+                    ecgArgs.Dlpf
+                );
+                rpcClient.DataLogging.MissionAppend(rpcClient.DataLogging.MAX30001_Ecg);
+            }
+            // pace
+            if (EnablePace)
+            {
+                InitArgs.PACEInitStart paceArgs = GetPaceInitArgsPointer();
+                //rpcClient.DataLogging.MAX30001_Pace.AssignByIntArray(ParseHexString(tbPaceParameters.Text));
+                rpcClient.DataLogging.MAX30001_Pace.AssignByValue(
+                    1,//paceArgs.En_pace,
+                    paceArgs.Clr_pedge,
+                    paceArgs.Pol,
+                    paceArgs.Gn_diff_off,
+                    paceArgs.Gain,
+                    paceArgs.Aout_lbw,
+                    paceArgs.Aout,
+                    paceArgs.Dacp,
+                    paceArgs.Dacn
+                 );
+                rpcClient.DataLogging.MissionAppend(rpcClient.DataLogging.MAX30001_Pace);
+            }
+            // bioz
+            if (EnableBioz)
+            {
+                InitArgs.BIOZInitStart biozArgs = GetBioZInitArgsPointer();
+                //rpcClient.DataLogging.MAX30001_Bioz.AssignByIntArray(ParseHexString(tbBiozParameters.Text));
+                rpcClient.DataLogging.MAX30001_Bioz.AssignByValue(
+                    1, //biozArgs.En_bioz,
+                    biozArgs.Openp,
+                    biozArgs.Openn,
+                    biozArgs.Calp_sel,
+                    biozArgs.Caln_sel,
+                    biozArgs.CG_mode,
+                    biozArgs.B_fit,
+                    biozArgs.Rate,
+                    biozArgs.Ahpf,
+                    biozArgs.Ext_rbias,
+                    biozArgs.Gain,
+                    biozArgs.Dhpf,
+                    biozArgs.Dlpf,
+                    biozArgs.Fcgen,
+                    biozArgs.Cgmon,
+                    biozArgs.Cgmag,
+                    biozArgs.Phoff
+                );
+                rpcClient.DataLogging.MissionAppend(rpcClient.DataLogging.MAX30001_Bioz);
+            }
+            // RtoR
+            if (EnableRToR)
+            {
+                InitArgs.RToRInitStart rtorArgs = GetRToRInitArgsPointer();
+                //rpcClient.DataLogging.MAX30001_RtoR.AssignByIntArray(ParseHexString(tbRtoRParameters.Text));
+                rpcClient.DataLogging.MAX30001_RtoR.AssignByValue(
+                    1, //rtorArgs.En_rtor,
+                    rtorArgs.Wndw,
+                    rtorArgs.Gain,
+                    rtorArgs.Pavg,
+                    rtorArgs.Ptsf,
+                    rtorArgs.Hoff,
+                    rtorArgs.Ravg,
+                    rtorArgs.Rhsf,
+                    rtorArgs.Clr_rrint
+                );
+                rpcClient.DataLogging.MissionAppend(rpcClient.DataLogging.MAX30001_RtoR);
+            }
+            // SpO2
+            if (EnableOpticalSpO2)
+            {
+                rpcClient.DataLogging.MAX30101_SpO2.AssignByIntArray(ParseHexString(tbSpO2Parameters.Text));
+                rpcClient.DataLogging.MissionAppend(rpcClient.DataLogging.MAX30101_SpO2);
+            }
+            // HR
+            if (EnableOpticalHR)
+            {
+                rpcClient.DataLogging.MAX30101_HR.AssignByIntArray(ParseHexString(tbHRParameters.Text));
+                rpcClient.DataLogging.MissionAppend(rpcClient.DataLogging.MAX30101_HR);
+            }
+            // Multi
+            if (EnableOpticalMulti)
+            {
+                rpcClient.DataLogging.MAX30101_Multi.AssignByIntArray(ParseHexString(tbMultiParameters.Text));
+                rpcClient.DataLogging.MissionAppend(rpcClient.DataLogging.MAX30101_Multi);
+            }
+            // Temp1
+            if (EnableTemperature1)
+            {
+                rpcClient.DataLogging.MAX31725_1.AssignByIntArray(temperature1);
+                rpcClient.DataLogging.MissionAppend(rpcClient.DataLogging.MAX31725_1);
+            }
+            // Temp2
+            if (EnableTemperature2)
+            {
+                rpcClient.DataLogging.MAX31725_2.AssignByIntArray(temperature2);
+                rpcClient.DataLogging.MissionAppend(rpcClient.DataLogging.MAX31725_2);
+            }
+            // Accel
+            if (EnableAccelerometer)
+            {
+                rpcClient.DataLogging.LIS2DH.AssignByIntArray(new int[] {cboAccelSampleRate.SelectedIndex + 1, 15}); // FIFO depth is second parameter
+                rpcClient.DataLogging.MissionAppend(rpcClient.DataLogging.LIS2DH);
+            }
+            // Pressure
+            if (EnablePressure)
+            {
+                rpcClient.DataLogging.BMP280.AssignByIntArray(barometer);
+                rpcClient.DataLogging.MissionAppend(rpcClient.DataLogging.BMP280);
+            }
+
+            // add Rbias if we are using any of the MAX30001 commands
+            if (EnableEcg || EnableBioz || EnablePace || EnableRToR)
+            {
+                //rpcClient.DataLogging.MAX30001_Rbias.Define("/MAX30001/Rbias_FMSTR_Init 01 02 01 01 00");
+                rpcClient.DataLogging.MAX30001_Rbias_Fmstr.AssignByIntArray(ParseHexString(tbFMSTRParameters.Text));
+                //rpcClient.DataLogging.MAX30001_Rbias.Define("/MAX30001/Rbias_FMSTR_Init " + tbFMSTRParameters.Text);
+                rpcClient.DataLogging.MissionAppend(rpcClient.DataLogging.MAX30001_Rbias_Fmstr);
+            }
+            // Post Commands
+            rpcClient.DataLogging.PostCommand.Define(tbPostCmd.Text.Trim());
+            rpcClient.DataLogging.MissionAppend(rpcClient.DataLogging.PostCommand);
+
+            return true;
+        }
+
+        public bool ValidateGuiElements()
+        {
+            const int MaxTime = 1000; // TODO Ask Jerry to calculate the 16 bit timer limit
+            const int MinTime = 0;
+            const int MinRecommendedTempTime = 10;
+            int[] temperature1 = new int[1] { 10 };
+            int[] temperature2 = new int[1] { 10 };
+            int[] barometer = new int[1];
+
+            try
+            {
+                if (EnableTemperature1)
+                    temperature1[0] = Int32.Parse(txtTemp1SampleTime.Text.Trim());
+                if (EnableTemperature2)
+                    temperature2[0] = Int32.Parse(txtTemp2SampleTime.Text.Trim());
+                if (EnablePressure)
+                    barometer[0] = Int32.Parse(txtPressureSampleTime.Text.Trim());
+                // TODO Limit Max and Min Range
+                if (temperature1[0] > MaxTime || temperature2[0] > MaxTime || barometer[0] > MaxTime)
+                {
+                    MessageBox.Show("Time value cannot be larger than " + MaxTime);
+                }
+                else if (temperature1[0] < MinTime || temperature2[0] < MinTime || barometer[0] < MinTime)
+                {
+                    MessageBox.Show("Time value cannot be less than " + MinTime);
+                }
+                else if (temperature1[0] < MinRecommendedTempTime || temperature2[0] < MinRecommendedTempTime)
+                {
+                    MessageBox.Show("The recommended temperature sample period is >" + MinRecommendedTempTime + " seconds due to self heating effects.", "Warning");
+                }
+            }
+            catch (Exception)
+            {
+                if (EnableTemperature1 || EnableTemperature2 || EnablePressure)
+                {
+                    MessageBox.Show("Temperature 1 & 2 and Barometer must contain only digits", "Sample Rates");
+                    return false;
+                }
+            }
+
+            return true;
+        }
+
+
+        /// <summary>
+        /// Update GUI with data read from flash
+        /// </summary>
+        public void UpdateGuiElements(Mission missionSettings)
+        {
+            internalUpdate = true;
+
+            // Set optical state to none
+            cboOpticalMode.SelectedIndex = 0;
+
+            // pre cmd
+            tbPreCmd.Text = missionSettings.PreCommand;
+            // ecg
+            EnableEcg = missionSettings.EnableEcg;
+            if (EnableEcg)
+                EcgArgs = EcgArgs.FromIntArray(missionSettings.EcgArgs);
+            else
+                EcgArgs = null;
+            // pace
+            EnablePace = missionSettings.EnablePace;
+            if (EnablePace)
+                PaceArgs = PaceArgs.FromIntArray(missionSettings.PaceArgs);
+            else
+                PaceArgs = null;
+            // bioz
+            EnableBioz = missionSettings.EnableBioZ;
+            if (EnableBioz)
+                BioZArgs = BioZArgs.FromIntArray(missionSettings.BioZArgs);
+            else
+                BioZArgs = null;
+            // RtoR
+            EnableRToR = missionSettings.EnableRToR;
+            if (EnableRToR)
+                RToRArgs = RToRArgs.FromIntArray(missionSettings.RToRArgs);
+            else
+                RToRArgs = null;
+            // Rbias, FMSTR
+            if (EnableFMSTR && missionSettings.EnableRBias) // Only applies when OT90 is used
+                FMSTRArgs = FMSTRArgs.FromIntArray(missionSettings.RBiasArgs);
+            else
+                FMSTRArgs = null;
+            // SpO2, HR
+            EnableOpticalSpO2 = missionSettings.EnableOpticalSpO2;
+            if (EnableOpticalSpO2)
+                SpO2HRModeArgs = SpO2HRModeArgs.FromIntArray(missionSettings.SpO2HRModeArgs);
+            else
+                SpO2HRModeArgs = null;
+            EnableOpticalHR = missionSettings.EnableOpticalHR;
+            if (EnableOpticalHR)
+                HRModeArgs = HRModeArgs.FromIntArray(missionSettings.HRModeArgs);
+            else
+                HRModeArgs = null;
+            // Multi
+            EnableOpticalMulti = missionSettings.EnableOpticalMulti;
+            if (EnableOpticalMulti)
+                MultiModeArgs = MultiModeArgs.FromIntArray(missionSettings.MultiModeArgs);
+            else
+                MultiModeArgs = null;
+
+            if (EnableOpticalSpO2)
+            {
+                cboOpticalMode.SelectedItem = "SpO2";
+            }
+            else if (EnableOpticalHR)
+            {
+                cboOpticalMode.SelectedItem = "HR";
+            }
+            else if (EnableOpticalMulti)
+            {
+                cboOpticalMode.SelectedItem = "Multi";
+            }
+            else
+            {
+                cboOpticalMode.SelectedItem = "None";
+            }
+
+            /* These Parameters to not effect the other GUI tabs, thus are not accessible in a property field */
+            // Temp1
+            EnableTemperature1 = missionSettings.EnableTemperature1;
+            txtTemp1SampleTime.Text = EnableTemperature1 ? missionSettings.Temperature1Parameters[0].ToString() : "";
+            // Temp2
+            EnableTemperature2 = missionSettings.EnableTemperature2;
+            txtTemp2SampleTime.Text = EnableTemperature2 ? missionSettings.Temperature2Parameters[0].ToString() : "";
+            // Accel
+            EnableAccelerometer = missionSettings.EnableAccelerometer;
+            cboAccelSampleRate.SelectedIndex = EnableAccelerometer ? missionSettings.AccelerometerParameters[0] - 1 : 0;
+            // Pressure
+            EnablePressure = missionSettings.EnablePressure;
+            txtPressureSampleTime.Text = EnablePressure ? missionSettings.PressureParameters[0].ToString() : "";
+            // post cmd
+            tbPostCmd.Text = missionSettings.PostCommand;
+
+            internalUpdate = false;
+        }
+
+        /// <summary>
+        /// Update the logging parameters
+        /// </summary>
+        public void UpdateArgs()
+        {
+            updateArgsOT90();
+            updateArgsOS24();
+        }
+
+        private void updateArgsOT90()
+        {
+            InitArgs.EcgInitStart eargs;
+            InitArgs.BIOZInitStart bargs;
+            InitArgs.RToRInitStart rargs;
+            InitArgs.PACEInitStart pargs;
+            InitArgs.FMSTRInitStart fargs;
+
+            //btnWrite.Enabled = true;
+
+            // Override enable bit since if command is being sent, this should be set to 1
+            // based the data logging enable bit and not the GUI tab enable controls
+            if (GetEcgInitArgsPointer != null)
+            {
+                eargs = GetEcgInitArgsPointer();
+                eargs.En_ecg = 1;  
+
+                EcgArgs = eargs;
+            }
+
+            if (GetBioZInitArgsPointer != null)
+            {
+                bargs = GetBioZInitArgsPointer();
+                bargs.En_bioz = 1;  
+
+                BioZArgs = bargs;
+            }
+
+            if (GetRToRInitArgsPointer != null)
+            {
+                rargs = GetRToRInitArgsPointer();
+                rargs.En_rtor = 1;
+
+                RToRArgs = rargs;
+            }
+
+            if (GetPaceInitArgsPointer != null)
+            {
+                pargs = GetPaceInitArgsPointer();
+                pargs.En_pace = 1;
+
+                PaceArgs = pargs;
+            }
+
+            if (GetFMSTRInitArgsPointer != null)
+            {
+                fargs = GetFMSTRInitArgsPointer();
+
+                FMSTRArgs = fargs;
+            }
+
+        }
+
+        private void updateArgsOS24()
+        {
+            if (GetSpO2HRModeInitArgsPointer != null)
+            {
+                SpO2HRModeArgs = GetSpO2HRModeInitArgsPointer();
+            }
+
+            if (GetHRModeInitArgsPointer != null)
+            {
+                HRModeArgs = GetHRModeInitArgsPointer();
+            }
+
+            if (GetMultiModeInitArgsPointer != null)
+            {
+                MultiModeArgs = GetMultiModeInitArgsPointer();
+            }
+
+        }
+
+        public void PaceFunction(bool enable)
+        {
+            ckbxPace.Enabled = enable;
+            lblPace.Enabled = enable;
+            tbPaceParameters.Enabled = enable;
+        }
+
+        public void BioZFunction(bool enable)
+        {
+            ckbxBioz.Enabled = enable;
+            lblBioZ.Enabled = enable;
+            tbBiozParameters.Enabled = enable;
+        }
+
+        private void btnAdvanced_Click(object sender, EventArgs e)
+        {
+            grpParameters.Visible = !grpParameters.Visible;
+            grpPrePostCommands.Visible = !grpPrePostCommands.Visible;
+        }
+
+        private void cboOpticalMode_SelectedIndexChanged(object sender, EventArgs e)
+        {
+            MaximStyle.MaximComboBox cbo = (MaximStyle.MaximComboBox)sender;
+
+            if (internalUpdate == true)
+                return;
+
+            internalUpdate = true;
+
+            if ((string)cbo.SelectedItem == "SpO2")
+            {
+                EnableOpticalSpO2 = true;
+                EnableOpticalHR = false;
+                EnableOpticalMulti = false;
+            }
+            else if ((string)cbo.SelectedItem == "HR")
+            {
+                EnableOpticalSpO2 = false;
+                EnableOpticalHR = true;
+                EnableOpticalMulti = false;
+            }
+            else if ((string)cbo.SelectedItem == "Multi")
+            {
+                EnableOpticalSpO2 = false;
+                EnableOpticalHR = false;
+                EnableOpticalMulti = true;
+            }
+            else
+            {
+                EnableOpticalSpO2 = false;
+                EnableOpticalHR = false;
+                EnableOpticalMulti = false;
+            }
+
+            updateArgsOS24();
+
+            internalUpdate = false;
+        }
+
+        private void btnSaveToFile_Click(object sender, EventArgs e)
+        {
+            if (LogDownloadStart != null)
+                LogDownloadStart(this, e);
+
+            //btnWrite.Enabled = false;
+
+        }
+
+        private void OnLogStreamDone(object sender, EventArgs e)
+        {
+            if (LogDownloadStart != null)
+                LogDownloadStart(this, e);
+        }
+
+        private void ckbxBioz_CheckedChanged(object sender, EventArgs e)
+        {
+            if (ckbxEcg.Checked)
+                ckbxRtoR.Enabled = true;
+
+            if (ckbxEcg.Checked == false) 
+            {
+                if (ckbxRtoR.Checked == true)
+                    ckbxRtoR.Checked = false;
+
+                ckbxRtoR.Enabled = false;
+            }
+
+            MaximStyle.MaximCheckBox cbo = (MaximStyle.MaximCheckBox)sender;
+            if (cbo.Checked)
+                updateArgsOT90();
+        }
+
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HspGuiSourceV301/HSPGui/CustomControls/LoggingView.resx	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,123 @@
+<?xml version="1.0" encoding="utf-8"?>
+<root>
+  <!-- 
+    Microsoft ResX Schema 
+    
+    Version 2.0
+    
+    The primary goals of this format is to allow a simple XML format 
+    that is mostly human readable. The generation and parsing of the 
+    various data types are done through the TypeConverter classes 
+    associated with the data types.
+    
+    Example:
+    
+    ... ado.net/XML headers & schema ...
+    <resheader name="resmimetype">text/microsoft-resx</resheader>
+    <resheader name="version">2.0</resheader>
+    <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+    <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+    <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
+    <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+    <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+        <value>[base64 mime encoded serialized .NET Framework object]</value>
+    </data>
+    <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+        <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
+        <comment>This is a comment</comment>
+    </data>
+                
+    There are any number of "resheader" rows that contain simple 
+    name/value pairs.
+    
+    Each data row contains a name, and value. The row also contains a 
+    type or mimetype. Type corresponds to a .NET class that support 
+    text/value conversion through the TypeConverter architecture. 
+    Classes that don't support this are serialized and stored with the 
+    mimetype set.
+    
+    The mimetype is used for serialized objects, and tells the 
+    ResXResourceReader how to depersist the object. This is currently not 
+    extensible. For a given mimetype the value must be set accordingly:
+    
+    Note - application/x-microsoft.net.object.binary.base64 is the format 
+    that the ResXResourceWriter will generate, however the reader can 
+    read any of the formats listed below.
+    
+    mimetype: application/x-microsoft.net.object.binary.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
+            : and then encoded with base64 encoding.
+    
+    mimetype: application/x-microsoft.net.object.soap.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+            : and then encoded with base64 encoding.
+
+    mimetype: application/x-microsoft.net.object.bytearray.base64
+    value   : The object must be serialized into a byte array 
+            : using a System.ComponentModel.TypeConverter
+            : and then encoded with base64 encoding.
+    -->
+  <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+    <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
+    <xsd:element name="root" msdata:IsDataSet="true">
+      <xsd:complexType>
+        <xsd:choice maxOccurs="unbounded">
+          <xsd:element name="metadata">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" />
+              </xsd:sequence>
+              <xsd:attribute name="name" use="required" type="xsd:string" />
+              <xsd:attribute name="type" type="xsd:string" />
+              <xsd:attribute name="mimetype" type="xsd:string" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="assembly">
+            <xsd:complexType>
+              <xsd:attribute name="alias" type="xsd:string" />
+              <xsd:attribute name="name" type="xsd:string" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="data">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+                <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
+              <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+              <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="resheader">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" />
+            </xsd:complexType>
+          </xsd:element>
+        </xsd:choice>
+      </xsd:complexType>
+    </xsd:element>
+  </xsd:schema>
+  <resheader name="resmimetype">
+    <value>text/microsoft-resx</value>
+  </resheader>
+  <resheader name="version">
+    <value>2.0</value>
+  </resheader>
+  <resheader name="reader">
+    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <resheader name="writer">
+    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <metadata name="toolTip1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
+    <value>17, 17</value>
+  </metadata>
+</root>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HspGuiSourceV301/HSPGui/CustomControls/OpticalView.Designer.cs	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,1238 @@
+namespace HealthSensorPlatform.CustomControls
+{
+    partial class OpticalView
+    {
+        /// <summary> 
+        /// Required designer variable.
+        /// </summary>
+        private System.ComponentModel.IContainer components = null;
+
+        /// <summary> 
+        /// Clean up any resources being used.
+        /// </summary>
+        /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
+        protected override void Dispose(bool disposing)
+        {
+            if (disposing && (components != null))
+            {
+                components.Dispose();
+            }
+            base.Dispose(disposing);
+        }
+
+        #region Component Designer generated code
+
+        /// <summary> 
+        /// Required method for Designer support - do not modify 
+        /// the contents of this method with the code editor.
+        /// </summary>
+        private void InitializeComponent()
+        {
+            System.Windows.Forms.DataVisualization.Charting.ChartArea chartArea1 = new System.Windows.Forms.DataVisualization.Charting.ChartArea();
+            System.Windows.Forms.DataVisualization.Charting.ChartArea chartArea2 = new System.Windows.Forms.DataVisualization.Charting.ChartArea();
+            System.Windows.Forms.DataVisualization.Charting.ChartArea chartArea3 = new System.Windows.Forms.DataVisualization.Charting.ChartArea();
+            System.Windows.Forms.DataVisualization.Charting.Series series1 = new System.Windows.Forms.DataVisualization.Charting.Series();
+            System.Windows.Forms.DataVisualization.Charting.Series series2 = new System.Windows.Forms.DataVisualization.Charting.Series();
+            System.Windows.Forms.DataVisualization.Charting.Series series3 = new System.Windows.Forms.DataVisualization.Charting.Series();
+            System.Windows.Forms.DataVisualization.Charting.Title title1 = new System.Windows.Forms.DataVisualization.Charting.Title();
+            System.Windows.Forms.DataVisualization.Charting.ChartArea chartArea4 = new System.Windows.Forms.DataVisualization.Charting.ChartArea();
+            System.Windows.Forms.DataVisualization.Charting.ChartArea chartArea5 = new System.Windows.Forms.DataVisualization.Charting.ChartArea();
+            System.Windows.Forms.DataVisualization.Charting.ChartArea chartArea6 = new System.Windows.Forms.DataVisualization.Charting.ChartArea();
+            System.Windows.Forms.DataVisualization.Charting.Series series4 = new System.Windows.Forms.DataVisualization.Charting.Series();
+            System.Windows.Forms.DataVisualization.Charting.Series series5 = new System.Windows.Forms.DataVisualization.Charting.Series();
+            System.Windows.Forms.DataVisualization.Charting.Series series6 = new System.Windows.Forms.DataVisualization.Charting.Series();
+            System.Windows.Forms.DataVisualization.Charting.Title title2 = new System.Windows.Forms.DataVisualization.Charting.Title();
+            this.groupBoxAccelMeasurements = new MaximStyle.MaximGroupBox();
+            this.label7 = new System.Windows.Forms.Label();
+            this.chartAccel = new System.Windows.Forms.DataVisualization.Charting.Chart();
+            this.maximGroupBoxProximity = new MaximStyle.MaximGroupBox();
+            this.labelnumProxThreshold = new System.Windows.Forms.Label();
+            this.numProxThreshold = new System.Windows.Forms.NumericUpDown();
+            this.labelcboPilotPA = new System.Windows.Forms.Label();
+            this.label21 = new System.Windows.Forms.Label();
+            this.lblAvgPilotPALEDcurrent = new System.Windows.Forms.Label();
+            this.cboPilotPA = new MaximStyle.MaximComboBox();
+            this.groupBoxOpticalMeasurements = new MaximStyle.MaximGroupBox();
+            this.label45 = new System.Windows.Forms.Label();
+            this.chartLED = new System.Windows.Forms.DataVisualization.Charting.Chart();
+            this.maximGroupBoxLEDTimingSlots = new MaximStyle.MaximGroupBox();
+            this.cboLEDslot1 = new MaximStyle.MaximComboBox();
+            this.cboLEDslot2 = new MaximStyle.MaximComboBox();
+            this.labelcboLEDslot4 = new System.Windows.Forms.Label();
+            this.cboLEDslot3 = new MaximStyle.MaximComboBox();
+            this.labelcboLEDslot3 = new System.Windows.Forms.Label();
+            this.cboLEDslot4 = new MaximStyle.MaximComboBox();
+            this.labelcboLEDslot2 = new System.Windows.Forms.Label();
+            this.labelcboLEDslot1 = new System.Windows.Forms.Label();
+            this.maximGroupBoxSettings = new MaximStyle.MaximGroupBox();
+            this.label28 = new System.Windows.Forms.Label();
+            this.label25 = new System.Windows.Forms.Label();
+            this.label26 = new System.Windows.Forms.Label();
+            this.label27 = new System.Windows.Forms.Label();
+            this.cboADCFSrangenA = new MaximStyle.MaximComboBox();
+            this.label29 = new System.Windows.Forms.Label();
+            this.cboSampleAvg = new MaximStyle.MaximComboBox();
+            this.label30 = new System.Windows.Forms.Label();
+            this.cboSampleRate = new MaximStyle.MaximComboBox();
+            this.label31 = new System.Windows.Forms.Label();
+            this.cboPulseWidth = new MaximStyle.MaximComboBox();
+            this.maximGroupBoxLEDcurrents = new MaximStyle.MaximGroupBox();
+            this.cboIRLED = new MaximStyle.MaximComboBox();
+            this.labelcboRedLED = new System.Windows.Forms.Label();
+            this.labelcboGreenLED = new System.Windows.Forms.Label();
+            this.label32 = new System.Windows.Forms.Label();
+            this.label33 = new System.Windows.Forms.Label();
+            this.label35 = new System.Windows.Forms.Label();
+            this.label34 = new System.Windows.Forms.Label();
+            this.labelcboIRLED = new System.Windows.Forms.Label();
+            this.cboRedLED = new MaximStyle.MaximComboBox();
+            this.cboGreenLED = new MaximStyle.MaximComboBox();
+            this.lblAvgIRLEDcurrent = new System.Windows.Forms.Label();
+            this.lblAvgGreenLEDcurrent = new System.Windows.Forms.Label();
+            this.lblAvgRedLEDcurrent = new System.Windows.Forms.Label();
+            this.label36 = new System.Windows.Forms.Label();
+            this.label37 = new System.Windows.Forms.Label();
+            this.maximGroupBoxRegs = new MaximStyle.MaximGroupBox();
+            this.textBoxRegValue = new System.Windows.Forms.TextBox();
+            this.btnRegWrite = new MaximStyle.MaximButton();
+            this.btnRegRead = new MaximStyle.MaximButton();
+            this.comboBoxRegAddr = new MaximStyle.MaximComboBox();
+            this.btnDefaults = new MaximStyle.MaximButton();
+            this.btnMonitoring = new MaximStyle.MaximButton();
+            this.label38 = new System.Windows.Forms.Label();
+            this.cboMode = new MaximStyle.MaximComboBox();
+            this.button1 = new System.Windows.Forms.Button();
+            this.lblPulseInterval = new System.Windows.Forms.Label();
+            this.tableLayoutPanel1 = new System.Windows.Forms.TableLayoutPanel();
+            this.panel1 = new System.Windows.Forms.Panel();
+            this.grpAlgorithm = new MaximStyle.MaximGroupBox();
+            this.lblSpO2 = new System.Windows.Forms.Label();
+            this.lblHeartRate = new System.Windows.Forms.Label();
+            this.label8 = new System.Windows.Forms.Label();
+            this.label6 = new System.Windows.Forms.Label();
+            this.label2 = new System.Windows.Forms.Label();
+            this.label1 = new System.Windows.Forms.Label();
+            this.groupBoxAccelMeasurements.SuspendLayout();
+            ((System.ComponentModel.ISupportInitialize)(this.chartAccel)).BeginInit();
+            this.maximGroupBoxProximity.SuspendLayout();
+            ((System.ComponentModel.ISupportInitialize)(this.numProxThreshold)).BeginInit();
+            this.groupBoxOpticalMeasurements.SuspendLayout();
+            ((System.ComponentModel.ISupportInitialize)(this.chartLED)).BeginInit();
+            this.maximGroupBoxLEDTimingSlots.SuspendLayout();
+            this.maximGroupBoxSettings.SuspendLayout();
+            this.maximGroupBoxLEDcurrents.SuspendLayout();
+            this.maximGroupBoxRegs.SuspendLayout();
+            this.tableLayoutPanel1.SuspendLayout();
+            this.panel1.SuspendLayout();
+            this.grpAlgorithm.SuspendLayout();
+            this.SuspendLayout();
+            // 
+            // groupBoxAccelMeasurements
+            // 
+            this.groupBoxAccelMeasurements.BackgroundColor = System.Drawing.Color.White;
+            this.groupBoxAccelMeasurements.Controls.Add(this.label7);
+            this.groupBoxAccelMeasurements.Controls.Add(this.chartAccel);
+            this.groupBoxAccelMeasurements.Dock = System.Windows.Forms.DockStyle.Fill;
+            this.groupBoxAccelMeasurements.Location = new System.Drawing.Point(508, 3);
+            this.groupBoxAccelMeasurements.Name = "groupBoxAccelMeasurements";
+            this.groupBoxAccelMeasurements.Size = new System.Drawing.Size(247, 528);
+            this.groupBoxAccelMeasurements.TabIndex = 38;
+            this.groupBoxAccelMeasurements.TabStop = false;
+            this.groupBoxAccelMeasurements.Text = "Accelerometer Measurements";
+            // 
+            // label7
+            // 
+            this.label7.Anchor = System.Windows.Forms.AnchorStyles.Bottom;
+            this.label7.AutoSize = true;
+            this.label7.Location = new System.Drawing.Point(105, 511);
+            this.label7.Name = "label7";
+            this.label7.Size = new System.Drawing.Size(79, 13);
+            this.label7.TabIndex = 34;
+            this.label7.Text = "Time (seconds)";
+            // 
+            // chartAccel
+            // 
+            this.chartAccel.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) 
+            | System.Windows.Forms.AnchorStyles.Left) 
+            | System.Windows.Forms.AnchorStyles.Right)));
+            chartArea1.AxisY.Title = "Accelerometer X";
+            chartArea1.Name = "ChartArea4AccelX";
+            chartArea2.AlignWithChartArea = "ChartArea4AccelX";
+            chartArea2.AxisY.Title = "Accelerometer Y";
+            chartArea2.Name = "ChartArea5AccelY";
+            chartArea3.AlignWithChartArea = "ChartArea4AccelX";
+            chartArea3.AxisY.Title = "Accelerometer Z";
+            chartArea3.Name = "ChartArea6AccelZ";
+            this.chartAccel.ChartAreas.Add(chartArea1);
+            this.chartAccel.ChartAreas.Add(chartArea2);
+            this.chartAccel.ChartAreas.Add(chartArea3);
+            this.chartAccel.Location = new System.Drawing.Point(6, 19);
+            this.chartAccel.Name = "chartAccel";
+            series1.ChartArea = "ChartArea4AccelX";
+            series1.ChartType = System.Windows.Forms.DataVisualization.Charting.SeriesChartType.Line;
+            series1.Color = System.Drawing.Color.FromArgb(((int)(((byte)(0)))), ((int)(((byte)(51)))), ((int)(((byte)(89)))));
+            series1.MarkerSize = 1;
+            series1.Name = "SeriesAccelX";
+            series1.XValueType = System.Windows.Forms.DataVisualization.Charting.ChartValueType.UInt32;
+            series1.YValueType = System.Windows.Forms.DataVisualization.Charting.ChartValueType.Int32;
+            series2.ChartArea = "ChartArea5AccelY";
+            series2.ChartType = System.Windows.Forms.DataVisualization.Charting.SeriesChartType.Line;
+            series2.Color = System.Drawing.Color.FromArgb(((int)(((byte)(0)))), ((int)(((byte)(176)))), ((int)(((byte)(169)))));
+            series2.Name = "SeriesAccelY";
+            series2.XValueType = System.Windows.Forms.DataVisualization.Charting.ChartValueType.UInt32;
+            series2.YValueType = System.Windows.Forms.DataVisualization.Charting.ChartValueType.Int32;
+            series3.ChartArea = "ChartArea6AccelZ";
+            series3.ChartType = System.Windows.Forms.DataVisualization.Charting.SeriesChartType.Line;
+            series3.Color = System.Drawing.Color.FromArgb(((int)(((byte)(242)))), ((int)(((byte)(175)))), ((int)(((byte)(0)))));
+            series3.Name = "SeriesAccelZ";
+            series3.XValueType = System.Windows.Forms.DataVisualization.Charting.ChartValueType.UInt32;
+            series3.YValueType = System.Windows.Forms.DataVisualization.Charting.ChartValueType.Int32;
+            this.chartAccel.Series.Add(series1);
+            this.chartAccel.Series.Add(series2);
+            this.chartAccel.Series.Add(series3);
+            this.chartAccel.Size = new System.Drawing.Size(235, 503);
+            this.chartAccel.TabIndex = 32;
+            this.chartAccel.Text = "chart1";
+            title1.Name = "Title1";
+            title1.Text = "Red";
+            title1.Visible = false;
+            this.chartAccel.Titles.Add(title1);
+            // 
+            // maximGroupBoxProximity
+            // 
+            this.maximGroupBoxProximity.BackgroundColor = System.Drawing.Color.White;
+            this.maximGroupBoxProximity.Controls.Add(this.labelnumProxThreshold);
+            this.maximGroupBoxProximity.Controls.Add(this.numProxThreshold);
+            this.maximGroupBoxProximity.Controls.Add(this.labelcboPilotPA);
+            this.maximGroupBoxProximity.Controls.Add(this.label21);
+            this.maximGroupBoxProximity.Controls.Add(this.lblAvgPilotPALEDcurrent);
+            this.maximGroupBoxProximity.Controls.Add(this.cboPilotPA);
+            this.maximGroupBoxProximity.Enabled = false;
+            this.maximGroupBoxProximity.Location = new System.Drawing.Point(570, 517);
+            this.maximGroupBoxProximity.Name = "maximGroupBoxProximity";
+            this.maximGroupBoxProximity.Size = new System.Drawing.Size(248, 78);
+            this.maximGroupBoxProximity.TabIndex = 37;
+            this.maximGroupBoxProximity.TabStop = false;
+            this.maximGroupBoxProximity.Text = "Proximity";
+            this.maximGroupBoxProximity.Visible = false;
+            // 
+            // labelnumProxThreshold
+            // 
+            this.labelnumProxThreshold.AutoSize = true;
+            this.labelnumProxThreshold.Font = new System.Drawing.Font("Arial", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+            this.labelnumProxThreshold.Location = new System.Drawing.Point(13, 55);
+            this.labelnumProxThreshold.Name = "labelnumProxThreshold";
+            this.labelnumProxThreshold.Size = new System.Drawing.Size(123, 15);
+            this.labelnumProxThreshold.TabIndex = 24;
+            this.labelnumProxThreshold.Text = "PROX_INT_THRESH";
+            this.labelnumProxThreshold.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
+            // 
+            // numProxThreshold
+            // 
+            this.numProxThreshold.Hexadecimal = true;
+            this.numProxThreshold.Location = new System.Drawing.Point(148, 52);
+            this.numProxThreshold.Maximum = new decimal(new int[] {
+            255,
+            0,
+            0,
+            0});
+            this.numProxThreshold.Name = "numProxThreshold";
+            this.numProxThreshold.Size = new System.Drawing.Size(55, 20);
+            this.numProxThreshold.TabIndex = 14;
+            this.numProxThreshold.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
+            this.numProxThreshold.Value = new decimal(new int[] {
+            255,
+            0,
+            0,
+            0});
+            // 
+            // labelcboPilotPA
+            // 
+            this.labelcboPilotPA.AutoSize = true;
+            this.labelcboPilotPA.Font = new System.Drawing.Font("Arial", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+            this.labelcboPilotPA.Location = new System.Drawing.Point(12, 26);
+            this.labelcboPilotPA.Name = "labelcboPilotPA";
+            this.labelcboPilotPA.Size = new System.Drawing.Size(62, 15);
+            this.labelcboPilotPA.TabIndex = 4;
+            this.labelcboPilotPA.Text = "PILOT_PA";
+            this.labelcboPilotPA.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
+            // 
+            // label21
+            // 
+            this.label21.AutoSize = true;
+            this.label21.Font = new System.Drawing.Font("Arial", 9F);
+            this.label21.Location = new System.Drawing.Point(208, 26);
+            this.label21.Name = "label21";
+            this.label21.Size = new System.Drawing.Size(25, 15);
+            this.label21.TabIndex = 18;
+            this.label21.Text = "mA";
+            this.label21.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
+            // 
+            // lblAvgPilotPALEDcurrent
+            // 
+            this.lblAvgPilotPALEDcurrent.AutoSize = true;
+            this.lblAvgPilotPALEDcurrent.Font = new System.Drawing.Font("Arial", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+            this.lblAvgPilotPALEDcurrent.Location = new System.Drawing.Point(177, 26);
+            this.lblAvgPilotPALEDcurrent.Name = "lblAvgPilotPALEDcurrent";
+            this.lblAvgPilotPALEDcurrent.Size = new System.Drawing.Size(19, 15);
+            this.lblAvgPilotPALEDcurrent.TabIndex = 19;
+            this.lblAvgPilotPALEDcurrent.Text = "---";
+            this.lblAvgPilotPALEDcurrent.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
+            // 
+            // cboPilotPA
+            // 
+            this.cboPilotPA.BackColor = System.Drawing.Color.White;
+            this.cboPilotPA.DropDownHeight = 200;
+            this.cboPilotPA.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
+            this.cboPilotPA.DropDownWidth = 81;
+            this.cboPilotPA.Font = new System.Drawing.Font("Arial", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+            this.cboPilotPA.Location = new System.Drawing.Point(90, 25);
+            this.cboPilotPA.MaxDropDownItems = 10;
+            this.cboPilotPA.Name = "cboPilotPA";
+            this.cboPilotPA.Size = new System.Drawing.Size(81, 23);
+            this.cboPilotPA.TabIndex = 0;
+            this.cboPilotPA.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
+            this.cboPilotPA.TextAlignDropDownList = System.Windows.Forms.HorizontalAlignment.Left;
+            // 
+            // groupBoxOpticalMeasurements
+            // 
+            this.groupBoxOpticalMeasurements.BackgroundColor = System.Drawing.Color.White;
+            this.groupBoxOpticalMeasurements.Controls.Add(this.label45);
+            this.groupBoxOpticalMeasurements.Controls.Add(this.chartLED);
+            this.groupBoxOpticalMeasurements.Dock = System.Windows.Forms.DockStyle.Fill;
+            this.groupBoxOpticalMeasurements.Location = new System.Drawing.Point(256, 3);
+            this.groupBoxOpticalMeasurements.Name = "groupBoxOpticalMeasurements";
+            this.groupBoxOpticalMeasurements.Size = new System.Drawing.Size(246, 528);
+            this.groupBoxOpticalMeasurements.TabIndex = 36;
+            this.groupBoxOpticalMeasurements.TabStop = false;
+            this.groupBoxOpticalMeasurements.Text = "Optical Measurements";
+            // 
+            // label45
+            // 
+            this.label45.Anchor = System.Windows.Forms.AnchorStyles.Bottom;
+            this.label45.AutoSize = true;
+            this.label45.Location = new System.Drawing.Point(119, 511);
+            this.label45.Name = "label45";
+            this.label45.Size = new System.Drawing.Size(79, 13);
+            this.label45.TabIndex = 32;
+            this.label45.Text = "Time (seconds)";
+            // 
+            // chartLED
+            // 
+            this.chartLED.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) 
+            | System.Windows.Forms.AnchorStyles.Left) 
+            | System.Windows.Forms.AnchorStyles.Right)));
+            chartArea4.AxisY.IsStartedFromZero = false;
+            chartArea4.AxisY.Title = "Red ADC Code";
+            chartArea4.Name = "ChartArea1Red";
+            chartArea5.AlignWithChartArea = "ChartArea1Red";
+            chartArea5.AxisY.IsStartedFromZero = false;
+            chartArea5.AxisY.Title = "IR ADC Code";
+            chartArea5.Name = "ChartArea2IR";
+            chartArea6.AlignWithChartArea = "ChartArea1Red";
+            chartArea6.AxisY.IsStartedFromZero = false;
+            chartArea6.AxisY.Title = "Green ADC Code";
+            chartArea6.Name = "ChartArea3Green";
+            this.chartLED.ChartAreas.Add(chartArea4);
+            this.chartLED.ChartAreas.Add(chartArea5);
+            this.chartLED.ChartAreas.Add(chartArea6);
+            this.chartLED.Location = new System.Drawing.Point(6, 19);
+            this.chartLED.Name = "chartLED";
+            this.chartLED.Palette = System.Windows.Forms.DataVisualization.Charting.ChartColorPalette.None;
+            this.chartLED.PaletteCustomColors = new System.Drawing.Color[] {
+        System.Drawing.Color.Red,
+        System.Drawing.Color.FromArgb(((int)(((byte)(255)))), ((int)(((byte)(194)))), ((int)(((byte)(32))))),
+        System.Drawing.Color.FromArgb(((int)(((byte)(153)))), ((int)(((byte)(198)))), ((int)(((byte)(76))))),
+        System.Drawing.Color.FromArgb(((int)(((byte)(158)))), ((int)(((byte)(195)))), ((int)(((byte)(222))))),
+        System.Drawing.Color.FromArgb(((int)(((byte)(110)))), ((int)(((byte)(37)))), ((int)(((byte)(133))))),
+        System.Drawing.Color.FromArgb(((int)(((byte)(241)))), ((int)(((byte)(92)))), ((int)(((byte)(34)))))};
+            series4.ChartArea = "ChartArea1Red";
+            series4.ChartType = System.Windows.Forms.DataVisualization.Charting.SeriesChartType.Line;
+            series4.Color = System.Drawing.Color.FromArgb(((int)(((byte)(222)))), ((int)(((byte)(56)))), ((int)(((byte)(49)))));
+            series4.MarkerSize = 1;
+            series4.Name = "SeriesRed";
+            series4.XValueType = System.Windows.Forms.DataVisualization.Charting.ChartValueType.UInt32;
+            series4.YValueType = System.Windows.Forms.DataVisualization.Charting.ChartValueType.Int32;
+            series5.ChartArea = "ChartArea2IR";
+            series5.ChartType = System.Windows.Forms.DataVisualization.Charting.SeriesChartType.Line;
+            series5.Color = System.Drawing.Color.FromArgb(((int)(((byte)(110)))), ((int)(((byte)(37)))), ((int)(((byte)(133)))));
+            series5.Name = "SeriesIR";
+            series5.XValueType = System.Windows.Forms.DataVisualization.Charting.ChartValueType.UInt32;
+            series5.YValueType = System.Windows.Forms.DataVisualization.Charting.ChartValueType.Int32;
+            series6.ChartArea = "ChartArea3Green";
+            series6.ChartType = System.Windows.Forms.DataVisualization.Charting.SeriesChartType.Line;
+            series6.Color = System.Drawing.Color.FromArgb(((int)(((byte)(101)))), ((int)(((byte)(136)))), ((int)(((byte)(43)))));
+            series6.Name = "SeriesGreen";
+            series6.XValueType = System.Windows.Forms.DataVisualization.Charting.ChartValueType.UInt32;
+            series6.YValueType = System.Windows.Forms.DataVisualization.Charting.ChartValueType.Int32;
+            this.chartLED.Series.Add(series4);
+            this.chartLED.Series.Add(series5);
+            this.chartLED.Series.Add(series6);
+            this.chartLED.Size = new System.Drawing.Size(234, 503);
+            this.chartLED.TabIndex = 31;
+            this.chartLED.Text = "chartLED";
+            title2.Name = "Title1";
+            title2.Text = "Red";
+            title2.Visible = false;
+            this.chartLED.Titles.Add(title2);
+            // 
+            // maximGroupBoxLEDTimingSlots
+            // 
+            this.maximGroupBoxLEDTimingSlots.BackgroundColor = System.Drawing.Color.White;
+            this.maximGroupBoxLEDTimingSlots.Controls.Add(this.cboLEDslot1);
+            this.maximGroupBoxLEDTimingSlots.Controls.Add(this.cboLEDslot2);
+            this.maximGroupBoxLEDTimingSlots.Controls.Add(this.labelcboLEDslot4);
+            this.maximGroupBoxLEDTimingSlots.Controls.Add(this.cboLEDslot3);
+            this.maximGroupBoxLEDTimingSlots.Controls.Add(this.labelcboLEDslot3);
+            this.maximGroupBoxLEDTimingSlots.Controls.Add(this.cboLEDslot4);
+            this.maximGroupBoxLEDTimingSlots.Controls.Add(this.labelcboLEDslot2);
+            this.maximGroupBoxLEDTimingSlots.Controls.Add(this.labelcboLEDslot1);
+            this.maximGroupBoxLEDTimingSlots.Location = new System.Drawing.Point(3, 273);
+            this.maximGroupBoxLEDTimingSlots.Name = "maximGroupBoxLEDTimingSlots";
+            this.maximGroupBoxLEDTimingSlots.Size = new System.Drawing.Size(248, 131);
+            this.maximGroupBoxLEDTimingSlots.TabIndex = 34;
+            this.maximGroupBoxLEDTimingSlots.TabStop = false;
+            this.maximGroupBoxLEDTimingSlots.Text = "LED Mode: Timing Slots";
+            // 
+            // cboLEDslot1
+            // 
+            this.cboLEDslot1.BackColor = System.Drawing.Color.White;
+            this.cboLEDslot1.DropDownHeight = 200;
+            this.cboLEDslot1.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
+            this.cboLEDslot1.DropDownWidth = 160;
+            this.cboLEDslot1.Font = new System.Drawing.Font("Arial", 9F);
+            this.cboLEDslot1.Items.AddRange(new object[] {
+            "Disabled",
+            "LED1 (Red)",
+            "LED2 (IR)",
+            "LED3 (Green)",
+            "LED4 (Green)",
+            "LED1 Pilot",
+            "LED2 Pilot",
+            "Reserved"});
+            this.cboLEDslot1.Location = new System.Drawing.Point(80, 29);
+            this.cboLEDslot1.Name = "cboLEDslot1";
+            this.cboLEDslot1.Size = new System.Drawing.Size(160, 21);
+            this.cboLEDslot1.TabIndex = 14;
+            this.cboLEDslot1.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
+            this.cboLEDslot1.TextAlignDropDownList = System.Windows.Forms.HorizontalAlignment.Left;
+            // 
+            // cboLEDslot2
+            // 
+            this.cboLEDslot2.BackColor = System.Drawing.Color.White;
+            this.cboLEDslot2.DropDownHeight = 200;
+            this.cboLEDslot2.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
+            this.cboLEDslot2.DropDownWidth = 160;
+            this.cboLEDslot2.Font = new System.Drawing.Font("Arial", 9F);
+            this.cboLEDslot2.Items.AddRange(new object[] {
+            "Disabled",
+            "LED1 (Red)",
+            "LED2 (IR)",
+            "LED3 (Green)",
+            "LED4 (Green)",
+            "LED1 Pilot",
+            "LED2 Pilot",
+            "Reserved"});
+            this.cboLEDslot2.Location = new System.Drawing.Point(80, 54);
+            this.cboLEDslot2.Name = "cboLEDslot2";
+            this.cboLEDslot2.Size = new System.Drawing.Size(160, 21);
+            this.cboLEDslot2.TabIndex = 14;
+            this.cboLEDslot2.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
+            this.cboLEDslot2.TextAlignDropDownList = System.Windows.Forms.HorizontalAlignment.Left;
+            // 
+            // labelcboLEDslot4
+            // 
+            this.labelcboLEDslot4.AutoSize = true;
+            this.labelcboLEDslot4.Font = new System.Drawing.Font("Arial", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+            this.labelcboLEDslot4.Location = new System.Drawing.Point(5, 107);
+            this.labelcboLEDslot4.Name = "labelcboLEDslot4";
+            this.labelcboLEDslot4.Size = new System.Drawing.Size(65, 15);
+            this.labelcboLEDslot4.TabIndex = 15;
+            this.labelcboLEDslot4.Text = "LED Slot 4";
+            // 
+            // cboLEDslot3
+            // 
+            this.cboLEDslot3.BackColor = System.Drawing.Color.White;
+            this.cboLEDslot3.DropDownHeight = 200;
+            this.cboLEDslot3.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
+            this.cboLEDslot3.DropDownWidth = 160;
+            this.cboLEDslot3.Font = new System.Drawing.Font("Arial", 9F);
+            this.cboLEDslot3.Items.AddRange(new object[] {
+            "Disabled",
+            "LED1 (Red)",
+            "LED2 (IR)",
+            "LED3 (Green)",
+            "LED4 (Green)",
+            "LED1 Pilot",
+            "LED2 Pilot",
+            "Reserved"});
+            this.cboLEDslot3.Location = new System.Drawing.Point(80, 79);
+            this.cboLEDslot3.Name = "cboLEDslot3";
+            this.cboLEDslot3.Size = new System.Drawing.Size(160, 21);
+            this.cboLEDslot3.TabIndex = 14;
+            this.cboLEDslot3.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
+            this.cboLEDslot3.TextAlignDropDownList = System.Windows.Forms.HorizontalAlignment.Left;
+            // 
+            // labelcboLEDslot3
+            // 
+            this.labelcboLEDslot3.AutoSize = true;
+            this.labelcboLEDslot3.Font = new System.Drawing.Font("Arial", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+            this.labelcboLEDslot3.Location = new System.Drawing.Point(5, 83);
+            this.labelcboLEDslot3.Name = "labelcboLEDslot3";
+            this.labelcboLEDslot3.Size = new System.Drawing.Size(65, 15);
+            this.labelcboLEDslot3.TabIndex = 15;
+            this.labelcboLEDslot3.Text = "LED Slot 3";
+            // 
+            // cboLEDslot4
+            // 
+            this.cboLEDslot4.BackColor = System.Drawing.Color.White;
+            this.cboLEDslot4.DropDownHeight = 200;
+            this.cboLEDslot4.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
+            this.cboLEDslot4.DropDownWidth = 160;
+            this.cboLEDslot4.Font = new System.Drawing.Font("Arial", 9F);
+            this.cboLEDslot4.Items.AddRange(new object[] {
+            "Disabled",
+            "LED1 (Red)",
+            "LED2 (IR)",
+            "LED3 (Green)",
+            "LED4 (Green)",
+            "LED1 Pilot",
+            "LED2 Pilot",
+            "Reserved"});
+            this.cboLEDslot4.Location = new System.Drawing.Point(80, 104);
+            this.cboLEDslot4.Name = "cboLEDslot4";
+            this.cboLEDslot4.Size = new System.Drawing.Size(160, 21);
+            this.cboLEDslot4.TabIndex = 14;
+            this.cboLEDslot4.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
+            this.cboLEDslot4.TextAlignDropDownList = System.Windows.Forms.HorizontalAlignment.Left;
+            // 
+            // labelcboLEDslot2
+            // 
+            this.labelcboLEDslot2.AutoSize = true;
+            this.labelcboLEDslot2.Font = new System.Drawing.Font("Arial", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+            this.labelcboLEDslot2.Location = new System.Drawing.Point(5, 57);
+            this.labelcboLEDslot2.Name = "labelcboLEDslot2";
+            this.labelcboLEDslot2.Size = new System.Drawing.Size(65, 15);
+            this.labelcboLEDslot2.TabIndex = 15;
+            this.labelcboLEDslot2.Text = "LED Slot 2";
+            // 
+            // labelcboLEDslot1
+            // 
+            this.labelcboLEDslot1.AutoSize = true;
+            this.labelcboLEDslot1.Font = new System.Drawing.Font("Arial", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+            this.labelcboLEDslot1.Location = new System.Drawing.Point(5, 32);
+            this.labelcboLEDslot1.Name = "labelcboLEDslot1";
+            this.labelcboLEDslot1.Size = new System.Drawing.Size(65, 15);
+            this.labelcboLEDslot1.TabIndex = 15;
+            this.labelcboLEDslot1.Text = "LED Slot 1";
+            // 
+            // maximGroupBoxSettings
+            // 
+            this.maximGroupBoxSettings.BackgroundColor = System.Drawing.Color.White;
+            this.maximGroupBoxSettings.Controls.Add(this.label28);
+            this.maximGroupBoxSettings.Controls.Add(this.label25);
+            this.maximGroupBoxSettings.Controls.Add(this.label26);
+            this.maximGroupBoxSettings.Controls.Add(this.label27);
+            this.maximGroupBoxSettings.Controls.Add(this.cboADCFSrangenA);
+            this.maximGroupBoxSettings.Controls.Add(this.label29);
+            this.maximGroupBoxSettings.Controls.Add(this.cboSampleAvg);
+            this.maximGroupBoxSettings.Controls.Add(this.label30);
+            this.maximGroupBoxSettings.Controls.Add(this.cboSampleRate);
+            this.maximGroupBoxSettings.Controls.Add(this.label31);
+            this.maximGroupBoxSettings.Controls.Add(this.cboPulseWidth);
+            this.maximGroupBoxSettings.Location = new System.Drawing.Point(3, 40);
+            this.maximGroupBoxSettings.Name = "maximGroupBoxSettings";
+            this.maximGroupBoxSettings.Size = new System.Drawing.Size(248, 119);
+            this.maximGroupBoxSettings.TabIndex = 35;
+            this.maximGroupBoxSettings.TabStop = false;
+            this.maximGroupBoxSettings.Text = "Settings";
+            // 
+            // label28
+            // 
+            this.label28.AutoSize = true;
+            this.label28.Font = new System.Drawing.Font("Arial", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+            this.label28.Location = new System.Drawing.Point(11, 93);
+            this.label28.Name = "label28";
+            this.label28.Size = new System.Drawing.Size(129, 15);
+            this.label28.TabIndex = 25;
+            this.label28.Text = "ADC Full Scale Range";
+            this.label28.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
+            // 
+            // label25
+            // 
+            this.label25.AutoSize = true;
+            this.label25.Font = new System.Drawing.Font("Arial", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+            this.label25.Location = new System.Drawing.Point(11, 26);
+            this.label25.Name = "label25";
+            this.label25.Size = new System.Drawing.Size(79, 15);
+            this.label25.TabIndex = 4;
+            this.label25.Text = "Sample Rate";
+            this.label25.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
+            // 
+            // label26
+            // 
+            this.label26.AutoSize = true;
+            this.label26.Font = new System.Drawing.Font("Arial", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+            this.label26.Location = new System.Drawing.Point(11, 48);
+            this.label26.Name = "label26";
+            this.label26.Size = new System.Drawing.Size(96, 15);
+            this.label26.TabIndex = 22;
+            this.label26.Text = "Sample Average";
+            this.label26.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
+            // 
+            // label27
+            // 
+            this.label27.AutoSize = true;
+            this.label27.Font = new System.Drawing.Font("Arial", 9F);
+            this.label27.Location = new System.Drawing.Point(219, 29);
+            this.label27.Name = "label27";
+            this.label27.Size = new System.Drawing.Size(21, 15);
+            this.label27.TabIndex = 4;
+            this.label27.Text = "Hz";
+            this.label27.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
+            // 
+            // cboADCFSrangenA
+            // 
+            this.cboADCFSrangenA.BackColor = System.Drawing.Color.White;
+            this.cboADCFSrangenA.DropDownHeight = 200;
+            this.cboADCFSrangenA.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
+            this.cboADCFSrangenA.DropDownWidth = 70;
+            this.cboADCFSrangenA.Font = new System.Drawing.Font("Arial", 9F);
+            this.cboADCFSrangenA.Location = new System.Drawing.Point(145, 92);
+            this.cboADCFSrangenA.MaxDropDownItems = 10;
+            this.cboADCFSrangenA.Name = "cboADCFSrangenA";
+            this.cboADCFSrangenA.Size = new System.Drawing.Size(70, 21);
+            this.cboADCFSrangenA.TabIndex = 20;
+            this.cboADCFSrangenA.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
+            this.cboADCFSrangenA.TextAlignDropDownList = System.Windows.Forms.HorizontalAlignment.Left;
+            // 
+            // label29
+            // 
+            this.label29.AutoSize = true;
+            this.label29.Font = new System.Drawing.Font("Arial", 9F);
+            this.label29.Location = new System.Drawing.Point(219, 73);
+            this.label29.Name = "label29";
+            this.label29.Size = new System.Drawing.Size(21, 15);
+            this.label29.TabIndex = 4;
+            this.label29.Text = "µs";
+            this.label29.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
+            // 
+            // cboSampleAvg
+            // 
+            this.cboSampleAvg.BackColor = System.Drawing.Color.White;
+            this.cboSampleAvg.DropDownHeight = 200;
+            this.cboSampleAvg.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
+            this.cboSampleAvg.DropDownWidth = 70;
+            this.cboSampleAvg.Font = new System.Drawing.Font("Arial", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+            this.cboSampleAvg.Location = new System.Drawing.Point(145, 48);
+            this.cboSampleAvg.MaxDropDownItems = 10;
+            this.cboSampleAvg.Name = "cboSampleAvg";
+            this.cboSampleAvg.Size = new System.Drawing.Size(70, 21);
+            this.cboSampleAvg.TabIndex = 12;
+            this.cboSampleAvg.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
+            this.cboSampleAvg.TextAlignDropDownList = System.Windows.Forms.HorizontalAlignment.Left;
+            // 
+            // label30
+            // 
+            this.label30.AutoSize = true;
+            this.label30.Font = new System.Drawing.Font("Arial", 9F);
+            this.label30.Location = new System.Drawing.Point(219, 95);
+            this.label30.Name = "label30";
+            this.label30.Size = new System.Drawing.Size(21, 15);
+            this.label30.TabIndex = 4;
+            this.label30.Text = "nA";
+            this.label30.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
+            // 
+            // cboSampleRate
+            // 
+            this.cboSampleRate.BackColor = System.Drawing.Color.White;
+            this.cboSampleRate.DropDownHeight = 200;
+            this.cboSampleRate.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
+            this.cboSampleRate.DropDownWidth = 70;
+            this.cboSampleRate.Font = new System.Drawing.Font("Arial", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+            this.cboSampleRate.Location = new System.Drawing.Point(145, 26);
+            this.cboSampleRate.MaxDropDownItems = 10;
+            this.cboSampleRate.Name = "cboSampleRate";
+            this.cboSampleRate.Size = new System.Drawing.Size(70, 21);
+            this.cboSampleRate.TabIndex = 0;
+            this.cboSampleRate.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
+            this.cboSampleRate.TextAlignDropDownList = System.Windows.Forms.HorizontalAlignment.Left;
+            // 
+            // label31
+            // 
+            this.label31.AutoSize = true;
+            this.label31.Font = new System.Drawing.Font("Arial", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+            this.label31.Location = new System.Drawing.Point(11, 71);
+            this.label31.Name = "label31";
+            this.label31.Size = new System.Drawing.Size(73, 15);
+            this.label31.TabIndex = 4;
+            this.label31.Text = "Pulse Width";
+            this.label31.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
+            // 
+            // cboPulseWidth
+            // 
+            this.cboPulseWidth.BackColor = System.Drawing.Color.White;
+            this.cboPulseWidth.DropDownHeight = 200;
+            this.cboPulseWidth.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
+            this.cboPulseWidth.DropDownWidth = 70;
+            this.cboPulseWidth.Font = new System.Drawing.Font("Arial", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+            this.cboPulseWidth.Location = new System.Drawing.Point(145, 70);
+            this.cboPulseWidth.MaxDropDownItems = 10;
+            this.cboPulseWidth.Name = "cboPulseWidth";
+            this.cboPulseWidth.Size = new System.Drawing.Size(70, 21);
+            this.cboPulseWidth.TabIndex = 0;
+            this.cboPulseWidth.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
+            this.cboPulseWidth.TextAlignDropDownList = System.Windows.Forms.HorizontalAlignment.Left;
+            // 
+            // maximGroupBoxLEDcurrents
+            // 
+            this.maximGroupBoxLEDcurrents.BackgroundColor = System.Drawing.Color.White;
+            this.maximGroupBoxLEDcurrents.Controls.Add(this.cboIRLED);
+            this.maximGroupBoxLEDcurrents.Controls.Add(this.labelcboRedLED);
+            this.maximGroupBoxLEDcurrents.Controls.Add(this.labelcboGreenLED);
+            this.maximGroupBoxLEDcurrents.Controls.Add(this.label32);
+            this.maximGroupBoxLEDcurrents.Controls.Add(this.label33);
+            this.maximGroupBoxLEDcurrents.Controls.Add(this.label35);
+            this.maximGroupBoxLEDcurrents.Controls.Add(this.label34);
+            this.maximGroupBoxLEDcurrents.Controls.Add(this.labelcboIRLED);
+            this.maximGroupBoxLEDcurrents.Controls.Add(this.cboRedLED);
+            this.maximGroupBoxLEDcurrents.Controls.Add(this.cboGreenLED);
+            this.maximGroupBoxLEDcurrents.Controls.Add(this.lblAvgIRLEDcurrent);
+            this.maximGroupBoxLEDcurrents.Controls.Add(this.lblAvgGreenLEDcurrent);
+            this.maximGroupBoxLEDcurrents.Controls.Add(this.lblAvgRedLEDcurrent);
+            this.maximGroupBoxLEDcurrents.Controls.Add(this.label36);
+            this.maximGroupBoxLEDcurrents.Controls.Add(this.label37);
+            this.maximGroupBoxLEDcurrents.Location = new System.Drawing.Point(3, 161);
+            this.maximGroupBoxLEDcurrents.Name = "maximGroupBoxLEDcurrents";
+            this.maximGroupBoxLEDcurrents.Size = new System.Drawing.Size(248, 110);
+            this.maximGroupBoxLEDcurrents.TabIndex = 33;
+            this.maximGroupBoxLEDcurrents.TabStop = false;
+            this.maximGroupBoxLEDcurrents.Text = "LED Currents";
+            // 
+            // cboIRLED
+            // 
+            this.cboIRLED.BackColor = System.Drawing.Color.White;
+            this.cboIRLED.DropDownHeight = 200;
+            this.cboIRLED.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
+            this.cboIRLED.DropDownWidth = 81;
+            this.cboIRLED.Font = new System.Drawing.Font("Arial", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+            this.cboIRLED.Location = new System.Drawing.Point(90, 64);
+            this.cboIRLED.MaxDropDownItems = 10;
+            this.cboIRLED.Name = "cboIRLED";
+            this.cboIRLED.Size = new System.Drawing.Size(81, 21);
+            this.cboIRLED.TabIndex = 0;
+            this.cboIRLED.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
+            this.cboIRLED.TextAlignDropDownList = System.Windows.Forms.HorizontalAlignment.Left;
+            // 
+            // labelcboRedLED
+            // 
+            this.labelcboRedLED.AutoSize = true;
+            this.labelcboRedLED.Font = new System.Drawing.Font("Arial", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+            this.labelcboRedLED.Location = new System.Drawing.Point(12, 43);
+            this.labelcboRedLED.Name = "labelcboRedLED";
+            this.labelcboRedLED.Size = new System.Drawing.Size(30, 15);
+            this.labelcboRedLED.TabIndex = 4;
+            this.labelcboRedLED.Text = "Red";
+            this.labelcboRedLED.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
+            // 
+            // labelcboGreenLED
+            // 
+            this.labelcboGreenLED.AutoSize = true;
+            this.labelcboGreenLED.Font = new System.Drawing.Font("Arial", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+            this.labelcboGreenLED.Location = new System.Drawing.Point(12, 87);
+            this.labelcboGreenLED.Name = "labelcboGreenLED";
+            this.labelcboGreenLED.Size = new System.Drawing.Size(41, 15);
+            this.labelcboGreenLED.TabIndex = 4;
+            this.labelcboGreenLED.Text = "Green";
+            this.labelcboGreenLED.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
+            // 
+            // label32
+            // 
+            this.label32.AutoSize = true;
+            this.label32.Font = new System.Drawing.Font("Arial", 9F);
+            this.label32.Location = new System.Drawing.Point(207, 43);
+            this.label32.Name = "label32";
+            this.label32.Size = new System.Drawing.Size(25, 15);
+            this.label32.TabIndex = 4;
+            this.label32.Text = "mA";
+            this.label32.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
+            // 
+            // label33
+            // 
+            this.label33.AutoSize = true;
+            this.label33.Font = new System.Drawing.Font("Arial", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+            this.label33.Location = new System.Drawing.Point(178, 24);
+            this.label33.Name = "label33";
+            this.label33.Size = new System.Drawing.Size(51, 15);
+            this.label33.TabIndex = 4;
+            this.label33.Text = "Average";
+            this.label33.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
+            // 
+            // label35
+            // 
+            this.label35.AutoSize = true;
+            this.label35.Font = new System.Drawing.Font("Arial", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+            this.label35.Location = new System.Drawing.Point(12, 24);
+            this.label35.Name = "label35";
+            this.label35.Size = new System.Drawing.Size(64, 15);
+            this.label35.TabIndex = 4;
+            this.label35.Text = "LED Color";
+            this.label35.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
+            // 
+            // label34
+            // 
+            this.label34.AutoSize = true;
+            this.label34.Font = new System.Drawing.Font("Arial", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+            this.label34.Location = new System.Drawing.Point(111, 24);
+            this.label34.Name = "label34";
+            this.label34.Size = new System.Drawing.Size(35, 15);
+            this.label34.TabIndex = 4;
+            this.label34.Text = "Peak";
+            this.label34.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
+            // 
+            // labelcboIRLED
+            // 
+            this.labelcboIRLED.AutoSize = true;
+            this.labelcboIRLED.Font = new System.Drawing.Font("Arial", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+            this.labelcboIRLED.Location = new System.Drawing.Point(12, 65);
+            this.labelcboIRLED.Name = "labelcboIRLED";
+            this.labelcboIRLED.Size = new System.Drawing.Size(72, 15);
+            this.labelcboIRLED.TabIndex = 4;
+            this.labelcboIRLED.Text = "IR (Infrared)";
+            this.labelcboIRLED.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
+            // 
+            // cboRedLED
+            // 
+            this.cboRedLED.BackColor = System.Drawing.Color.White;
+            this.cboRedLED.DropDownHeight = 200;
+            this.cboRedLED.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
+            this.cboRedLED.DropDownWidth = 81;
+            this.cboRedLED.Font = new System.Drawing.Font("Arial", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+            this.cboRedLED.Location = new System.Drawing.Point(90, 42);
+            this.cboRedLED.MaxDropDownItems = 10;
+            this.cboRedLED.Name = "cboRedLED";
+            this.cboRedLED.Size = new System.Drawing.Size(81, 21);
+            this.cboRedLED.TabIndex = 0;
+            this.cboRedLED.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
+            this.cboRedLED.TextAlignDropDownList = System.Windows.Forms.HorizontalAlignment.Left;
+            // 
+            // cboGreenLED
+            // 
+            this.cboGreenLED.BackColor = System.Drawing.Color.White;
+            this.cboGreenLED.DropDownHeight = 200;
+            this.cboGreenLED.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
+            this.cboGreenLED.DropDownWidth = 81;
+            this.cboGreenLED.Font = new System.Drawing.Font("Arial", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+            this.cboGreenLED.Location = new System.Drawing.Point(90, 86);
+            this.cboGreenLED.MaxDropDownItems = 10;
+            this.cboGreenLED.Name = "cboGreenLED";
+            this.cboGreenLED.Size = new System.Drawing.Size(81, 21);
+            this.cboGreenLED.TabIndex = 0;
+            this.cboGreenLED.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
+            this.cboGreenLED.TextAlignDropDownList = System.Windows.Forms.HorizontalAlignment.Left;
+            // 
+            // lblAvgIRLEDcurrent
+            // 
+            this.lblAvgIRLEDcurrent.AutoSize = true;
+            this.lblAvgIRLEDcurrent.Font = new System.Drawing.Font("Arial", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+            this.lblAvgIRLEDcurrent.Location = new System.Drawing.Point(178, 65);
+            this.lblAvgIRLEDcurrent.Name = "lblAvgIRLEDcurrent";
+            this.lblAvgIRLEDcurrent.Size = new System.Drawing.Size(19, 15);
+            this.lblAvgIRLEDcurrent.TabIndex = 16;
+            this.lblAvgIRLEDcurrent.Text = "---";
+            this.lblAvgIRLEDcurrent.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
+            // 
+            // lblAvgGreenLEDcurrent
+            // 
+            this.lblAvgGreenLEDcurrent.AutoSize = true;
+            this.lblAvgGreenLEDcurrent.Font = new System.Drawing.Font("Arial", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+            this.lblAvgGreenLEDcurrent.Location = new System.Drawing.Point(178, 87);
+            this.lblAvgGreenLEDcurrent.Name = "lblAvgGreenLEDcurrent";
+            this.lblAvgGreenLEDcurrent.Size = new System.Drawing.Size(19, 15);
+            this.lblAvgGreenLEDcurrent.TabIndex = 19;
+            this.lblAvgGreenLEDcurrent.Text = "---";
+            this.lblAvgGreenLEDcurrent.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
+            // 
+            // lblAvgRedLEDcurrent
+            // 
+            this.lblAvgRedLEDcurrent.AutoSize = true;
+            this.lblAvgRedLEDcurrent.Font = new System.Drawing.Font("Arial", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+            this.lblAvgRedLEDcurrent.Location = new System.Drawing.Point(178, 43);
+            this.lblAvgRedLEDcurrent.Name = "lblAvgRedLEDcurrent";
+            this.lblAvgRedLEDcurrent.Size = new System.Drawing.Size(19, 15);
+            this.lblAvgRedLEDcurrent.TabIndex = 19;
+            this.lblAvgRedLEDcurrent.Text = "---";
+            this.lblAvgRedLEDcurrent.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
+            // 
+            // label36
+            // 
+            this.label36.AutoSize = true;
+            this.label36.Font = new System.Drawing.Font("Arial", 9F);
+            this.label36.Location = new System.Drawing.Point(207, 65);
+            this.label36.Name = "label36";
+            this.label36.Size = new System.Drawing.Size(25, 15);
+            this.label36.TabIndex = 15;
+            this.label36.Text = "mA";
+            this.label36.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
+            // 
+            // label37
+            // 
+            this.label37.AutoSize = true;
+            this.label37.Font = new System.Drawing.Font("Arial", 9F);
+            this.label37.Location = new System.Drawing.Point(207, 87);
+            this.label37.Name = "label37";
+            this.label37.Size = new System.Drawing.Size(25, 15);
+            this.label37.TabIndex = 18;
+            this.label37.Text = "mA";
+            this.label37.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
+            // 
+            // maximGroupBoxRegs
+            // 
+            this.maximGroupBoxRegs.BackgroundColor = System.Drawing.Color.White;
+            this.maximGroupBoxRegs.Controls.Add(this.textBoxRegValue);
+            this.maximGroupBoxRegs.Controls.Add(this.btnRegWrite);
+            this.maximGroupBoxRegs.Controls.Add(this.btnRegRead);
+            this.maximGroupBoxRegs.Controls.Add(this.comboBoxRegAddr);
+            this.maximGroupBoxRegs.Enabled = false;
+            this.maximGroupBoxRegs.Location = new System.Drawing.Point(306, 534);
+            this.maximGroupBoxRegs.Name = "maximGroupBoxRegs";
+            this.maximGroupBoxRegs.Size = new System.Drawing.Size(248, 53);
+            this.maximGroupBoxRegs.TabIndex = 31;
+            this.maximGroupBoxRegs.TabStop = false;
+            this.maximGroupBoxRegs.Text = "Registers";
+            this.maximGroupBoxRegs.Visible = false;
+            // 
+            // textBoxRegValue
+            // 
+            this.textBoxRegValue.Location = new System.Drawing.Point(169, 25);
+            this.textBoxRegValue.Name = "textBoxRegValue";
+            this.textBoxRegValue.Size = new System.Drawing.Size(41, 20);
+            this.textBoxRegValue.TabIndex = 2;
+            this.textBoxRegValue.Text = "0xFF";
+            // 
+            // btnRegWrite
+            // 
+            this.btnRegWrite.Location = new System.Drawing.Point(215, 25);
+            this.btnRegWrite.Name = "btnRegWrite";
+            this.btnRegWrite.Size = new System.Drawing.Size(28, 23);
+            this.btnRegWrite.TabIndex = 1;
+            this.btnRegWrite.Text = "Wr";
+            this.btnRegWrite.UseVisualStyleBackColor = true;
+            // 
+            // btnRegRead
+            // 
+            this.btnRegRead.Location = new System.Drawing.Point(137, 25);
+            this.btnRegRead.Name = "btnRegRead";
+            this.btnRegRead.Size = new System.Drawing.Size(26, 23);
+            this.btnRegRead.TabIndex = 1;
+            this.btnRegRead.Text = "Rd";
+            this.btnRegRead.UseVisualStyleBackColor = true;
+            // 
+            // comboBoxRegAddr
+            // 
+            this.comboBoxRegAddr.BackColor = System.Drawing.Color.White;
+            this.comboBoxRegAddr.DropDownHeight = 200;
+            this.comboBoxRegAddr.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
+            this.comboBoxRegAddr.DropDownWidth = 126;
+            this.comboBoxRegAddr.Font = new System.Drawing.Font("Arial", 7.8F);
+            this.comboBoxRegAddr.Location = new System.Drawing.Point(6, 23);
+            this.comboBoxRegAddr.Name = "comboBoxRegAddr";
+            this.comboBoxRegAddr.Size = new System.Drawing.Size(126, 21);
+            this.comboBoxRegAddr.TabIndex = 0;
+            this.comboBoxRegAddr.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
+            this.comboBoxRegAddr.TextAlignDropDownList = System.Windows.Forms.HorizontalAlignment.Left;
+            // 
+            // btnDefaults
+            // 
+            this.btnDefaults.Location = new System.Drawing.Point(133, 412);
+            this.btnDefaults.Name = "btnDefaults";
+            this.btnDefaults.Size = new System.Drawing.Size(118, 23);
+            this.btnDefaults.TabIndex = 26;
+            this.btnDefaults.Text = "Restore Defaults";
+            this.btnDefaults.UseVisualStyleBackColor = true;
+            this.btnDefaults.Click += new System.EventHandler(this.btnDefaults_Click);
+            // 
+            // btnMonitoring
+            // 
+            this.btnMonitoring.Location = new System.Drawing.Point(3, 412);
+            this.btnMonitoring.Name = "btnMonitoring";
+            this.btnMonitoring.Size = new System.Drawing.Size(120, 23);
+            this.btnMonitoring.TabIndex = 13;
+            this.btnMonitoring.Text = "Start Monitor";
+            this.btnMonitoring.UseVisualStyleBackColor = true;
+            this.btnMonitoring.Click += new System.EventHandler(this.btnMonitoring_Click);
+            // 
+            // label38
+            // 
+            this.label38.AutoSize = true;
+            this.label38.Font = new System.Drawing.Font("Arial", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+            this.label38.Location = new System.Drawing.Point(6, 11);
+            this.label38.Name = "label38";
+            this.label38.Size = new System.Drawing.Size(114, 15);
+            this.label38.TabIndex = 21;
+            this.label38.Text = "Mode Configuration";
+            this.label38.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
+            // 
+            // cboMode
+            // 
+            this.cboMode.BackColor = System.Drawing.Color.White;
+            this.cboMode.DropDownHeight = 200;
+            this.cboMode.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
+            this.cboMode.DropDownWidth = 70;
+            this.cboMode.Font = new System.Drawing.Font("Arial", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+            this.cboMode.Location = new System.Drawing.Point(145, 8);
+            this.cboMode.MaxDropDownItems = 10;
+            this.cboMode.Name = "cboMode";
+            this.cboMode.Size = new System.Drawing.Size(70, 21);
+            this.cboMode.TabIndex = 20;
+            this.cboMode.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
+            this.cboMode.TextAlignDropDownList = System.Windows.Forms.HorizontalAlignment.Left;
+            this.cboMode.SelectedIndexChanged += new System.EventHandler(this.cbo_IndexChanged);
+            // 
+            // button1
+            // 
+            this.button1.Location = new System.Drawing.Point(147, 542);
+            this.button1.Name = "button1";
+            this.button1.Size = new System.Drawing.Size(75, 23);
+            this.button1.TabIndex = 39;
+            this.button1.Text = "button1";
+            this.button1.UseVisualStyleBackColor = true;
+            this.button1.Visible = false;
+            this.button1.Click += new System.EventHandler(this.button1_Click_1);
+            // 
+            // lblPulseInterval
+            // 
+            this.lblPulseInterval.AutoSize = true;
+            this.lblPulseInterval.Font = new System.Drawing.Font("Microsoft Sans Serif", 12F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+            this.lblPulseInterval.Location = new System.Drawing.Point(852, 468);
+            this.lblPulseInterval.Name = "lblPulseInterval";
+            this.lblPulseInterval.Size = new System.Drawing.Size(18, 20);
+            this.lblPulseInterval.TabIndex = 51;
+            this.lblPulseInterval.Text = "0";
+            this.lblPulseInterval.Visible = false;
+            // 
+            // tableLayoutPanel1
+            // 
+            this.tableLayoutPanel1.ColumnCount = 3;
+            this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 253F));
+            this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 50F));
+            this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 50F));
+            this.tableLayoutPanel1.Controls.Add(this.groupBoxOpticalMeasurements, 1, 0);
+            this.tableLayoutPanel1.Controls.Add(this.groupBoxAccelMeasurements, 2, 0);
+            this.tableLayoutPanel1.Controls.Add(this.panel1, 0, 0);
+            this.tableLayoutPanel1.Dock = System.Windows.Forms.DockStyle.Fill;
+            this.tableLayoutPanel1.Location = new System.Drawing.Point(0, 0);
+            this.tableLayoutPanel1.Name = "tableLayoutPanel1";
+            this.tableLayoutPanel1.RowCount = 1;
+            this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F));
+            this.tableLayoutPanel1.Size = new System.Drawing.Size(758, 534);
+            this.tableLayoutPanel1.TabIndex = 54;
+            // 
+            // panel1
+            // 
+            this.panel1.Controls.Add(this.label38);
+            this.panel1.Controls.Add(this.cboMode);
+            this.panel1.Location = new System.Drawing.Point(3, 3);
+            this.panel1.Name = "panel1";
+            this.panel1.Size = new System.Drawing.Size(247, 36);
+            this.panel1.TabIndex = 39;
+            // 
+            // grpAlgorithm
+            // 
+            this.grpAlgorithm.BackgroundColor = System.Drawing.Color.White;
+            this.grpAlgorithm.Controls.Add(this.lblSpO2);
+            this.grpAlgorithm.Controls.Add(this.lblHeartRate);
+            this.grpAlgorithm.Controls.Add(this.label8);
+            this.grpAlgorithm.Controls.Add(this.label6);
+            this.grpAlgorithm.Controls.Add(this.label2);
+            this.grpAlgorithm.Controls.Add(this.label1);
+            this.grpAlgorithm.Location = new System.Drawing.Point(2, 438);
+            this.grpAlgorithm.Name = "grpAlgorithm";
+            this.grpAlgorithm.Size = new System.Drawing.Size(248, 80);
+            this.grpAlgorithm.TabIndex = 33;
+            this.grpAlgorithm.TabStop = false;
+            this.grpAlgorithm.Text = "Algorithm";
+            // 
+            // lblSpO2
+            // 
+            this.lblSpO2.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
+            this.lblSpO2.Font = new System.Drawing.Font("Arial", 9.75F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+            this.lblSpO2.Location = new System.Drawing.Point(133, 51);
+            this.lblSpO2.Name = "lblSpO2";
+            this.lblSpO2.Size = new System.Drawing.Size(56, 24);
+            this.lblSpO2.TabIndex = 5;
+            this.lblSpO2.Text = "-----";
+            this.lblSpO2.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
+            // 
+            // lblHeartRate
+            // 
+            this.lblHeartRate.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
+            this.lblHeartRate.Font = new System.Drawing.Font("Arial", 9.75F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+            this.lblHeartRate.Location = new System.Drawing.Point(133, 22);
+            this.lblHeartRate.Name = "lblHeartRate";
+            this.lblHeartRate.Size = new System.Drawing.Size(56, 24);
+            this.lblHeartRate.TabIndex = 4;
+            this.lblHeartRate.Text = "-----";
+            this.lblHeartRate.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
+            // 
+            // label8
+            // 
+            this.label8.AutoSize = true;
+            this.label8.Font = new System.Drawing.Font("Arial", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+            this.label8.Location = new System.Drawing.Point(195, 56);
+            this.label8.Name = "label8";
+            this.label8.Size = new System.Drawing.Size(18, 15);
+            this.label8.TabIndex = 3;
+            this.label8.Text = "%";
+            // 
+            // label6
+            // 
+            this.label6.AutoSize = true;
+            this.label6.Font = new System.Drawing.Font("Arial", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+            this.label6.Location = new System.Drawing.Point(195, 27);
+            this.label6.Name = "label6";
+            this.label6.Size = new System.Drawing.Size(32, 15);
+            this.label6.TabIndex = 2;
+            this.label6.Text = "BPM";
+            // 
+            // label2
+            // 
+            this.label2.AutoSize = true;
+            this.label2.Font = new System.Drawing.Font("Arial", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+            this.label2.Location = new System.Drawing.Point(6, 56);
+            this.label2.Name = "label2";
+            this.label2.Size = new System.Drawing.Size(38, 15);
+            this.label2.TabIndex = 1;
+            this.label2.Text = "SpO2";
+            // 
+            // label1
+            // 
+            this.label1.AutoSize = true;
+            this.label1.Font = new System.Drawing.Font("Arial", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+            this.label1.Location = new System.Drawing.Point(7, 27);
+            this.label1.Name = "label1";
+            this.label1.Size = new System.Drawing.Size(66, 15);
+            this.label1.TabIndex = 0;
+            this.label1.Text = "Heart Rate";
+            // 
+            // OpticalView
+            // 
+            this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
+            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+            this.BackColor = System.Drawing.Color.White;
+            this.Controls.Add(this.grpAlgorithm);
+            this.Controls.Add(this.maximGroupBoxProximity);
+            this.Controls.Add(this.lblPulseInterval);
+            this.Controls.Add(this.button1);
+            this.Controls.Add(this.maximGroupBoxLEDTimingSlots);
+            this.Controls.Add(this.btnMonitoring);
+            this.Controls.Add(this.maximGroupBoxSettings);
+            this.Controls.Add(this.btnDefaults);
+            this.Controls.Add(this.maximGroupBoxLEDcurrents);
+            this.Controls.Add(this.maximGroupBoxRegs);
+            this.Controls.Add(this.tableLayoutPanel1);
+            this.Name = "OpticalView";
+            this.Size = new System.Drawing.Size(758, 534);
+            this.Load += new System.EventHandler(this.OpticalView_Load);
+            this.groupBoxAccelMeasurements.ResumeLayout(false);
+            this.groupBoxAccelMeasurements.PerformLayout();
+            ((System.ComponentModel.ISupportInitialize)(this.chartAccel)).EndInit();
+            this.maximGroupBoxProximity.ResumeLayout(false);
+            this.maximGroupBoxProximity.PerformLayout();
+            ((System.ComponentModel.ISupportInitialize)(this.numProxThreshold)).EndInit();
+            this.groupBoxOpticalMeasurements.ResumeLayout(false);
+            this.groupBoxOpticalMeasurements.PerformLayout();
+            ((System.ComponentModel.ISupportInitialize)(this.chartLED)).EndInit();
+            this.maximGroupBoxLEDTimingSlots.ResumeLayout(false);
+            this.maximGroupBoxLEDTimingSlots.PerformLayout();
+            this.maximGroupBoxSettings.ResumeLayout(false);
+            this.maximGroupBoxSettings.PerformLayout();
+            this.maximGroupBoxLEDcurrents.ResumeLayout(false);
+            this.maximGroupBoxLEDcurrents.PerformLayout();
+            this.maximGroupBoxRegs.ResumeLayout(false);
+            this.maximGroupBoxRegs.PerformLayout();
+            this.tableLayoutPanel1.ResumeLayout(false);
+            this.panel1.ResumeLayout(false);
+            this.panel1.PerformLayout();
+            this.grpAlgorithm.ResumeLayout(false);
+            this.grpAlgorithm.PerformLayout();
+            this.ResumeLayout(false);
+            this.PerformLayout();
+
+        }
+
+        #endregion
+
+        private MaximStyle.MaximGroupBox groupBoxAccelMeasurements;
+        private System.Windows.Forms.DataVisualization.Charting.Chart chartAccel;
+        private MaximStyle.MaximGroupBox maximGroupBoxProximity;
+        private System.Windows.Forms.Label labelnumProxThreshold;
+        private System.Windows.Forms.NumericUpDown numProxThreshold;
+        private System.Windows.Forms.Label labelcboPilotPA;
+        private System.Windows.Forms.Label label21;
+        private System.Windows.Forms.Label lblAvgPilotPALEDcurrent;
+        private MaximStyle.MaximComboBox cboPilotPA;
+        private MaximStyle.MaximGroupBox groupBoxOpticalMeasurements;
+        private System.Windows.Forms.DataVisualization.Charting.Chart chartLED;
+        private MaximStyle.MaximGroupBox maximGroupBoxLEDTimingSlots;
+        private MaximStyle.MaximComboBox cboLEDslot1;
+        private MaximStyle.MaximComboBox cboLEDslot2;
+        private System.Windows.Forms.Label labelcboLEDslot4;
+        private MaximStyle.MaximComboBox cboLEDslot3;
+        private System.Windows.Forms.Label labelcboLEDslot3;
+        private MaximStyle.MaximComboBox cboLEDslot4;
+        private System.Windows.Forms.Label labelcboLEDslot2;
+        private System.Windows.Forms.Label labelcboLEDslot1;
+        private MaximStyle.MaximGroupBox maximGroupBoxSettings;
+        private System.Windows.Forms.Label label28;
+        private System.Windows.Forms.Label label25;
+        private System.Windows.Forms.Label label26;
+        private System.Windows.Forms.Label label27;
+        private MaximStyle.MaximComboBox cboADCFSrangenA;
+        private System.Windows.Forms.Label label29;
+        private MaximStyle.MaximComboBox cboSampleAvg;
+        private System.Windows.Forms.Label label30;
+        private MaximStyle.MaximComboBox cboSampleRate;
+        private System.Windows.Forms.Label label31;
+        private MaximStyle.MaximComboBox cboPulseWidth;
+        private MaximStyle.MaximGroupBox maximGroupBoxLEDcurrents;
+        private MaximStyle.MaximComboBox cboIRLED;
+        private System.Windows.Forms.Label labelcboRedLED;
+        private System.Windows.Forms.Label labelcboGreenLED;
+        private System.Windows.Forms.Label label32;
+        private System.Windows.Forms.Label label33;
+        private System.Windows.Forms.Label label35;
+        private System.Windows.Forms.Label label34;
+        private System.Windows.Forms.Label labelcboIRLED;
+        private MaximStyle.MaximComboBox cboRedLED;
+        private MaximStyle.MaximComboBox cboGreenLED;
+        private System.Windows.Forms.Label lblAvgIRLEDcurrent;
+        private System.Windows.Forms.Label lblAvgGreenLEDcurrent;
+        private System.Windows.Forms.Label lblAvgRedLEDcurrent;
+        private System.Windows.Forms.Label label36;
+        private System.Windows.Forms.Label label37;
+        private MaximStyle.MaximGroupBox maximGroupBoxRegs;
+        private System.Windows.Forms.TextBox textBoxRegValue;
+        private MaximStyle.MaximButton btnRegWrite;
+        private MaximStyle.MaximButton btnRegRead;
+        private MaximStyle.MaximComboBox comboBoxRegAddr;
+        private MaximStyle.MaximButton btnDefaults;
+        private MaximStyle.MaximButton btnMonitoring;
+        private System.Windows.Forms.Label label38;
+        private MaximStyle.MaximComboBox cboMode;
+        private System.Windows.Forms.Button button1;
+        private System.Windows.Forms.Label lblPulseInterval;
+        private System.Windows.Forms.Label label7;
+        private System.Windows.Forms.Label label45;
+        private System.Windows.Forms.TableLayoutPanel tableLayoutPanel1;
+        private System.Windows.Forms.Panel panel1;
+        private MaximStyle.MaximGroupBox grpAlgorithm;
+        private System.Windows.Forms.Label lblSpO2;
+        private System.Windows.Forms.Label lblHeartRate;
+        private System.Windows.Forms.Label label8;
+        private System.Windows.Forms.Label label6;
+        private System.Windows.Forms.Label label2;
+        private System.Windows.Forms.Label label1;
+
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HspGuiSourceV301/HSPGui/CustomControls/OpticalView.cs	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,1366 @@
+/*******************************************************************************
+* Copyright (C) 2016 Maxim Integrated Products, Inc., All rights Reserved.
+* 
+* This software is protected by copyright laws of the United States and
+* of foreign countries. This material may also be protected by patent laws
+* and technology transfer regulations of the United States and of foreign
+* countries. This software is furnished under a license agreement and/or a
+* nondisclosure agreement and may only be used or reproduced in accordance
+* with the terms of those agreements. Dissemination of this information to
+* any party or parties not specified in the license agreement and/or
+* nondisclosure agreement is expressly prohibited.
+*
+* The above copyright notice and this permission notice shall be included
+* in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+* OTHER DEALINGS IN THE SOFTWARE.
+*
+* Except as contained in this notice, the name of Maxim Integrated
+* Products, Inc. shall not be used except as stated in the Maxim Integrated
+* Products, Inc. Branding Policy.
+*
+* The mere transfer of this software does not imply any licenses
+* of trade secrets, proprietary technology, copyrights, patents,
+* trademarks, maskwork rights, or any other form of intellectual
+* property whatsoever. Maxim Integrated Products, Inc. retains all
+* ownership rights.
+*******************************************************************************
+*/
+
+#define USE_MEDICALCHARTHELPER
+//#define CES_DEMO
+
+using System;
+using System.Collections.Generic;
+using System.Collections;
+using System.ComponentModel;
+using System.Drawing;
+using System.Data;
+using System.Linq;
+using System.Text;
+using System.Windows.Forms;
+using RPCSupport.Streaming;
+using Maxim.Charting;
+using System.Threading;
+using HealthSensorPlatform.View;
+
+using System.Windows.Forms.DataVisualization.Charting;
+
+// DEBUG
+using System.IO;
+
+namespace HealthSensorPlatform.CustomControls
+{
+    public partial class OpticalView : UserControl, IDeviceView, IOpticalAlgorithmView
+    {
+        /* Constant Fields */
+        static string StartString = "Start Monitor";
+        static string StopString = "Stop Monitor";
+
+        const int ChartTime = 4; // 4 seconds
+
+        /* Fields */
+        private bool connected = false;
+        private bool streaming = false;
+
+        private RPCSupport.RPCClient rpcClient;
+        //private MedicalChartHelper medicalChartLED;
+        //private MedicalChartHelper medicalChartAccel;
+        private AutoScaleCalculator fifo1Calc;
+        private AutoScaleCalculator fifo2Calc;
+        private AutoScaleCalculator fifo3Calc;
+
+        eStreamMode streamMode;
+        byte fifo_waterlevel_mark = 0x0f;
+        byte sample_avg;
+        byte sample_rate;
+        byte pulse_width;
+        byte red_led_current;
+        byte ir_led_current;
+        byte green_led_current;
+        byte slot_1;
+        byte slot_2;
+        byte slot_3;
+        byte slot_4;
+
+        // Heart Rate Sensor
+        int points; // Number of x-axis points for a plot
+        int sampleRate; // Human readable sample rate
+        int sampleAverage; // Human readable number of average points
+        // LIS2HD
+        int sampleRateAccel; 
+        int pointsAccel;
+
+        EventHandler<PartialArrayIntAvailableEventArgs> appendChart; // Allows event to be unregistered
+
+        Dictionary<string, MedianFilter> intervalDict = new Dictionary<string, MedianFilter>();
+        Dictionary<string, AutoScaleCalculator> chartScaleDict = new Dictionary<string, AutoScaleCalculator>();
+
+        List<Control> streamingControls = new List<Control>();
+
+#if CES_DEMO
+        // Algorithm Data
+        Queue red;
+        Queue ir;
+        Queue led;
+        // struct to run algorithms
+        AlgorithmMobileBU.AlgorithmConfiguration config;
+        AlgorithmMobileBU.AlgorithmOutput output;
+        int algoCounter = 0;
+#endif
+
+        // DEBUG
+        //StreamWriter file = new StreamWriter("hsp_output_data.csv");
+
+        /* Constructors */
+        public OpticalView()
+        {
+            InitializeComponent();
+
+            OpticalSensorInitControls();
+
+            cboSampleRate.SelectedIndexChanged += new EventHandler(cboSRPWLed_SelectedIndexChanged);
+            cboPulseWidth.SelectedIndexChanged += new EventHandler(cboSRPWLed_SelectedIndexChanged);
+            cboRedLED.SelectedIndexChanged += new EventHandler(cboSRPWLed_SelectedIndexChanged);
+            cboIRLED.SelectedIndexChanged += new EventHandler(cboSRPWLed_SelectedIndexChanged);
+            cboGreenLED.SelectedIndexChanged += new EventHandler(cboSRPWLed_SelectedIndexChanged);
+
+            cboSampleRate.SelectedIndexChanged += new EventHandler(cboSampleRate_SelectedIndexChanged);
+            cboSampleAvg.SelectedIndexChanged += new EventHandler(cboSampleRate_SelectedIndexChanged);
+
+            streamingControls.AddRange(new Control[] { panel1, maximGroupBoxSettings, maximGroupBoxLEDcurrents, maximGroupBoxLEDTimingSlots, btnDefaults });
+#if CES_DEMO
+            // Algorithm 
+            red = new Queue();
+            ir = new Queue();
+            led = new Queue();
+
+            config = new AlgorithmMobileBU.AlgorithmConfiguration();
+            output = new AlgorithmMobileBU.AlgorithmOutput();
+
+            config.snrNoFingerThreshold = -9;
+            config.acLowPerfusionThreshold = 950;
+            config.isAGC = 0;
+
+            //updateAlgorithm();           
+            lblHeartRate.Visible = true;
+            lblHeartRateText.Visible = true;
+#endif
+        }
+
+        /* Delegates */
+        //public delegate void StreamingStartStopEventHandler(StreamingStartStopEventArgs e);
+
+        /* Events */
+        //public event StreamingStartStopEventHandler StreamingStartStop;
+        public event EventHandler<StreamingStartStopEventArgs> StreamingStartStop;
+
+        /* Enums */
+        public enum eStreamMode
+        {
+            eHR,
+            eSPO2,
+            eMulti
+        }
+
+        /* Properties */
+        public RPCSupport.RPCClient RPCClient
+        {
+            set
+            {
+                rpcClient = value;
+                appendChart = new EventHandler<PartialArrayIntAvailableEventArgs>(On_AppendChart);
+                rpcClient.streaming.PartialArrayIntAvailable += appendChart;
+            }
+        }
+
+        public bool Connected
+        {
+            get
+            {
+                return connected;
+            }
+            set
+            {
+                connected = value;
+                if (connected == false)
+                    if (btnMonitoring.Text == StopString)
+                        streamingStartStop();
+            }
+        }
+
+        public int AccelSampleRate
+        {
+            get
+            {
+                return sampleRateAccel;
+            }
+        }
+
+        public int OpticalSampleRate
+        {
+            get
+            {
+                return sampleRate / sampleAverage;
+            }
+        }
+        
+        public eStreamMode ModeConfiguration
+        {
+            get
+            {
+                return streamMode;
+            }
+        }
+
+        /* Methods */
+
+        // Clean up streaming 
+        public void Close()
+        {
+            rpcClient.streaming.PartialArrayIntAvailable -= appendChart; // Stop event from firing
+            // Disable streaming if enabled
+            if (btnMonitoring.Text == StopString)
+                streamingStartStop();
+        }
+
+        public void DisplayAlgorithmResult(double heartRateBPM, bool heartRateBPMValid, double heartRateBPMSignalStrength, 
+            double spO2Percent, bool spO2PercentValid, double spO2PercentSignalStrength)
+        {
+            // 100Hz only - TODO
+            if (OpticalSampleRate != 100)
+                return;
+
+            if (heartRateBPMValid)
+            {
+                lblHeartRate.ForeColor = SystemColors.ControlText;
+                lblHeartRate.Text = string.Format("{0}", heartRateBPM * (sampleRate / 100.0)); // 100.0 for default sample rate
+            }
+            else
+            {
+                lblHeartRate.ForeColor = Color.Gray;
+            }
+
+            if (spO2PercentValid)
+            {
+                lblSpO2.ForeColor = SystemColors.ControlText;
+                lblSpO2.Text = string.Format("{0:0.0}", spO2Percent);
+            }
+            else
+            {
+                lblSpO2.ForeColor = Color.Gray;
+            }
+        }
+
+        public void DisplayAlgorithmReset()
+        {
+            lblHeartRate.Text = "----";
+            lblHeartRate.ForeColor = Color.Gray;
+
+            lblSpO2.Text = "----";
+            lblSpO2.ForeColor = Color.Gray;
+        }
+
+        System.Windows.Forms.Timer timer = new System.Windows.Forms.Timer();
+        void InitGraphs()
+        {
+            /*
+            medicalChartLED = new MedicalChartHelper(chartLED,
+                "ChartArea1Red", "SeriesRed", "Red ADC Code",
+                "ChartArea2IR", "SeriesIR", "IR ADC Code",
+                "ChartArea3Green", "SeriesGreen", "Green ADC Code",
+                MedicalChartHelper.DataFormats.FormatUnsigned);
+            medicalChartLED._plotPoints = 200;
+            medicalChartAccel = new MedicalChartHelper(chartAccel,
+                "ChartArea4AccelX", "SeriesAccelX", "Accelerometer X",
+                "ChartArea5AccelY", "SeriesAccelY", "Accelerometer Y",
+                "ChartArea6AccelZ", "SeriesAccelZ", "Accelerometer Z",
+                MedicalChartHelper.DataFormats.Format16bit2sComplement);
+            */
+
+            MedianFilter fifo1 = new MedianFilter(10);
+            MedianFilter fifo2 = new MedianFilter(10);
+            MedianFilter fifo3 = new MedianFilter(10);
+            MedianFilter accelx = new MedianFilter(10);
+            MedianFilter accely = new MedianFilter(10);
+            MedianFilter accelz = new MedianFilter(10);
+
+            intervalDict.Add("ChartArea1Red", fifo1);
+            intervalDict.Add("ChartArea2IR", fifo2);
+            intervalDict.Add("ChartArea3Green", fifo3);
+
+            intervalDict.Add("ChartArea4AccelX", accelx);
+            intervalDict.Add("ChartArea5AccelY", accely);
+            intervalDict.Add("ChartArea6AccelZ", accelz);
+
+            fifo1Calc = new AutoScaleCalculator(0, 90000);
+            fifo1Calc.Minimum = 0;
+            fifo1Calc.Maximum = Math.Pow(2, 18);
+            fifo1Calc.Intervals = 5;
+            fifo1Calc.MinimumRange = 200;
+            fifo1Calc.ScaleTrigger = 0.8;
+            fifo1Calc.RescaleTargetRange = 0.25;
+            chartScaleDict.Add("ChartArea1Red", fifo1Calc);
+
+            fifo2Calc = new AutoScaleCalculator(0, 90000);
+            fifo2Calc.Minimum = 0;
+            fifo2Calc.Maximum = Math.Pow(2, 18);
+            fifo2Calc.Intervals = 5;
+            fifo2Calc.MinimumRange = 200;
+            fifo2Calc.ScaleTrigger = 0.8;
+            fifo2Calc.RescaleTargetRange = 0.25;
+            chartScaleDict.Add("ChartArea2IR", fifo2Calc);
+
+            fifo3Calc = new AutoScaleCalculator(0, 90000);
+            fifo3Calc.Minimum = 0;
+            fifo3Calc.Maximum = Math.Pow(2, 18);
+            fifo3Calc.Intervals = 5;
+            fifo3Calc.MinimumRange = 200;
+            fifo3Calc.ScaleTrigger = 0.8;
+            fifo3Calc.RescaleTargetRange = 0.25;
+            chartScaleDict.Add("ChartArea3Green", fifo2Calc);
+
+            AutoScaleCalculator accelXCalc = new AutoScaleCalculator(-10000, 10000);
+            accelXCalc.Minimum = -32768;
+            accelXCalc.Maximum = 32767;
+            accelXCalc.Intervals = 5;
+            accelXCalc.MinimumRange = 500;
+            accelXCalc.ScaleTrigger = 0.8;
+            accelXCalc.RescaleTargetRange = 0.25;
+            chartScaleDict.Add("ChartArea4AccelX", accelXCalc);
+
+            AutoScaleCalculator accelYCalc = new AutoScaleCalculator(-10000, 10000);
+            accelYCalc.Minimum = -32768;
+            accelYCalc.Maximum = 32767;
+            accelYCalc.Intervals = 5;
+            accelYCalc.MinimumRange = 500;
+            accelYCalc.ScaleTrigger = 0.8;
+            accelYCalc.RescaleTargetRange = 0.25;
+            chartScaleDict.Add("ChartArea5AccelY", accelYCalc);
+
+            AutoScaleCalculator accelZCalc = new AutoScaleCalculator(-10000, 10000);
+            accelZCalc.Minimum = -32768;
+            accelZCalc.Maximum = 32767;
+            accelZCalc.Intervals = 5;
+            accelZCalc.MinimumRange = 500;
+            accelZCalc.ScaleTrigger = 0.8;
+            accelZCalc.RescaleTargetRange = 0.25;
+            chartScaleDict.Add("ChartArea6AccelZ", accelZCalc);
+
+            /*
+            Random rand = new Random();
+            int[] data1 = new int[10];
+            int[] data2 = new int[10];
+            int[] data3 = new int[10];
+            double[] data1_ = new double[10];
+            double[] data2_ = new double[10];
+            double[] data3_ = new double[10];
+            for (int i = 0; i < data1.Length; i++)
+            {
+                data1[i] = rand.Next(10);
+                data2[i] = rand.Next(10);
+                data3[i] = rand.Next(10);
+                data1_[i] = rand.NextDouble() * 10;
+                data2_[i] = rand.NextDouble() * 10;
+                data3_[i] = rand.NextDouble() * 10;
+            }
+            */
+
+            /*
+            int[] dummyData = new int[] { 0 };
+            medicalChartLED.AppendDataChartArea1(dummyData, 0, 0);
+            medicalChartLED.AppendDataChartArea2(dummyData, 0, 0);
+            medicalChartLED.AppendDataChartArea3(dummyData, 0, 0);
+            //medicalChartAccel._xCount1++;
+            //medicalChartAccel._xCount2++;
+            //medicalChartAccel._xCount3++;
+            medicalChartAccel.AppendDataChartArea1(dummyData, 0, 0);
+            medicalChartAccel.AppendDataChartArea2(dummyData, 0, 0);
+            medicalChartAccel.AppendDataChartArea3(dummyData, 0, 0);
+            */
+
+            setupGraphs();
+
+            chartLED.ChartAreas["ChartArea3Green"].Visible = false;
+            timer.Interval = 50;    
+            //timer.Tick += new EventHandler(timer_Tick);
+        }
+
+        void setupGraphs()
+        {
+            chartLED.SuspendLayout();
+            chartAccel.SuspendLayout();
+
+            /* Initialize Empty Chart Grid */
+            chartLED.Series["SeriesRed"].Points.Clear();
+            chartLED.Series["SeriesIR"].Points.Clear();
+            chartLED.Series["SeriesGreen"].Points.Clear();
+
+            chartAccel.Series["SeriesAccelX"].Points.Clear();
+            chartAccel.Series["SeriesAccelY"].Points.Clear();
+            chartAccel.Series["SeriesAccelZ"].Points.Clear();
+
+            // Clear labels
+            chartLED.ChartAreas["ChartArea1Red"].AxisX.CustomLabels.Clear();
+            chartLED.ChartAreas["ChartArea2IR"].AxisX.CustomLabels.Clear();
+            chartLED.ChartAreas["ChartArea3Green"].AxisX.CustomLabels.Clear();
+            chartAccel.ChartAreas["ChartArea4AccelX"].AxisX.CustomLabels.Clear();
+            chartAccel.ChartAreas["ChartArea5AccelY"].AxisX.CustomLabels.Clear();
+            chartAccel.ChartAreas["ChartArea6AccelZ"].AxisX.CustomLabels.Clear();
+
+            chartLED.Series["SeriesRed"].Points.Add(0);
+            chartLED.Series["SeriesIR"].Points.Add(0);
+            chartLED.Series["SeriesGreen"].Points.Add(0);
+
+            chartAccel.Series["SeriesAccelX"].Points.Add(0);
+            chartAccel.Series["SeriesAccelY"].Points.Add(0);
+            chartAccel.Series["SeriesAccelZ"].Points.Add(0);
+
+            // Initialize Plots for OS24
+            chartLED.ChartAreas["ChartArea1Red"].AxisX.Interval = points / ChartTime;
+            chartLED.ChartAreas["ChartArea2IR"].AxisX.Interval = points / ChartTime;
+            chartLED.ChartAreas["ChartArea3Green"].AxisX.Interval = points / ChartTime;
+            chartLED.ChartAreas["ChartArea1Red"].AxisX.Maximum = points;
+            chartLED.ChartAreas["ChartArea2IR"].AxisX.Maximum = points;
+            chartLED.ChartAreas["ChartArea3Green"].AxisX.Maximum = points;
+            chartLED.ChartAreas["ChartArea1Red"].AxisY.Maximum = 90000;
+            chartLED.ChartAreas["ChartArea1Red"].AxisY.Minimum = 0;
+            chartLED.ChartAreas["ChartArea2IR"].AxisY.Maximum = 90000;
+            chartLED.ChartAreas["ChartArea2IR"].AxisY.Minimum = 0;
+            chartLED.ChartAreas["ChartArea3Green"].AxisY.Maximum = 90000;
+            chartLED.ChartAreas["ChartArea3Green"].AxisY.Minimum = 0;
+
+            // Initialize Plots for LIS2HD
+            sampleRateAccel = sampleRate;
+            //pointsAccel = (sampleRateAccel / sampleAverage) * ChartTime;
+            pointsAccel = (sampleRateAccel) * ChartTime;
+            chartAccel.ChartAreas["ChartArea4AccelX"].AxisX.Interval = pointsAccel / ChartTime;
+            chartAccel.ChartAreas["ChartArea5AccelY"].AxisX.Interval = pointsAccel / ChartTime;
+            chartAccel.ChartAreas["ChartArea6AccelZ"].AxisX.Interval = pointsAccel / ChartTime;
+            chartAccel.ChartAreas["ChartArea4AccelX"].AxisX.Maximum = pointsAccel;
+            chartAccel.ChartAreas["ChartArea5AccelY"].AxisX.Maximum = pointsAccel;
+            chartAccel.ChartAreas["ChartArea6AccelZ"].AxisX.Maximum = pointsAccel;
+            chartAccel.ChartAreas["ChartArea4AccelX"].AxisY.Minimum = -10000;
+            chartAccel.ChartAreas["ChartArea5AccelY"].AxisY.Minimum = -10000;
+            chartAccel.ChartAreas["ChartArea6AccelZ"].AxisY.Minimum = -10000;
+            chartAccel.ChartAreas["ChartArea4AccelX"].AxisY.Maximum = 10000;
+            chartAccel.ChartAreas["ChartArea5AccelY"].AxisY.Maximum = 10000;
+            chartAccel.ChartAreas["ChartArea6AccelZ"].AxisY.Maximum = 10000;
+
+            // Set X-axis labels in seconds
+            for (int i = 0; i < ChartTime + 1; i++)
+            {
+                chartLED.ChartAreas["ChartArea1Red"].AxisX.CustomLabels.Add( (sampleRate / sampleAverage) * (2 * i - 1) / 2, (sampleRate / sampleAverage) * (2 * i + 1) / 2, i.ToString());
+                chartLED.ChartAreas["ChartArea2IR"].AxisX.CustomLabels.Add( (sampleRate / sampleAverage) * (2 * i - 1) / 2, (sampleRate / sampleAverage) * (2 * i + 1) / 2, i.ToString());
+                chartLED.ChartAreas["ChartArea3Green"].AxisX.CustomLabels.Add( (sampleRate / sampleAverage) * (2 * i - 1) / 2, (sampleRate / sampleAverage) * (2 * i + 1) / 2, i.ToString());
+
+                chartAccel.ChartAreas["ChartArea4AccelX"].AxisX.CustomLabels.Add(sampleRateAccel * (2 * i - 1) / 2, sampleRateAccel * (2 * i + 1) / 2, i.ToString());
+                chartAccel.ChartAreas["ChartArea5AccelY"].AxisX.CustomLabels.Add(sampleRateAccel * (2 * i - 1) / 2, sampleRateAccel * (2 * i + 1) / 2, i.ToString());
+                chartAccel.ChartAreas["ChartArea6AccelZ"].AxisX.CustomLabels.Add(sampleRateAccel * (2 * i - 1) / 2, sampleRateAccel * (2 * i + 1) / 2, i.ToString());
+            }
+
+            chartLED.ResumeLayout();
+            chartLED.Invalidate();
+            chartAccel.ResumeLayout();
+            chartAccel.Invalidate();
+        }
+
+        void timer_Tick(object sender, EventArgs e)
+        {
+            /*Single tmpData = dynamicData[0].Y;
+            for (int i = 0; i < dynamicData.Length - 1; i++)
+            {
+                dynamicData[i].Y = dynamicData[i + 1].Y;
+            }
+            dynamicData[dynamicData.Length - 1].Y = tmpData;*/
+
+            //PointF[] newData = GenerateDynamicData(100, 5);
+            //UpdateLedChart("SeriesRed", newData);
+            //UpdateLedChart("SeriesIR", newData);
+            //UpdateLedChart("SeriesGreen", newData);
+        }
+
+        /*private void UpdateLedChart(string seriesName, PointF[] data)
+        {
+            int count; 
+
+            chartLED.SuspendLayout();
+            //chartLED.Series[seriesName].Points.Clear();
+            foreach (PointF pt in data)
+            {
+                //chartLED.Series[seriesName].Points.AddXY(pt.X, pt.Y);
+                chartLED.Series[seriesName].Points.Add(pt.Y);
+            }
+
+            for (count = chartLED.Series[seriesName].Points.Count; 
+                count > points; 
+                count = chartLED.Series[seriesName].Points.Count)
+            {
+                chartLED.Series[seriesName].Points.RemoveAt(0);
+            } 
+            chartLED.ResumeLayout();
+            chartLED.Invalidate();
+        }*/
+
+        private void UpdateXYZChart(string seriesName, int[] data)
+        {
+            int datapoint;
+            int count;
+
+            chartAccel.SuspendLayout();
+            //chartLED.Series[seriesName].Points.Clear();
+            foreach (int val in data)
+            {
+                //chartLED.Series[seriesName].Points.AddXY(pt.X, pt.Y);
+                datapoint = val;
+                // Two's complement conversion
+                if (val > 0x8000)
+                {
+                    datapoint = datapoint - 0x10000;
+                }
+                    chartAccel.Series[seriesName].Points.Add(datapoint);
+            }
+
+            for (count = chartAccel.Series[seriesName].Points.Count;
+                count > pointsAccel;
+                count = chartAccel.Series[seriesName].Points.Count)
+            {
+                chartAccel.Series[seriesName].Points.RemoveAt(0);
+            }
+            //chartAccel.ResetAutoValues();
+            chartAccel.ResumeLayout();
+            chartAccel.Invalidate();
+        }
+
+        private void UpdateLedChart(string seriesName, int[] data)
+        {
+            int[] dataPoints = new int[points];
+            int j = 0;
+            int count;
+
+            chartLED.SuspendLayout();
+            //chartLED.Series[seriesName].Points.Clear();
+
+            // Update Chart with new data
+            if (data.Length > points)
+                j = data.Length - points;
+
+            for (; j < data.Length; j++ )
+            {
+                chartLED.Series[seriesName].Points.Add(data[j]);
+#if CES_DEMO
+                if (seriesName.CompareTo("SeriesRed") == 0)
+                    red.Enqueue(data[j]);
+                else if (seriesName.CompareTo("SeriesIR") == 0)
+                    ir.Enqueue(data[j]);
+                else if (seriesName.CompareTo("SeriesGreen") == 0)
+                    led.Enqueue(data[j]);
+#endif
+            }
+
+            for (count = chartLED.Series[seriesName].Points.Count; 
+                count > points; 
+                count = chartLED.Series[seriesName].Points.Count)
+            {
+                chartLED.Series[seriesName].Points.RemoveAt(0);
+            }
+        }
+
+        private void UpdateLedChartScale(string chartName, string seriesName)
+        {
+            int min = Int32.MaxValue, max = 0;
+            int i, j;
+            int[] data = new int[points];
+            int graphCount;
+            //int maxRound, minRound;
+
+            graphCount = chartLED.Series[seriesName].Points.Count;
+
+            for (j = 0; j < graphCount; j++ )
+            {
+                data[j] = (int)chartLED.Series[seriesName].Points[j].YValues[0];
+            }
+
+            //if (data.Length < sampleRate)
+            //    return; // not enough data to draw graph
+            /*else*/
+            if (graphCount < (sampleRate / sampleAverage) * 2) // look back 2 seconds
+            {
+                i = 0;
+            }
+            else // look back 2 seconds
+            {
+                i = graphCount - (sampleRate / sampleAverage) * 2;
+            }
+
+            min = data[i];
+            max = data[i];
+            for (; i < graphCount; i++ )
+            {
+                if (data[i] < min && data[i] != 0)
+                    min = data[i];
+                else if (data[i] > max)
+                    max = data[i];
+            }
+
+            /*
+            MedianFilter filter;
+            intervalDict.TryGetValue(chartName, out filter);
+
+            var minMax = chartInterval(min, max, chartLED.ChartAreas[chartName].AxisY.Minimum, chartLED.ChartAreas[chartName].AxisY.Maximum, filter);
+            minRound = minMax.Item1;
+            maxRound = minMax.Item2;
+
+
+
+            // For no finger on sensor
+            if (max < 500)
+                max = 500;
+            */
+
+            AutoScaleCalculator chartScale;
+            chartScaleDict.TryGetValue(chartName, out chartScale);
+
+            var minMax = chartScale.Interval(min, max);
+
+            // Round to nearest 100 with averaging
+            //chartLED.ChartAreas[chartName].AxisY.Maximum = (chartLED.ChartAreas[chartName].AxisY.Maximum + (max / 100 + 1) * 100)/2;
+            //chartLED.ChartAreas[chartName].AxisY.Maximum = (((int)chartLED.ChartAreas[chartName].AxisY.Maximum + max)/200 + 1) * 100;
+            //chartLED.ChartAreas[chartName].AxisY.Minimum = (chartLED.ChartAreas[chartName].AxisY.Minimum + (min / 100 - 1) * 100)/2;
+            //chartLED.ChartAreas[chartName].AxisY.Minimum = (((int)chartLED.ChartAreas[chartName].AxisY.Minimum + min)/200 - 1) * 100;
+            chartLED.ChartAreas[chartName].AxisY.Minimum = minMax.Item1;
+            chartLED.ChartAreas[chartName].AxisY.Maximum = minMax.Item2;
+
+            chartLED.ResumeLayout();
+            chartLED.Invalidate();
+        }
+
+        private void UpdateXYZChartScale(string chartName, string seriesName)
+        {
+            int min = Int32.MaxValue, max = Int32.MinValue;
+            int i, j;
+            int maxRound, minRound;
+            int graphCount;
+
+            int[] data = new int[pointsAccel];
+
+            graphCount = chartAccel.Series[seriesName].Points.Count;
+
+            // Save all points from plot to data[]
+            for (j = 0; j < graphCount; j++)
+            {
+                data[j] = (int)chartAccel.Series[seriesName].Points[j].YValues[0];
+            }
+
+            if (graphCount < (sampleRateAccel / sampleAverage) * 2) // look back 3 seconds
+                i = 0;
+            else
+                i = graphCount - (sampleRateAccel / sampleAverage) * 2;
+
+            // Find min/max
+            min = data[i];
+            max = data[i];
+            for (; i < graphCount; i++)
+            {
+                if (data[i] < min)
+                    min = data[i];
+                else if (data[i] > max)
+                    max = data[i];
+            }
+
+            /*
+            // Sane defaults
+            if (min == max)
+            {
+                min = 0;
+                max = 100;
+            }
+
+            MedianFilter filter;
+            intervalDict.TryGetValue(chartName, out filter);
+
+            var minMax = chartInterval(min, max, chartAccel.ChartAreas[chartName].AxisY.Minimum, chartAccel.ChartAreas[chartName].AxisY.Maximum, filter);
+            minRound = minMax.Item1;
+            maxRound = minMax.Item2;
+
+            if (maxRound > 32768)
+                maxRound = 33000;
+
+            if (minRound < -32768)
+                minRound = -33000;
+            */
+
+            AutoScaleCalculator chartScale;
+            chartScaleDict.TryGetValue(chartName, out chartScale);
+
+            var minMax = chartScale.Interval(min, max);
+            minRound = (int)minMax.Item1;
+            maxRound = (int)minMax.Item2;
+
+            // Set the Min and Max for Y Axis
+            //chartAccel.ChartAreas[chartName].AxisY.Maximum = (((int)chartAccel.ChartAreas[chartName].AxisY.Maximum + max) / 200 + 1) * 100;
+            //chartAccel.ChartAreas[chartName].AxisY.Minimum = (((int)chartAccel.ChartAreas[chartName].AxisY.Minimum + min) / 200 - 1) * 100;
+            chartAccel.ChartAreas[chartName].AxisY.Maximum = maxRound;
+            chartAccel.ChartAreas[chartName].AxisY.Minimum = minRound;
+            //System.Diagnostics.Debug.Print(chartName + " count: " + graphCount + " minRound: " + minRound + " maxRound: " + maxRound + " min: " + min + " max: " + max);
+
+            chartAccel.ResumeLayout();
+            chartAccel.Invalidate();
+        }
+
+        /*private PointF[] dynamicData;
+        private static PointF[] GenerateDynamicData(double amplitude, int sampleCount)
+        {
+            Random rnd = new Random();
+            PointF[] points = new PointF[sampleCount];
+            points[0] = new PointF(0, (Single)(amplitude * rnd.NextDouble()));
+            for (int i = 1; i < sampleCount; i++)
+            {
+                points[i] = new PointF(i, (Single)(points[i - 1].Y + (amplitude / 10 * (0.5 - rnd.NextDouble()))));
+                if (points[i].Y > amplitude) points[i].Y = (Single)amplitude;
+            }
+            return (points);
+        }*/
+
+        /// <summary>
+        /// Calculate rounded minimum and maximum for chart data
+        /// </summary>
+        /// <param name="minimum"></param>
+        /// <param name="maximum"></param>
+        /// <param name="chartInterval"></param>
+        /// <returns></returns>
+        private static Tuple<int, int> chartInterval(int minimum, int maximum, double chartMinimum, double chartMaximum, MedianFilter chartInterval)
+        {
+            int delta, interval, roundInterval, roundCenter;
+            double mag, magPower, magMostSigDigit;
+            int center;
+
+            // 10% and 90% range
+            int chartRange = (int)(chartMaximum - chartMinimum);
+            int dataRange = maximum - minimum;
+            if (minimum < chartMinimum + chartRange * 0.10 || maximum > chartMaximum - chartRange * 0.10
+                || dataRange > 0.9 * chartRange || dataRange < 0.1 * chartRange)
+            {
+
+                delta = (int)((maximum - minimum));
+
+                interval = delta * (100 / 35) / 5; // delta * 4 = 25% * 4 = 100 (full chart scale)
+                center = minimum + (maximum - minimum) / 2;
+
+                mag = Math.Floor(Math.Log10(interval));
+                magPower = Math.Pow(10, mag);
+
+                magMostSigDigit = (int)(interval / (double)magPower + 0.5);
+
+                if (magMostSigDigit >= 5.0)
+                    magMostSigDigit = 10;
+                else if (magMostSigDigit >= 2.0)
+                    magMostSigDigit = 5;
+                else if (magMostSigDigit >= 1.0)
+                    magMostSigDigit = 2;
+
+                roundInterval = (int)(magMostSigDigit * magPower);
+                if (roundInterval < 100)
+                {
+                    roundInterval = 100;
+                }
+                roundInterval = chartInterval.Filter(roundInterval);
+
+                roundCenter = ((center + 100) / 200) * 200;
+
+                int roundMin = (int)(roundCenter - roundInterval * 2.5);
+                int roundMax = (int)(roundCenter + roundInterval * 2.5);
+                if (roundInterval > 104858)
+                {
+                    roundMin = 0;
+                    roundMax = 550000;
+                }
+                /*else
+                {
+                    if (roundMin < 0) // || roundMax > 524288)
+                    {
+                        roundMin = 0;
+                        roundMax = roundInterval * 5;
+                    }
+                }*/
+
+                return new Tuple<int, int>(roundMin, roundMax);
+            }
+
+            return new Tuple<int, int>((int)chartMinimum, (int)chartMaximum);
+        }
+
+        void OpticalSensorInitControls()
+        {
+            cboMode.Items.AddRange(new string[] { "HR","SPO2","LED" });
+            cboSampleRate.Items.AddRange(new string[] { "50", "100", "200", "400" });
+            cboSampleAvg.Items.AddRange(new string[] { "1", "2", "4", "8", "16", "32" });
+            cboPulseWidth.Items.AddRange(new string[] { "69", "118", "215", "411" });
+            cboADCFSrangenA.Items.AddRange(new string[] { "2048", "4096", "8192", "16384" });
+            double slopeInt = 25.0 / 128.0;
+            for (int index = 0; index < 256; index++)
+            {
+                string str = index < 0x0F ? (0.2 * index).ToString() : (slopeInt * index + slopeInt).ToString();
+                cboIRLED.Items.Add(str);
+                cboRedLED.Items.Add(str);
+                cboGreenLED.Items.Add(str);
+                cboPilotPA.Items.Add(str);
+            }
+
+            OpticalSensorDefaults();
+            calculateAvgCurrent();
+
+            InitGraphs();            
+        }
+
+        public void OpticalSensorDefaults()
+        {
+            cboMode.SelectedItem = "SPO2";
+            cboRedLED.SelectedItem = "10.15625";
+            cboIRLED.SelectedItem = "10.15625";
+            cboGreenLED.SelectedItem = "10.15625";
+            cboSampleRate.SelectedItem = "100";
+            cboPulseWidth.SelectedItem = "411";
+            cboSampleAvg.SelectedItem = "1";
+            cboADCFSrangenA.SelectedItem = "8192";
+
+            cboLEDslot1.SelectedIndex = 1;
+            cboLEDslot2.SelectedIndex = 2;
+            cboLEDslot3.SelectedIndex = 3;
+            cboLEDslot4.SelectedIndex = 0;
+
+            // Used to generate the initial chart grid
+            sample_rate = (byte)cboSampleRate.SelectedIndex;
+            sample_avg = (byte)cboSampleAvg.SelectedIndex;
+
+            sampleRate = (1 << sample_rate) * 50; // (1 << sample_rate) = 2^sample_rate
+            sampleAverage = (1 << sample_avg); // 2^sample_avg
+            points = (sampleRate / sampleAverage) * ChartTime; // 4 seconds, 2^sample_av
+
+            sampleRateAccel = sampleRate; 
+            pointsAccel = (sampleRateAccel / sampleAverage) * ChartTime;
+        }
+
+        private void cbo_IndexChanged(object sender, EventArgs e)
+        {
+            if ((MaximStyle.MaximComboBox)sender == cboMode)
+            {
+                bool HRmode = (cboMode.Text == "HR");
+                bool SPO2mode = (cboMode.Text == "SPO2");
+                bool multiLEDmode = (cboMode.Text == "LED");
+                //labelcboRedLED.Enabled = myMAX30101.valid_Red;
+                //cboRedLED.Enabled = myMAX30101.valid_Red;
+                bool valid_IR = (multiLEDmode || SPO2mode);
+                bool valid_Green = multiLEDmode;
+                bool valid_Red = multiLEDmode;
+                labelcboIRLED.Enabled = valid_IR;
+                cboIRLED.Enabled = valid_IR;
+                labelcboGreenLED.Enabled = valid_Green;
+                cboGreenLED.Enabled = valid_Green;
+                cboLEDslot1.Enabled = multiLEDmode;
+                cboLEDslot2.Enabled = multiLEDmode;
+                cboLEDslot3.Enabled = multiLEDmode;
+                cboLEDslot4.Enabled = multiLEDmode;
+                {
+                    // Hide unused LED channel graphs
+                    // | mode | ChartArea1Red | ChartArea2IR | ChartArea3Green |
+                    // | LED  |   visible     |   visible    |   visible       | MAX30101 only
+                    // | SPO2 |   visible     |   visible    |   hidden        |
+                    // | HR   |   visible     |   hidden     |   hidden        | MAX30101: Red only. MAX30100: IR only.
+                    valid_Red = true;
+                    valid_IR = multiLEDmode || SPO2mode;
+                    valid_Green = multiLEDmode;
+                    
+                    chartLED.ChartAreas["ChartArea1Red"].Visible = valid_Red;
+                    chartLED.ChartAreas["ChartArea2IR"].Visible = valid_IR;
+                    chartLED.ChartAreas["ChartArea3Green"].Visible = valid_Green;                   
+                }
+            }
+        }
+
+        public void On_AppendChart(object sender, PartialArrayIntAvailableEventArgs e)
+        {
+            if (streaming)
+            {
+                if ((e.reportID & 0xF0) == PartialArrayIntAvailableEventArgs.PACKET_MAX30101)
+                {
+                    if (e.array1.Length != 0)
+                    {
+                        UpdateLedChart("SeriesRed", e.array1);
+                        UpdateLedChartScale("ChartArea1Red", "SeriesRed");
+                    }
+                    if (e.array2.Length != 0)
+                    {
+                        UpdateLedChart("SeriesIR", e.array2);
+                        UpdateLedChartScale("ChartArea2IR", "SeriesIR");
+                    }
+                    if (e.array3.Length != 0)
+                    {
+                        UpdateLedChart("SeriesGreen", e.array3);
+                        UpdateLedChartScale("ChartArea3Green", "SeriesGreen");
+                    }
+                }
+                if (e.reportID == PartialArrayIntAvailableEventArgs.PACKET_LIS2DH)
+                {
+                    if (e.array1.Length != 0)
+                    {
+                        UpdateXYZChart("SeriesAccelX", e.array1);
+                        UpdateXYZChartScale("ChartArea4AccelX", "SeriesAccelX");
+                    }
+                    if (e.array2.Length != 0)
+                    {
+                        UpdateXYZChart("SeriesAccelY", e.array2);
+                        UpdateXYZChartScale("ChartArea5AccelY", "SeriesAccelY");
+                    }
+                    if (e.array3.Length != 0)
+                    {
+                        UpdateXYZChart("SeriesAccelZ", e.array3);
+                        UpdateXYZChartScale("ChartArea6AccelZ", "SeriesAccelZ");
+                    }
+
+#if CES_DEMO
+                if (sampleRate == 100)
+                    updateAlgorithm();
+#endif
+                }
+            }
+        }
+
+#if CES_DEMO
+        private void updateAlgorithm()
+        {
+            int rtn = 0;
+
+            while (red.Count != 0 ) //&& ir.Couunt != 0 && led.Count != 0)
+            {
+                StringBuilder outputData = new StringBuilder();
+                int redVal = (Int32)red.Dequeue(); // Always dequeue red, checked in while loop
+                int irVal = ir.Count > 0 ? (Int32)ir.Dequeue() : 1;
+                int ledVal = led.Count > 0 ? (Int32)led.Dequeue() : 1;
+
+                switch (streamMode)
+                {
+                    case eStreamMode.eSPO2:
+                        rtn = AlgorithmMobileBU.runAlgorithm_win(irVal, redVal, 1, // ir, r, led
+                                    25, sampleRate, ++algoCounter, 
+                                    0, 0, 0, ref config, ref output);
+                        break;
+                    case eStreamMode.eHR: // TODO: Not functioning
+                        rtn = AlgorithmMobileBU.runAlgorithm_win(1, redVal, 1, // ir, r, led
+                                    25, sampleRate, ++algoCounter, 
+                                    0, 0, 0, ref config, ref output);
+                        break;
+                    case eStreamMode.eMulti:
+                        rtn = AlgorithmMobileBU.runAlgorithm_win(irVal, redVal, ledVal, // ir, r, led
+                                    25, sampleRate, ++algoCounter, 
+                                    0, 0, 0, ref config, ref output);
+                        break;
+                }
+
+                //outputData.Append(DateTime.Now.ToString("HH:mm:ss.ffff"));
+                //outputData.Append(",");
+                //outputData.Append(irVal);
+                //outputData.Append(",");
+                //outputData.Append(redVal);
+                //outputData.Append(",");
+                //outputData.Append(0); // Can be green
+                //outputData.Append(",");
+                //outputData.Append(0); // Ax
+                //outputData.Append(",");
+                //outputData.Append(0); // Ay
+                //outputData.Append(",");
+                //outputData.Append(0); // Az
+                //outputData.Append(",");
+
+                //file.WriteLine(outputData.ToString()); // Raw data output
+            }
+
+            lblHeartRate.Text = Math.Round(output.hr).ToString(); //redIn.ToString();
+            lblRespRate.Text = output.resp_rate.ToString("N");
+            lblSpO2.Text = output.R == 0 ? "0" : (-45.060 * output.R * output.R + 30.354 * output.R + 94.845).ToString("N");//output.spo2.ToString("N");
+            lblHeartRateVariation.Text = output.hrv.ToString("N");
+            lblPulseInterval.Text = output.pulse_interval.ToString("N");
+        }
+
+#endif
+
+        private void OpticalView_Load(object sender, EventArgs e)
+        {
+            //OpticalSensorInitControls();
+            //OpticalSensorDefaults();
+        }
+
+        private void streamingStartStop()
+        {
+            if (cboMode.Text == "HR") streamMode = eStreamMode.eHR;
+            if (cboMode.Text == "SPO2") streamMode = eStreamMode.eSPO2;
+            if (cboMode.Text == "LED") streamMode = eStreamMode.eMulti;
+
+            if (Connected && btnMonitoring.Text == StartString)
+            {
+                streaming = true;
+                sample_rate = (byte)cboSampleRate.SelectedIndex;
+                sample_avg = (byte)cboSampleAvg.SelectedIndex;
+                pulse_width = (byte)cboPulseWidth.SelectedIndex;
+                red_led_current = (byte)cboRedLED.SelectedIndex;
+                ir_led_current = (byte)cboIRLED.SelectedIndex;
+                green_led_current = (byte)cboGreenLED.SelectedIndex;
+                slot_1 = (byte)cboLEDslot1.SelectedIndex;
+                slot_2 = (byte)cboLEDslot2.SelectedIndex;
+                slot_3 = (byte)cboLEDslot3.SelectedIndex;
+                slot_4 = (byte)cboLEDslot4.SelectedIndex;
+
+                sampleRate = Int32.Parse((string)cboSampleRate.SelectedItem);
+                sampleAverage = Int32.Parse((string)cboSampleAvg.SelectedItem);
+                points = (sampleRate / sampleAverage ) * ChartTime;
+
+                foreach (Control c in streamingControls)
+                    c.Enabled = false;
+
+#if CES_DEMO
+                // For Algorithm
+                sampleRate = (1 << sample_rate) * 50; // (1 << sample_rate) = 2^sample_rate
+                sampleAverage = (1 << sample_avg); // 2^sample_avg
+                points = (sampleRate / sampleAverage) * ChartTime; // 4 seconds, 2^sample_av
+
+                sampleRateAccel = 10; // TODO, update with real value from Jerry
+                pointsAccel = (sampleRateAccel / sampleAverage) * ChartTime;
+
+                // Reset algorithm counter
+                algoCounter = 0;
+
+                if (sampleRate == 100)
+                {
+                    lblHeartRateText.Enabled = true;
+                    lblHeartRate.Enabled = true;
+                    lblSpO2.Enabled = true;
+                    lblSpO2Text.Enabled = true;
+                }
+                else
+                {
+                    lblHeartRateText.Enabled = false;
+                    lblHeartRate.Enabled = false;
+                    lblSpO2.Enabled = false;
+                    lblSpO2Text.Enabled = false;
+                }
+#endif
+
+                // Setup grid
+                setupGraphs();
+
+                switch (streamMode)
+                {
+                    case eStreamMode.eHR:
+                        rpcClient.MAX30101.HRmode_init(fifo_waterlevel_mark, sample_avg, sample_rate, pulse_width,
+                                                                         red_led_current, (byte)(sample_rate + 4));
+                        break;
+                    case eStreamMode.eMulti:
+                        rpcClient.MAX30101.Multimode_init(fifo_waterlevel_mark, sample_avg, sample_rate, pulse_width,
+                                             red_led_current, ir_led_current, green_led_current,
+                                             slot_1, slot_2, slot_3, slot_4, (byte)(sample_rate + 4));
+                        break;
+                    case eStreamMode.eSPO2:
+                        rpcClient.MAX30101.SpO2mode_init(fifo_waterlevel_mark, sample_avg, sample_rate, pulse_width,
+                                                                         red_led_current, ir_led_current, (byte)(sample_rate + 4));
+                        break;
+                }
+
+                btnMonitoring.Text = StopString;
+
+                if (StreamingStartStop != null) 
+                    StreamingStartStop(this, new StreamingStartStopEventArgs() { state = true });
+
+            }
+            else if (btnMonitoring.Text == StopString)
+            {
+                streaming = false;
+                switch (streamMode)
+                {
+                    case eStreamMode.eHR:
+                        rpcClient.MAX30101.HRmode_stop(connected);
+                        break;
+                    case eStreamMode.eMulti:
+                        rpcClient.MAX30101.Multimode_stop(connected);
+                        break;
+                    case eStreamMode.eSPO2:
+                        rpcClient.MAX30101.SpO2mode_stop(connected);
+                        break;
+                }
+                //rpcClient.MAX30101.StopStreaming();
+                btnMonitoring.Text = StartString;
+
+                foreach (Control c in streamingControls)
+                    c.Enabled = true;
+                
+                if (StreamingStartStop != null)
+                    StreamingStartStop(this, new StreamingStartStopEventArgs() { state = false });
+            }
+        }
+
+        private void btnMonitoring_Click(object sender, EventArgs e)
+        {
+            //if (Connected)
+            streamingStartStop();
+        }
+
+        private void button1_Click(object sender, EventArgs e)
+        {
+            timer.Start();
+        }
+
+        private void button1_Click_1(object sender, EventArgs e)
+        {
+            /* Debug*/
+            //int count = chartLED.Series["SeriesRed"].Points.Count;
+            //int count2 = chartAccel.Series["SeriesAccelX"].Points.Count;
+            UpdateXYZChartScale("ChartArea6AccelZ", "SeriesAccelZ");
+        }
+
+        private void btnDefaults_Click(object sender, EventArgs e)
+        {
+            OpticalSensorDefaults();
+        }
+
+        private void cboSRPWLed_SelectedIndexChanged(object sender, EventArgs e)
+        {
+            calculateAvgCurrent();
+        }
+
+        private void calculateAvgCurrent()
+        {
+            double ratio = double.Parse(cboPulseWidth.Text) * 1e-6 * double.Parse(cboSampleRate.Text);
+            string _noDataString = "---";
+            if (ratio <= 1)
+            {
+                lblAvgIRLEDcurrent.Text = String.Format("{0:0.00}", double.Parse(cboIRLED.Text) * ratio);
+                lblAvgRedLEDcurrent.Text = String.Format("{0:0.00}", double.Parse(cboRedLED.Text) * ratio);
+                // https://jira.maxim-ic.com/browse/OS24EVK-17 Green LED: Multi-LED Mode timeslice; FIFO Read Red, IR, Green
+                lblAvgGreenLEDcurrent.Text = String.Format("{0:0.00}", double.Parse(cboGreenLED.Text) * ratio);
+                // https://jira.maxim-ic.com/browse/OS24EVK-32 update lblAvgPilotPALEDcurrent from cboPilotPA similar to lblAvgGreenLEDcurrent
+                //lblAvgPilotPALEDcurrent.Text = String.Format("{0:0.00}", double.Parse(cboPilotPA.Text) * ratio);
+            }
+            else
+            {
+                lblAvgIRLEDcurrent.Text = _noDataString;
+                lblAvgRedLEDcurrent.Text = _noDataString;
+                // https://jira.maxim-ic.com/browse/OS24EVK-17 Green LED: Multi-LED Mode timeslice; FIFO Read Red, IR, Green
+                lblAvgGreenLEDcurrent.Text = _noDataString;
+                // https://jira.maxim-ic.com/browse/OS24EVK-32 update lblAvgPilotPALEDcurrent from cboPilotPA similar to lblAvgGreenLEDcurrent
+                lblAvgPilotPALEDcurrent.Text = _noDataString;
+            }
+        }
+
+        void cboSampleRate_SelectedIndexChanged(object sender, EventArgs e)
+        {
+            if ((string)cboSampleRate.SelectedItem == "100" && (string)cboSampleAvg.SelectedItem == "1")
+                grpAlgorithm.Enabled = true;
+            else
+                grpAlgorithm.Enabled = false;
+
+            sampleRate = Int32.Parse((string)cboSampleRate.SelectedItem);
+            sampleAverage = Int32.Parse((string)cboSampleAvg.SelectedItem);
+        }
+
+        public string SettingsString()
+        {
+            StringBuilder strBuilder = new StringBuilder();
+
+            strBuilder.Append("% ");
+            strBuilder.Append("Mode = ");
+            strBuilder.Append(cboMode.SelectedItem);
+            strBuilder.Append(Environment.NewLine);
+
+            strBuilder.Append("% ");
+            strBuilder.Append("Sample Rate (Hz) = ");
+            strBuilder.Append(cboSampleRate.SelectedItem);
+            strBuilder.Append(" Sample Average = ");
+            strBuilder.Append(cboSampleAvg.SelectedItem);
+            strBuilder.Append(" Pulse Width (us) = ");
+            strBuilder.Append(cboPulseWidth.SelectedItem);
+            strBuilder.Append(" ADC Full Scale Range (nA) = ");
+            strBuilder.Append(cboADCFSrangenA.SelectedItem);
+            strBuilder.Append(Environment.NewLine);
+
+            strBuilder.Append("% ");
+            strBuilder.Append(" LED Red (mA) = ");
+            strBuilder.Append(cboRedLED.SelectedItem);
+            strBuilder.Append(" LED IR (mA) = ");
+            strBuilder.Append(cboIRLED.SelectedItem);
+            strBuilder.Append(" LED Green (mA) = ");
+            strBuilder.Append(cboGreenLED.SelectedItem);
+            strBuilder.Append(Environment.NewLine);
+
+            strBuilder.Append("% ");
+            strBuilder.Append("LED Slot 1 = ");
+            strBuilder.Append(cboLEDslot1.SelectedIndex);
+            strBuilder.Append(" LED Slot 2 = ");
+            strBuilder.Append(cboLEDslot2.SelectedIndex);
+            strBuilder.Append(" LED Slot 3 = ");
+            strBuilder.Append(cboLEDslot3.SelectedIndex);
+            strBuilder.Append(" LED Slot 4 = ");
+            strBuilder.Append(cboLEDslot4.SelectedIndex);
+
+            return strBuilder.ToString();
+        }
+
+        public string AccelSettingString()
+        {
+            return "% Sample Rate (Hz) = " + AccelSampleRate;
+        }
+
+        public InitArgs.HRModeInitStart GetHRModeArgs()
+        {
+            InitArgs.HRModeInitStart args = new InitArgs.HRModeInitStart();
+
+            args.FifoWaterlevelMark = fifo_waterlevel_mark;
+            args.SampleRate = (byte)cboSampleRate.SelectedIndex;
+            args.SampleAverage = (byte)cboSampleAvg.SelectedIndex;
+            args.PulseWidth = (byte)cboPulseWidth.SelectedIndex;
+            args.RedLedCurrent = (byte)cboRedLED.SelectedIndex;
+
+            return args;
+        }
+
+        public InitArgs.SpO2HRModeInitStart GetSpO2HRModeArgs()
+        {
+            InitArgs.SpO2HRModeInitStart args = new InitArgs.SpO2HRModeInitStart();
+
+            args.FifoWaterlevelMark = fifo_waterlevel_mark;
+            args.SampleRate = (byte)cboSampleRate.SelectedIndex;
+            args.SampleAverage = (byte)cboSampleAvg.SelectedIndex;
+            args.PulseWidth = (byte)cboPulseWidth.SelectedIndex;
+            args.RedLedCurrent = (byte)cboRedLED.SelectedIndex;
+            args.IRLedCurrent = (byte)cboIRLED.SelectedIndex;
+
+            return args;
+        }
+
+        public InitArgs.MultiModeInitStart GetMultiModeArgs()
+        {
+            InitArgs.MultiModeInitStart args = new InitArgs.MultiModeInitStart();
+
+            args.FifoWaterlevelMark = fifo_waterlevel_mark;
+            args.SampleRate = (byte)cboSampleRate.SelectedIndex;
+            args.SampleAverage = (byte)cboSampleAvg.SelectedIndex;
+            args.PulseWidth = (byte)cboPulseWidth.SelectedIndex;
+            args.RedLedCurrent = (byte)cboRedLED.SelectedIndex;
+            args.IRLedCurrent = (byte)cboIRLED.SelectedIndex;
+            args.GreenLedCurrent = (byte)cboGreenLED.SelectedIndex;
+            args.Slot1 = (byte)cboLEDslot1.SelectedIndex;
+            args.Slot2 = (byte)cboLEDslot2.SelectedIndex;
+            args.Slot3 = (byte)cboLEDslot3.SelectedIndex;
+            args.Slot4 = (byte)cboLEDslot4.SelectedIndex;
+
+            return args;
+        }
+
+        public void SetHRModeArgs(InitArgs.HRModeInitStart args)
+        {
+            cboSampleRate.SelectedIndex = args.SampleRate; 
+            cboSampleAvg.SelectedIndex = args.SampleAverage;
+            cboPulseWidth.SelectedIndex = args.PulseWidth;
+            cboRedLED.SelectedIndex = args.RedLedCurrent;
+        }
+        
+        public void SetSpO2HRModeArgs(InitArgs.SpO2HRModeInitStart args)
+        {
+            cboSampleRate.SelectedIndex = args.SampleRate; 
+            cboSampleAvg.SelectedIndex = args.SampleAverage;
+            cboPulseWidth.SelectedIndex = args.PulseWidth;
+            cboRedLED.SelectedIndex = args.RedLedCurrent;
+            cboIRLED.SelectedIndex = args.IRLedCurrent;
+        }
+
+        public void SetMultiModeArgs(InitArgs.MultiModeInitStart args)
+        {
+            cboSampleRate.SelectedIndex = args.SampleRate;
+            cboSampleAvg.SelectedIndex = args.SampleAverage;
+            cboPulseWidth.SelectedIndex = args.PulseWidth;
+            cboRedLED.SelectedIndex = args.RedLedCurrent;
+            cboIRLED.SelectedIndex = args.IRLedCurrent;
+            cboGreenLED.SelectedIndex = args.GreenLedCurrent;
+            cboLEDslot1.SelectedIndex = args.Slot1;
+            cboLEDslot2.SelectedIndex = args.Slot2;
+            cboLEDslot3.SelectedIndex = args.Slot3;
+            cboLEDslot4.SelectedIndex = args.Slot4;
+        }
+
+        class MedianFilter
+        {
+            Queue<int> items;
+            int depth;
+
+            public MedianFilter(int depth)
+            {
+                items = new Queue<int>(depth + 1);
+                this.depth = depth;
+            }
+
+            public int Filter(int current)
+            {
+                int last;
+
+                items.Enqueue(current);
+                if (items.Count > depth)
+                {
+                    items.Dequeue();
+                }
+
+                last = items.Peek();
+
+                if (items.Count < depth)
+                {
+                    return current;
+                }
+                else
+                {
+                    int count;
+                    int[] arrayItems = items.ToArray();
+                    int maxCount = 0;
+                    int maxKey = 0;
+
+                    Dictionary<int, int> valueOccurance = new Dictionary<int, int>();
+
+                    for (int i = 0; i < arrayItems.Length; i++)
+                    {
+                        bool exists = valueOccurance.TryGetValue(arrayItems[i], out count);
+                        if (exists)
+                        {
+                            count++;
+                            valueOccurance.Remove(arrayItems[i]);
+                            valueOccurance.Add(arrayItems[i], count);
+                        }
+                        else
+                        {
+                            valueOccurance.Add(arrayItems[i], 1);
+                        }
+                    }
+
+                    foreach (KeyValuePair<int, int> item in valueOccurance)
+                    {
+                        if (item.Key > maxCount)
+                        {
+                            maxKey = item.Key;
+                        }
+                    }
+
+                    return maxKey;
+                }
+
+            }
+        }
+
+        /*
+        public class StreamingStartStopEventArgs : EventArgs
+        {
+            public bool state { get; set; }
+        }*/
+
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HspGuiSourceV301/HSPGui/CustomControls/OpticalView.resx	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,120 @@
+<?xml version="1.0" encoding="utf-8"?>
+<root>
+  <!-- 
+    Microsoft ResX Schema 
+    
+    Version 2.0
+    
+    The primary goals of this format is to allow a simple XML format 
+    that is mostly human readable. The generation and parsing of the 
+    various data types are done through the TypeConverter classes 
+    associated with the data types.
+    
+    Example:
+    
+    ... ado.net/XML headers & schema ...
+    <resheader name="resmimetype">text/microsoft-resx</resheader>
+    <resheader name="version">2.0</resheader>
+    <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+    <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+    <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
+    <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+    <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+        <value>[base64 mime encoded serialized .NET Framework object]</value>
+    </data>
+    <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+        <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
+        <comment>This is a comment</comment>
+    </data>
+                
+    There are any number of "resheader" rows that contain simple 
+    name/value pairs.
+    
+    Each data row contains a name, and value. The row also contains a 
+    type or mimetype. Type corresponds to a .NET class that support 
+    text/value conversion through the TypeConverter architecture. 
+    Classes that don't support this are serialized and stored with the 
+    mimetype set.
+    
+    The mimetype is used for serialized objects, and tells the 
+    ResXResourceReader how to depersist the object. This is currently not 
+    extensible. For a given mimetype the value must be set accordingly:
+    
+    Note - application/x-microsoft.net.object.binary.base64 is the format 
+    that the ResXResourceWriter will generate, however the reader can 
+    read any of the formats listed below.
+    
+    mimetype: application/x-microsoft.net.object.binary.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
+            : and then encoded with base64 encoding.
+    
+    mimetype: application/x-microsoft.net.object.soap.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+            : and then encoded with base64 encoding.
+
+    mimetype: application/x-microsoft.net.object.bytearray.base64
+    value   : The object must be serialized into a byte array 
+            : using a System.ComponentModel.TypeConverter
+            : and then encoded with base64 encoding.
+    -->
+  <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+    <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
+    <xsd:element name="root" msdata:IsDataSet="true">
+      <xsd:complexType>
+        <xsd:choice maxOccurs="unbounded">
+          <xsd:element name="metadata">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" />
+              </xsd:sequence>
+              <xsd:attribute name="name" use="required" type="xsd:string" />
+              <xsd:attribute name="type" type="xsd:string" />
+              <xsd:attribute name="mimetype" type="xsd:string" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="assembly">
+            <xsd:complexType>
+              <xsd:attribute name="alias" type="xsd:string" />
+              <xsd:attribute name="name" type="xsd:string" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="data">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+                <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
+              <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+              <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="resheader">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" />
+            </xsd:complexType>
+          </xsd:element>
+        </xsd:choice>
+      </xsd:complexType>
+    </xsd:element>
+  </xsd:schema>
+  <resheader name="resmimetype">
+    <value>text/microsoft-resx</value>
+  </resheader>
+  <resheader name="version">
+    <value>2.0</value>
+  </resheader>
+  <resheader name="reader">
+    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <resheader name="writer">
+    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+</root>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HspGuiSourceV301/HSPGui/CustomControls/PrimitivesView.Designer.cs	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,861 @@
+namespace HealthSensorPlatform.CustomControls
+{
+    partial class PrimitivesView
+    {
+        /// <summary> 
+        /// Required designer variable.
+        /// </summary>
+        private System.ComponentModel.IContainer components = null;
+
+        /// <summary> 
+        /// Clean up any resources being used.
+        /// </summary>
+        /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
+        protected override void Dispose(bool disposing)
+        {
+            if (disposing && (components != null))
+            {
+                components.Dispose();
+            }
+            base.Dispose(disposing);
+        }
+
+        #region Component Designer generated code
+
+        /// <summary> 
+        /// Required method for Designer support - do not modify 
+        /// the contents of this method with the code editor.
+        /// </summary>
+        private void InitializeComponent()
+        {
+            this.groupBox6 = new MaximStyle.MaximGroupBox();
+            this.label18 = new System.Windows.Forms.Label();
+            this.tbCommandLine = new System.Windows.Forms.TextBox();
+            this.btnRawRpcEnter = new MaximStyle.MaximButton();
+            this.groupBox5 = new MaximStyle.MaximGroupBox();
+            this.label17 = new System.Windows.Forms.Label();
+            this.tbLIS2HDWriteData = new System.Windows.Forms.TextBox();
+            this.label16 = new System.Windows.Forms.Label();
+            this.btnLIS2HDReadReg = new MaximStyle.MaximButton();
+            this.tbLIS2HDAddress = new System.Windows.Forms.TextBox();
+            this.label15 = new System.Windows.Forms.Label();
+            this.tbLIS2HDReadData = new System.Windows.Forms.TextBox();
+            this.btnLIS2HDWriteReg = new MaximStyle.MaximButton();
+            this.groupBox4 = new MaximStyle.MaximGroupBox();
+            this.label14 = new System.Windows.Forms.Label();
+            this.tbMAX30205WriteData = new System.Windows.Forms.TextBox();
+            this.btnMAX30205ReadReg = new MaximStyle.MaximButton();
+            this.tbMAX30205Address = new System.Windows.Forms.TextBox();
+            this.label13 = new System.Windows.Forms.Label();
+            this.tbMAX30205ReadData = new System.Windows.Forms.TextBox();
+            this.btnMAX30205WriteReg = new MaximStyle.MaximButton();
+            this.label12 = new System.Windows.Forms.Label();
+            this.groupBox3 = new MaximStyle.MaximGroupBox();
+            this.label11 = new System.Windows.Forms.Label();
+            this.btnMAX30101ReadReg = new MaximStyle.MaximButton();
+            this.tbMAX30101WriteData = new System.Windows.Forms.TextBox();
+            this.label10 = new System.Windows.Forms.Label();
+            this.btnSpiWriteReg = new MaximStyle.MaximButton();
+            this.tbMAX30101ReadData = new System.Windows.Forms.TextBox();
+            this.label9 = new System.Windows.Forms.Label();
+            this.tbMAX30101Address = new System.Windows.Forms.TextBox();
+            this.groupBox2 = new MaximStyle.MaximGroupBox();
+            this.label8 = new System.Windows.Forms.Label();
+            this.tbSpiWriteData = new System.Windows.Forms.TextBox();
+            this.label7 = new System.Windows.Forms.Label();
+            this.btnSpiReadReg = new MaximStyle.MaximButton();
+            this.label6 = new System.Windows.Forms.Label();
+            this.tbSpiAddress = new System.Windows.Forms.TextBox();
+            this.tbSpiReadData = new System.Windows.Forms.TextBox();
+            this.btnI2cWriteData = new MaximStyle.MaximButton();
+            this.groupBox1 = new MaximStyle.MaximGroupBox();
+            this.label5 = new System.Windows.Forms.Label();
+            this.label4 = new System.Windows.Forms.Label();
+            this.label3 = new System.Windows.Forms.Label();
+            this.label2 = new System.Windows.Forms.Label();
+            this.label1 = new System.Windows.Forms.Label();
+            this.tbI2cInstance = new System.Windows.Forms.TextBox();
+            this.tbI2cWriteData = new System.Windows.Forms.TextBox();
+            this.btnI2cWriteReg = new MaximStyle.MaximButton();
+            this.tbI2cReadData = new System.Windows.Forms.TextBox();
+            this.btnI2cReadReg = new MaximStyle.MaximButton();
+            this.tbI2cAddress = new System.Windows.Forms.TextBox();
+            this.tbI2cSlaveAddress = new System.Windows.Forms.TextBox();
+            this.btnShowHideRpcLog = new MaximStyle.MaximButton();
+            this.groupBox7 = new MaximStyle.MaximGroupBox();
+            this.label19 = new System.Windows.Forms.Label();
+            this.tbMAX30001WriteData = new System.Windows.Forms.TextBox();
+            this.btnMAX30001ReadReg = new MaximStyle.MaximButton();
+            this.tbMAX30001Address = new System.Windows.Forms.TextBox();
+            this.label20 = new System.Windows.Forms.Label();
+            this.tbMAX30001ReadData = new System.Windows.Forms.TextBox();
+            this.btnMAX30001WriteReg = new MaximStyle.MaximButton();
+            this.label21 = new System.Windows.Forms.Label();
+            this.label22 = new System.Windows.Forms.Label();
+            this.groupBox6.SuspendLayout();
+            this.groupBox5.SuspendLayout();
+            this.groupBox4.SuspendLayout();
+            this.groupBox3.SuspendLayout();
+            this.groupBox2.SuspendLayout();
+            this.groupBox1.SuspendLayout();
+            this.groupBox7.SuspendLayout();
+            this.SuspendLayout();
+            // 
+            // groupBox6
+            // 
+            this.groupBox6.BackgroundColor = System.Drawing.Color.White;
+            this.groupBox6.Controls.Add(this.label18);
+            this.groupBox6.Controls.Add(this.tbCommandLine);
+            this.groupBox6.Controls.Add(this.btnRawRpcEnter);
+            this.groupBox6.Location = new System.Drawing.Point(424, 266);
+            this.groupBox6.Name = "groupBox6";
+            this.groupBox6.Size = new System.Drawing.Size(378, 110);
+            this.groupBox6.TabIndex = 87;
+            this.groupBox6.TabStop = false;
+            this.groupBox6.Text = "Raw RPC";
+            // 
+            // label18
+            // 
+            this.label18.AutoSize = true;
+            this.label18.Location = new System.Drawing.Point(16, 28);
+            this.label18.Name = "label18";
+            this.label18.Size = new System.Drawing.Size(77, 13);
+            this.label18.TabIndex = 106;
+            this.label18.Text = "Command Line";
+            // 
+            // tbCommandLine
+            // 
+            this.tbCommandLine.Location = new System.Drawing.Point(19, 44);
+            this.tbCommandLine.Name = "tbCommandLine";
+            this.tbCommandLine.Size = new System.Drawing.Size(279, 20);
+            this.tbCommandLine.TabIndex = 65;
+            this.tbCommandLine.Text = "/I2c/ReadReg 02 AE FF";
+            // 
+            // btnRawRpcEnter
+            // 
+            this.btnRawRpcEnter.Location = new System.Drawing.Point(229, 70);
+            this.btnRawRpcEnter.Name = "btnRawRpcEnter";
+            this.btnRawRpcEnter.Size = new System.Drawing.Size(80, 23);
+            this.btnRawRpcEnter.TabIndex = 64;
+            this.btnRawRpcEnter.Text = "Enter";
+            this.btnRawRpcEnter.UseVisualStyleBackColor = true;
+            this.btnRawRpcEnter.Click += new System.EventHandler(this.btnRawRpcEnter_Click);
+            // 
+            // groupBox5
+            // 
+            this.groupBox5.BackgroundColor = System.Drawing.Color.White;
+            this.groupBox5.Controls.Add(this.label17);
+            this.groupBox5.Controls.Add(this.tbLIS2HDWriteData);
+            this.groupBox5.Controls.Add(this.label16);
+            this.groupBox5.Controls.Add(this.btnLIS2HDReadReg);
+            this.groupBox5.Controls.Add(this.tbLIS2HDAddress);
+            this.groupBox5.Controls.Add(this.label15);
+            this.groupBox5.Controls.Add(this.tbLIS2HDReadData);
+            this.groupBox5.Controls.Add(this.btnLIS2HDWriteReg);
+            this.groupBox5.Location = new System.Drawing.Point(424, 44);
+            this.groupBox5.Name = "groupBox5";
+            this.groupBox5.Size = new System.Drawing.Size(380, 110);
+            this.groupBox5.TabIndex = 86;
+            this.groupBox5.TabStop = false;
+            this.groupBox5.Text = "LIS2HD";
+            // 
+            // label17
+            // 
+            this.label17.AutoSize = true;
+            this.label17.Location = new System.Drawing.Point(226, 28);
+            this.label17.Name = "label17";
+            this.label17.Size = new System.Drawing.Size(58, 13);
+            this.label17.TabIndex = 79;
+            this.label17.Text = "Write Data";
+            // 
+            // tbLIS2HDWriteData
+            // 
+            this.tbLIS2HDWriteData.Location = new System.Drawing.Point(229, 45);
+            this.tbLIS2HDWriteData.Name = "tbLIS2HDWriteData";
+            this.tbLIS2HDWriteData.Size = new System.Drawing.Size(80, 20);
+            this.tbLIS2HDWriteData.TabIndex = 105;
+            this.tbLIS2HDWriteData.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
+            // 
+            // label16
+            // 
+            this.label16.AutoSize = true;
+            this.label16.Location = new System.Drawing.Point(120, 28);
+            this.label16.Name = "label16";
+            this.label16.Size = new System.Drawing.Size(59, 13);
+            this.label16.TabIndex = 78;
+            this.label16.Text = "Read Data";
+            // 
+            // btnLIS2HDReadReg
+            // 
+            this.btnLIS2HDReadReg.Location = new System.Drawing.Point(123, 72);
+            this.btnLIS2HDReadReg.Margin = new System.Windows.Forms.Padding(2);
+            this.btnLIS2HDReadReg.Name = "btnLIS2HDReadReg";
+            this.btnLIS2HDReadReg.Size = new System.Drawing.Size(80, 22);
+            this.btnLIS2HDReadReg.TabIndex = 98;
+            this.btnLIS2HDReadReg.Text = "ReadReg";
+            this.btnLIS2HDReadReg.UseVisualStyleBackColor = true;
+            this.btnLIS2HDReadReg.Click += new System.EventHandler(this.btnLIS2HDReadReg_Click);
+            // 
+            // tbLIS2HDAddress
+            // 
+            this.tbLIS2HDAddress.Location = new System.Drawing.Point(19, 45);
+            this.tbLIS2HDAddress.Name = "tbLIS2HDAddress";
+            this.tbLIS2HDAddress.Size = new System.Drawing.Size(80, 20);
+            this.tbLIS2HDAddress.TabIndex = 100;
+            this.tbLIS2HDAddress.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
+            // 
+            // label15
+            // 
+            this.label15.AutoSize = true;
+            this.label15.Location = new System.Drawing.Point(16, 28);
+            this.label15.Name = "label15";
+            this.label15.Size = new System.Drawing.Size(45, 13);
+            this.label15.TabIndex = 77;
+            this.label15.Text = "Address";
+            // 
+            // tbLIS2HDReadData
+            // 
+            this.tbLIS2HDReadData.Location = new System.Drawing.Point(123, 45);
+            this.tbLIS2HDReadData.Name = "tbLIS2HDReadData";
+            this.tbLIS2HDReadData.ReadOnly = true;
+            this.tbLIS2HDReadData.Size = new System.Drawing.Size(80, 20);
+            this.tbLIS2HDReadData.TabIndex = 102;
+            this.tbLIS2HDReadData.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
+            // 
+            // btnLIS2HDWriteReg
+            // 
+            this.btnLIS2HDWriteReg.Location = new System.Drawing.Point(229, 72);
+            this.btnLIS2HDWriteReg.Margin = new System.Windows.Forms.Padding(2);
+            this.btnLIS2HDWriteReg.Name = "btnLIS2HDWriteReg";
+            this.btnLIS2HDWriteReg.Size = new System.Drawing.Size(80, 22);
+            this.btnLIS2HDWriteReg.TabIndex = 104;
+            this.btnLIS2HDWriteReg.Text = "WriteReg";
+            this.btnLIS2HDWriteReg.UseVisualStyleBackColor = true;
+            this.btnLIS2HDWriteReg.Click += new System.EventHandler(this.btnLIS2HDWriteReg_Click);
+            // 
+            // groupBox4
+            // 
+            this.groupBox4.BackgroundColor = System.Drawing.Color.White;
+            this.groupBox4.Controls.Add(this.label14);
+            this.groupBox4.Controls.Add(this.tbMAX30205WriteData);
+            this.groupBox4.Controls.Add(this.btnMAX30205ReadReg);
+            this.groupBox4.Controls.Add(this.tbMAX30205Address);
+            this.groupBox4.Controls.Add(this.label13);
+            this.groupBox4.Controls.Add(this.tbMAX30205ReadData);
+            this.groupBox4.Controls.Add(this.btnMAX30205WriteReg);
+            this.groupBox4.Controls.Add(this.label12);
+            this.groupBox4.Location = new System.Drawing.Point(16, 377);
+            this.groupBox4.Name = "groupBox4";
+            this.groupBox4.Size = new System.Drawing.Size(400, 110);
+            this.groupBox4.TabIndex = 85;
+            this.groupBox4.TabStop = false;
+            this.groupBox4.Text = "MAX30205";
+            // 
+            // label14
+            // 
+            this.label14.AutoSize = true;
+            this.label14.Location = new System.Drawing.Point(226, 30);
+            this.label14.Name = "label14";
+            this.label14.Size = new System.Drawing.Size(58, 13);
+            this.label14.TabIndex = 79;
+            this.label14.Text = "Write Data";
+            // 
+            // tbMAX30205WriteData
+            // 
+            this.tbMAX30205WriteData.Location = new System.Drawing.Point(229, 46);
+            this.tbMAX30205WriteData.Name = "tbMAX30205WriteData";
+            this.tbMAX30205WriteData.Size = new System.Drawing.Size(80, 20);
+            this.tbMAX30205WriteData.TabIndex = 107;
+            this.tbMAX30205WriteData.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
+            // 
+            // btnMAX30205ReadReg
+            // 
+            this.btnMAX30205ReadReg.Location = new System.Drawing.Point(123, 72);
+            this.btnMAX30205ReadReg.Margin = new System.Windows.Forms.Padding(2);
+            this.btnMAX30205ReadReg.Name = "btnMAX30205ReadReg";
+            this.btnMAX30205ReadReg.Size = new System.Drawing.Size(80, 22);
+            this.btnMAX30205ReadReg.TabIndex = 100;
+            this.btnMAX30205ReadReg.Text = "ReadReg";
+            this.btnMAX30205ReadReg.UseVisualStyleBackColor = true;
+            this.btnMAX30205ReadReg.Click += new System.EventHandler(this.btnMAX30205ReadReg_Click);
+            // 
+            // tbMAX30205Address
+            // 
+            this.tbMAX30205Address.Location = new System.Drawing.Point(19, 46);
+            this.tbMAX30205Address.Name = "tbMAX30205Address";
+            this.tbMAX30205Address.Size = new System.Drawing.Size(80, 20);
+            this.tbMAX30205Address.TabIndex = 102;
+            this.tbMAX30205Address.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
+            // 
+            // label13
+            // 
+            this.label13.AutoSize = true;
+            this.label13.Location = new System.Drawing.Point(120, 30);
+            this.label13.Name = "label13";
+            this.label13.Size = new System.Drawing.Size(59, 13);
+            this.label13.TabIndex = 78;
+            this.label13.Text = "Read Data";
+            // 
+            // tbMAX30205ReadData
+            // 
+            this.tbMAX30205ReadData.Location = new System.Drawing.Point(123, 46);
+            this.tbMAX30205ReadData.Name = "tbMAX30205ReadData";
+            this.tbMAX30205ReadData.ReadOnly = true;
+            this.tbMAX30205ReadData.Size = new System.Drawing.Size(80, 20);
+            this.tbMAX30205ReadData.TabIndex = 104;
+            this.tbMAX30205ReadData.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
+            // 
+            // btnMAX30205WriteReg
+            // 
+            this.btnMAX30205WriteReg.Location = new System.Drawing.Point(229, 72);
+            this.btnMAX30205WriteReg.Margin = new System.Windows.Forms.Padding(2);
+            this.btnMAX30205WriteReg.Name = "btnMAX30205WriteReg";
+            this.btnMAX30205WriteReg.Size = new System.Drawing.Size(80, 22);
+            this.btnMAX30205WriteReg.TabIndex = 106;
+            this.btnMAX30205WriteReg.Text = "WriteReg";
+            this.btnMAX30205WriteReg.UseVisualStyleBackColor = true;
+            this.btnMAX30205WriteReg.Click += new System.EventHandler(this.btnMAX30205WriteReg_Click);
+            // 
+            // label12
+            // 
+            this.label12.AutoSize = true;
+            this.label12.Location = new System.Drawing.Point(16, 30);
+            this.label12.Name = "label12";
+            this.label12.Size = new System.Drawing.Size(45, 13);
+            this.label12.TabIndex = 77;
+            this.label12.Text = "Address";
+            // 
+            // groupBox3
+            // 
+            this.groupBox3.BackgroundColor = System.Drawing.Color.White;
+            this.groupBox3.Controls.Add(this.label11);
+            this.groupBox3.Controls.Add(this.btnMAX30101ReadReg);
+            this.groupBox3.Controls.Add(this.tbMAX30101WriteData);
+            this.groupBox3.Controls.Add(this.label10);
+            this.groupBox3.Controls.Add(this.btnSpiWriteReg);
+            this.groupBox3.Controls.Add(this.tbMAX30101ReadData);
+            this.groupBox3.Controls.Add(this.label9);
+            this.groupBox3.Controls.Add(this.tbMAX30101Address);
+            this.groupBox3.Location = new System.Drawing.Point(16, 266);
+            this.groupBox3.Name = "groupBox3";
+            this.groupBox3.Size = new System.Drawing.Size(400, 110);
+            this.groupBox3.TabIndex = 84;
+            this.groupBox3.TabStop = false;
+            this.groupBox3.Text = "MAX30101";
+            // 
+            // label11
+            // 
+            this.label11.AutoSize = true;
+            this.label11.Location = new System.Drawing.Point(226, 28);
+            this.label11.Name = "label11";
+            this.label11.Size = new System.Drawing.Size(58, 13);
+            this.label11.TabIndex = 79;
+            this.label11.Text = "Write Data";
+            // 
+            // btnMAX30101ReadReg
+            // 
+            this.btnMAX30101ReadReg.Location = new System.Drawing.Point(123, 71);
+            this.btnMAX30101ReadReg.Margin = new System.Windows.Forms.Padding(2);
+            this.btnMAX30101ReadReg.Name = "btnMAX30101ReadReg";
+            this.btnMAX30101ReadReg.Size = new System.Drawing.Size(80, 22);
+            this.btnMAX30101ReadReg.TabIndex = 92;
+            this.btnMAX30101ReadReg.Text = "ReadReg";
+            this.btnMAX30101ReadReg.UseVisualStyleBackColor = true;
+            this.btnMAX30101ReadReg.Click += new System.EventHandler(this.btnMAX30101ReadReg_Click);
+            // 
+            // tbMAX30101WriteData
+            // 
+            this.tbMAX30101WriteData.Location = new System.Drawing.Point(229, 44);
+            this.tbMAX30101WriteData.Name = "tbMAX30101WriteData";
+            this.tbMAX30101WriteData.Size = new System.Drawing.Size(80, 20);
+            this.tbMAX30101WriteData.TabIndex = 99;
+            this.tbMAX30101WriteData.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
+            // 
+            // label10
+            // 
+            this.label10.AutoSize = true;
+            this.label10.Location = new System.Drawing.Point(120, 28);
+            this.label10.Name = "label10";
+            this.label10.Size = new System.Drawing.Size(59, 13);
+            this.label10.TabIndex = 78;
+            this.label10.Text = "Read Data";
+            // 
+            // btnSpiWriteReg
+            // 
+            this.btnSpiWriteReg.Location = new System.Drawing.Point(229, 71);
+            this.btnSpiWriteReg.Margin = new System.Windows.Forms.Padding(2);
+            this.btnSpiWriteReg.Name = "btnSpiWriteReg";
+            this.btnSpiWriteReg.Size = new System.Drawing.Size(80, 22);
+            this.btnSpiWriteReg.TabIndex = 98;
+            this.btnSpiWriteReg.Text = "WriteReg";
+            this.btnSpiWriteReg.UseVisualStyleBackColor = true;
+            this.btnSpiWriteReg.Click += new System.EventHandler(this.btnSpiWriteReg_Click);
+            // 
+            // tbMAX30101ReadData
+            // 
+            this.tbMAX30101ReadData.Location = new System.Drawing.Point(123, 44);
+            this.tbMAX30101ReadData.Name = "tbMAX30101ReadData";
+            this.tbMAX30101ReadData.ReadOnly = true;
+            this.tbMAX30101ReadData.Size = new System.Drawing.Size(80, 20);
+            this.tbMAX30101ReadData.TabIndex = 96;
+            this.tbMAX30101ReadData.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
+            // 
+            // label9
+            // 
+            this.label9.AutoSize = true;
+            this.label9.Location = new System.Drawing.Point(16, 28);
+            this.label9.Name = "label9";
+            this.label9.Size = new System.Drawing.Size(45, 13);
+            this.label9.TabIndex = 77;
+            this.label9.Text = "Address";
+            // 
+            // tbMAX30101Address
+            // 
+            this.tbMAX30101Address.Location = new System.Drawing.Point(19, 44);
+            this.tbMAX30101Address.Name = "tbMAX30101Address";
+            this.tbMAX30101Address.Size = new System.Drawing.Size(80, 20);
+            this.tbMAX30101Address.TabIndex = 94;
+            this.tbMAX30101Address.Text = "AE";
+            this.tbMAX30101Address.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
+            // 
+            // groupBox2
+            // 
+            this.groupBox2.BackgroundColor = System.Drawing.Color.White;
+            this.groupBox2.Controls.Add(this.label8);
+            this.groupBox2.Controls.Add(this.tbSpiWriteData);
+            this.groupBox2.Controls.Add(this.label7);
+            this.groupBox2.Controls.Add(this.btnSpiReadReg);
+            this.groupBox2.Controls.Add(this.label6);
+            this.groupBox2.Controls.Add(this.tbSpiAddress);
+            this.groupBox2.Controls.Add(this.tbSpiReadData);
+            this.groupBox2.Controls.Add(this.btnI2cWriteData);
+            this.groupBox2.Location = new System.Drawing.Point(16, 155);
+            this.groupBox2.Name = "groupBox2";
+            this.groupBox2.Size = new System.Drawing.Size(400, 110);
+            this.groupBox2.TabIndex = 83;
+            this.groupBox2.TabStop = false;
+            this.groupBox2.Text = "SPI";
+            // 
+            // label8
+            // 
+            this.label8.AutoSize = true;
+            this.label8.Location = new System.Drawing.Point(226, 31);
+            this.label8.Name = "label8";
+            this.label8.Size = new System.Drawing.Size(58, 13);
+            this.label8.TabIndex = 79;
+            this.label8.Text = "Write Data";
+            // 
+            // tbSpiWriteData
+            // 
+            this.tbSpiWriteData.Location = new System.Drawing.Point(229, 47);
+            this.tbSpiWriteData.Name = "tbSpiWriteData";
+            this.tbSpiWriteData.Size = new System.Drawing.Size(80, 20);
+            this.tbSpiWriteData.TabIndex = 104;
+            this.tbSpiWriteData.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
+            // 
+            // label7
+            // 
+            this.label7.AutoSize = true;
+            this.label7.Location = new System.Drawing.Point(120, 31);
+            this.label7.Name = "label7";
+            this.label7.Size = new System.Drawing.Size(59, 13);
+            this.label7.TabIndex = 78;
+            this.label7.Text = "Read Data";
+            // 
+            // btnSpiReadReg
+            // 
+            this.btnSpiReadReg.Location = new System.Drawing.Point(123, 73);
+            this.btnSpiReadReg.Margin = new System.Windows.Forms.Padding(2);
+            this.btnSpiReadReg.Name = "btnSpiReadReg";
+            this.btnSpiReadReg.Size = new System.Drawing.Size(80, 22);
+            this.btnSpiReadReg.TabIndex = 97;
+            this.btnSpiReadReg.Text = "ReadReg";
+            this.btnSpiReadReg.UseVisualStyleBackColor = true;
+            this.btnSpiReadReg.Click += new System.EventHandler(this.btnSpiReadReg_Click);
+            // 
+            // label6
+            // 
+            this.label6.AutoSize = true;
+            this.label6.Location = new System.Drawing.Point(16, 31);
+            this.label6.Name = "label6";
+            this.label6.Size = new System.Drawing.Size(45, 13);
+            this.label6.TabIndex = 77;
+            this.label6.Text = "Address";
+            // 
+            // tbSpiAddress
+            // 
+            this.tbSpiAddress.Location = new System.Drawing.Point(19, 47);
+            this.tbSpiAddress.Name = "tbSpiAddress";
+            this.tbSpiAddress.Size = new System.Drawing.Size(80, 20);
+            this.tbSpiAddress.TabIndex = 99;
+            this.tbSpiAddress.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
+            // 
+            // tbSpiReadData
+            // 
+            this.tbSpiReadData.Location = new System.Drawing.Point(123, 47);
+            this.tbSpiReadData.Name = "tbSpiReadData";
+            this.tbSpiReadData.ReadOnly = true;
+            this.tbSpiReadData.Size = new System.Drawing.Size(80, 20);
+            this.tbSpiReadData.TabIndex = 101;
+            this.tbSpiReadData.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
+            // 
+            // btnI2cWriteData
+            // 
+            this.btnI2cWriteData.Location = new System.Drawing.Point(229, 73);
+            this.btnI2cWriteData.Margin = new System.Windows.Forms.Padding(2);
+            this.btnI2cWriteData.Name = "btnI2cWriteData";
+            this.btnI2cWriteData.Size = new System.Drawing.Size(80, 22);
+            this.btnI2cWriteData.TabIndex = 103;
+            this.btnI2cWriteData.Text = "WriteReg";
+            this.btnI2cWriteData.UseVisualStyleBackColor = true;
+            this.btnI2cWriteData.Click += new System.EventHandler(this.btnI2cWriteData_Click);
+            // 
+            // groupBox1
+            // 
+            this.groupBox1.BackgroundColor = System.Drawing.Color.White;
+            this.groupBox1.Controls.Add(this.label5);
+            this.groupBox1.Controls.Add(this.label4);
+            this.groupBox1.Controls.Add(this.label3);
+            this.groupBox1.Controls.Add(this.label2);
+            this.groupBox1.Controls.Add(this.label1);
+            this.groupBox1.Controls.Add(this.tbI2cInstance);
+            this.groupBox1.Controls.Add(this.tbI2cWriteData);
+            this.groupBox1.Controls.Add(this.btnI2cWriteReg);
+            this.groupBox1.Controls.Add(this.tbI2cReadData);
+            this.groupBox1.Controls.Add(this.btnI2cReadReg);
+            this.groupBox1.Controls.Add(this.tbI2cAddress);
+            this.groupBox1.Controls.Add(this.tbI2cSlaveAddress);
+            this.groupBox1.Location = new System.Drawing.Point(16, 44);
+            this.groupBox1.Name = "groupBox1";
+            this.groupBox1.Size = new System.Drawing.Size(400, 110);
+            this.groupBox1.TabIndex = 82;
+            this.groupBox1.TabStop = false;
+            this.groupBox1.Text = "I2C";
+            // 
+            // label5
+            // 
+            this.label5.AutoSize = true;
+            this.label5.Location = new System.Drawing.Point(317, 27);
+            this.label5.Name = "label5";
+            this.label5.Size = new System.Drawing.Size(58, 13);
+            this.label5.TabIndex = 79;
+            this.label5.Text = "Write Data";
+            // 
+            // label4
+            // 
+            this.label4.AutoSize = true;
+            this.label4.Location = new System.Drawing.Point(250, 27);
+            this.label4.Name = "label4";
+            this.label4.Size = new System.Drawing.Size(59, 13);
+            this.label4.TabIndex = 78;
+            this.label4.Text = "Read Data";
+            // 
+            // label3
+            // 
+            this.label3.AutoSize = true;
+            this.label3.Location = new System.Drawing.Point(166, 27);
+            this.label3.Name = "label3";
+            this.label3.Size = new System.Drawing.Size(45, 13);
+            this.label3.TabIndex = 77;
+            this.label3.Text = "Address";
+            // 
+            // label2
+            // 
+            this.label2.AutoSize = true;
+            this.label2.Location = new System.Drawing.Point(91, 27);
+            this.label2.Name = "label2";
+            this.label2.Size = new System.Drawing.Size(75, 13);
+            this.label2.TabIndex = 76;
+            this.label2.Text = "Slave Address";
+            // 
+            // label1
+            // 
+            this.label1.AutoSize = true;
+            this.label1.Location = new System.Drawing.Point(12, 27);
+            this.label1.Name = "label1";
+            this.label1.Size = new System.Drawing.Size(48, 13);
+            this.label1.TabIndex = 75;
+            this.label1.Text = "Instance";
+            // 
+            // tbI2cInstance
+            // 
+            this.tbI2cInstance.Location = new System.Drawing.Point(15, 45);
+            this.tbI2cInstance.Name = "tbI2cInstance";
+            this.tbI2cInstance.Size = new System.Drawing.Size(69, 20);
+            this.tbI2cInstance.TabIndex = 72;
+            this.tbI2cInstance.Text = "2";
+            this.tbI2cInstance.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
+            // 
+            // tbI2cWriteData
+            // 
+            this.tbI2cWriteData.Location = new System.Drawing.Point(320, 45);
+            this.tbI2cWriteData.Name = "tbI2cWriteData";
+            this.tbI2cWriteData.Size = new System.Drawing.Size(69, 20);
+            this.tbI2cWriteData.TabIndex = 74;
+            this.tbI2cWriteData.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
+            // 
+            // btnI2cWriteReg
+            // 
+            this.btnI2cWriteReg.Location = new System.Drawing.Point(320, 72);
+            this.btnI2cWriteReg.Margin = new System.Windows.Forms.Padding(2);
+            this.btnI2cWriteReg.Name = "btnI2cWriteReg";
+            this.btnI2cWriteReg.Size = new System.Drawing.Size(69, 22);
+            this.btnI2cWriteReg.TabIndex = 71;
+            this.btnI2cWriteReg.Text = "WriteReg";
+            this.btnI2cWriteReg.UseVisualStyleBackColor = true;
+            this.btnI2cWriteReg.Click += new System.EventHandler(this.btnI2cWriteReg_Click);
+            // 
+            // tbI2cReadData
+            // 
+            this.tbI2cReadData.Location = new System.Drawing.Point(253, 45);
+            this.tbI2cReadData.Name = "tbI2cReadData";
+            this.tbI2cReadData.ReadOnly = true;
+            this.tbI2cReadData.Size = new System.Drawing.Size(61, 20);
+            this.tbI2cReadData.TabIndex = 69;
+            this.tbI2cReadData.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
+            // 
+            // btnI2cReadReg
+            // 
+            this.btnI2cReadReg.Location = new System.Drawing.Point(253, 72);
+            this.btnI2cReadReg.Margin = new System.Windows.Forms.Padding(2);
+            this.btnI2cReadReg.Name = "btnI2cReadReg";
+            this.btnI2cReadReg.Size = new System.Drawing.Size(61, 22);
+            this.btnI2cReadReg.TabIndex = 64;
+            this.btnI2cReadReg.Text = "ReadReg";
+            this.btnI2cReadReg.UseVisualStyleBackColor = true;
+            this.btnI2cReadReg.Click += new System.EventHandler(this.btnI2cReadReg_Click);
+            // 
+            // tbI2cAddress
+            // 
+            this.tbI2cAddress.Location = new System.Drawing.Point(169, 45);
+            this.tbI2cAddress.Name = "tbI2cAddress";
+            this.tbI2cAddress.Size = new System.Drawing.Size(69, 20);
+            this.tbI2cAddress.TabIndex = 67;
+            this.tbI2cAddress.Text = "FF";
+            this.tbI2cAddress.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
+            // 
+            // tbI2cSlaveAddress
+            // 
+            this.tbI2cSlaveAddress.Location = new System.Drawing.Point(94, 45);
+            this.tbI2cSlaveAddress.Name = "tbI2cSlaveAddress";
+            this.tbI2cSlaveAddress.Size = new System.Drawing.Size(69, 20);
+            this.tbI2cSlaveAddress.TabIndex = 65;
+            this.tbI2cSlaveAddress.Text = "AE";
+            this.tbI2cSlaveAddress.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
+            // 
+            // btnShowHideRpcLog
+            // 
+            this.btnShowHideRpcLog.Location = new System.Drawing.Point(16, 15);
+            this.btnShowHideRpcLog.Name = "btnShowHideRpcLog";
+            this.btnShowHideRpcLog.Size = new System.Drawing.Size(127, 23);
+            this.btnShowHideRpcLog.TabIndex = 88;
+            this.btnShowHideRpcLog.Text = "Show RPC Log";
+            this.btnShowHideRpcLog.UseVisualStyleBackColor = true;
+            this.btnShowHideRpcLog.Click += new System.EventHandler(this.btnShowHideRpcLog_Click);
+            // 
+            // groupBox7
+            // 
+            this.groupBox7.BackgroundColor = System.Drawing.Color.White;
+            this.groupBox7.Controls.Add(this.label19);
+            this.groupBox7.Controls.Add(this.tbMAX30001WriteData);
+            this.groupBox7.Controls.Add(this.btnMAX30001ReadReg);
+            this.groupBox7.Controls.Add(this.tbMAX30001Address);
+            this.groupBox7.Controls.Add(this.label20);
+            this.groupBox7.Controls.Add(this.tbMAX30001ReadData);
+            this.groupBox7.Controls.Add(this.btnMAX30001WriteReg);
+            this.groupBox7.Controls.Add(this.label21);
+            this.groupBox7.Location = new System.Drawing.Point(424, 155);
+            this.groupBox7.Name = "groupBox7";
+            this.groupBox7.Size = new System.Drawing.Size(380, 110);
+            this.groupBox7.TabIndex = 109;
+            this.groupBox7.TabStop = false;
+            this.groupBox7.Text = "MAX30001";
+            // 
+            // label19
+            // 
+            this.label19.AutoSize = true;
+            this.label19.Location = new System.Drawing.Point(226, 31);
+            this.label19.Name = "label19";
+            this.label19.Size = new System.Drawing.Size(58, 13);
+            this.label19.TabIndex = 79;
+            this.label19.Text = "Write Data";
+            // 
+            // tbMAX30001WriteData
+            // 
+            this.tbMAX30001WriteData.Location = new System.Drawing.Point(229, 47);
+            this.tbMAX30001WriteData.Name = "tbMAX30001WriteData";
+            this.tbMAX30001WriteData.Size = new System.Drawing.Size(80, 20);
+            this.tbMAX30001WriteData.TabIndex = 107;
+            this.tbMAX30001WriteData.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
+            // 
+            // btnMAX30001ReadReg
+            // 
+            this.btnMAX30001ReadReg.Location = new System.Drawing.Point(123, 73);
+            this.btnMAX30001ReadReg.Margin = new System.Windows.Forms.Padding(2);
+            this.btnMAX30001ReadReg.Name = "btnMAX30001ReadReg";
+            this.btnMAX30001ReadReg.Size = new System.Drawing.Size(80, 22);
+            this.btnMAX30001ReadReg.TabIndex = 100;
+            this.btnMAX30001ReadReg.Text = "ReadReg";
+            this.btnMAX30001ReadReg.UseVisualStyleBackColor = true;
+            this.btnMAX30001ReadReg.Click += new System.EventHandler(this.btnMAX30001ReadReg_Click);
+            // 
+            // tbMAX30001Address
+            // 
+            this.tbMAX30001Address.Location = new System.Drawing.Point(19, 47);
+            this.tbMAX30001Address.Name = "tbMAX30001Address";
+            this.tbMAX30001Address.Size = new System.Drawing.Size(80, 20);
+            this.tbMAX30001Address.TabIndex = 102;
+            this.tbMAX30001Address.Text = "02";
+            this.tbMAX30001Address.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
+            // 
+            // label20
+            // 
+            this.label20.AutoSize = true;
+            this.label20.Location = new System.Drawing.Point(120, 31);
+            this.label20.Name = "label20";
+            this.label20.Size = new System.Drawing.Size(59, 13);
+            this.label20.TabIndex = 78;
+            this.label20.Text = "Read Data";
+            // 
+            // tbMAX30001ReadData
+            // 
+            this.tbMAX30001ReadData.Location = new System.Drawing.Point(123, 47);
+            this.tbMAX30001ReadData.Name = "tbMAX30001ReadData";
+            this.tbMAX30001ReadData.ReadOnly = true;
+            this.tbMAX30001ReadData.Size = new System.Drawing.Size(80, 20);
+            this.tbMAX30001ReadData.TabIndex = 104;
+            this.tbMAX30001ReadData.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
+            // 
+            // btnMAX30001WriteReg
+            // 
+            this.btnMAX30001WriteReg.Location = new System.Drawing.Point(229, 73);
+            this.btnMAX30001WriteReg.Margin = new System.Windows.Forms.Padding(2);
+            this.btnMAX30001WriteReg.Name = "btnMAX30001WriteReg";
+            this.btnMAX30001WriteReg.Size = new System.Drawing.Size(80, 22);
+            this.btnMAX30001WriteReg.TabIndex = 106;
+            this.btnMAX30001WriteReg.Text = "WriteReg";
+            this.btnMAX30001WriteReg.UseVisualStyleBackColor = true;
+            this.btnMAX30001WriteReg.Click += new System.EventHandler(this.btnMAX30001WriteReg_Click);
+            // 
+            // label21
+            // 
+            this.label21.AutoSize = true;
+            this.label21.Location = new System.Drawing.Point(16, 31);
+            this.label21.Name = "label21";
+            this.label21.Size = new System.Drawing.Size(45, 13);
+            this.label21.TabIndex = 77;
+            this.label21.Text = "Address";
+            // 
+            // label22
+            // 
+            this.label22.AutoSize = true;
+            this.label22.Location = new System.Drawing.Point(20, 494);
+            this.label22.Name = "label22";
+            this.label22.Size = new System.Drawing.Size(230, 13);
+            this.label22.TabIndex = 110;
+            this.label22.Text = "Note: All values on this tab are in hexadecimal. ";
+            // 
+            // PrimitivesView
+            // 
+            this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
+            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+            this.BackColor = System.Drawing.Color.White;
+            this.Controls.Add(this.label22);
+            this.Controls.Add(this.groupBox7);
+            this.Controls.Add(this.btnShowHideRpcLog);
+            this.Controls.Add(this.groupBox6);
+            this.Controls.Add(this.groupBox5);
+            this.Controls.Add(this.groupBox4);
+            this.Controls.Add(this.groupBox3);
+            this.Controls.Add(this.groupBox2);
+            this.Controls.Add(this.groupBox1);
+            this.Name = "PrimitivesView";
+            this.Size = new System.Drawing.Size(1006, 512);
+            this.Load += new System.EventHandler(this.PrimitivesView_Load);
+            this.groupBox6.ResumeLayout(false);
+            this.groupBox6.PerformLayout();
+            this.groupBox5.ResumeLayout(false);
+            this.groupBox5.PerformLayout();
+            this.groupBox4.ResumeLayout(false);
+            this.groupBox4.PerformLayout();
+            this.groupBox3.ResumeLayout(false);
+            this.groupBox3.PerformLayout();
+            this.groupBox2.ResumeLayout(false);
+            this.groupBox2.PerformLayout();
+            this.groupBox1.ResumeLayout(false);
+            this.groupBox1.PerformLayout();
+            this.groupBox7.ResumeLayout(false);
+            this.groupBox7.PerformLayout();
+            this.ResumeLayout(false);
+            this.PerformLayout();
+
+        }
+
+        #endregion
+
+        private MaximStyle.MaximGroupBox groupBox6;
+        private System.Windows.Forms.TextBox tbCommandLine;
+        private MaximStyle.MaximButton btnRawRpcEnter;
+        private MaximStyle.MaximGroupBox groupBox5;
+        private System.Windows.Forms.TextBox tbLIS2HDWriteData;
+        private MaximStyle.MaximButton btnLIS2HDReadReg;
+        private System.Windows.Forms.TextBox tbLIS2HDAddress;
+        private System.Windows.Forms.TextBox tbLIS2HDReadData;
+        private MaximStyle.MaximButton btnLIS2HDWriteReg;
+        private MaximStyle.MaximGroupBox groupBox4;
+        private System.Windows.Forms.TextBox tbMAX30205WriteData;
+        private MaximStyle.MaximButton btnMAX30205ReadReg;
+        private System.Windows.Forms.TextBox tbMAX30205Address;
+        private System.Windows.Forms.TextBox tbMAX30205ReadData;
+        private MaximStyle.MaximButton btnMAX30205WriteReg;
+        private MaximStyle.MaximGroupBox groupBox3;
+        private MaximStyle.MaximButton btnMAX30101ReadReg;
+        private System.Windows.Forms.TextBox tbMAX30101WriteData;
+        private MaximStyle.MaximButton btnSpiWriteReg;
+        private System.Windows.Forms.TextBox tbMAX30101ReadData;
+        private System.Windows.Forms.TextBox tbMAX30101Address;
+        private MaximStyle.MaximGroupBox groupBox2;
+        private System.Windows.Forms.TextBox tbSpiWriteData;
+        private MaximStyle.MaximButton btnSpiReadReg;
+        private System.Windows.Forms.TextBox tbSpiAddress;
+        private System.Windows.Forms.TextBox tbSpiReadData;
+        private MaximStyle.MaximButton btnI2cWriteData;
+        private MaximStyle.MaximGroupBox groupBox1;
+        private System.Windows.Forms.TextBox tbI2cInstance;
+        private System.Windows.Forms.TextBox tbI2cWriteData;
+        private MaximStyle.MaximButton btnI2cWriteReg;
+        private System.Windows.Forms.TextBox tbI2cReadData;
+        private MaximStyle.MaximButton btnI2cReadReg;
+        private System.Windows.Forms.TextBox tbI2cAddress;
+        private System.Windows.Forms.TextBox tbI2cSlaveAddress;
+        private MaximStyle.MaximButton btnShowHideRpcLog;
+        private System.Windows.Forms.Label label1;
+        private System.Windows.Forms.Label label18;
+        private System.Windows.Forms.Label label17;
+        private System.Windows.Forms.Label label16;
+        private System.Windows.Forms.Label label15;
+        private System.Windows.Forms.Label label14;
+        private System.Windows.Forms.Label label13;
+        private System.Windows.Forms.Label label12;
+        private System.Windows.Forms.Label label11;
+        private System.Windows.Forms.Label label10;
+        private System.Windows.Forms.Label label9;
+        private System.Windows.Forms.Label label8;
+        private System.Windows.Forms.Label label7;
+        private System.Windows.Forms.Label label6;
+        private System.Windows.Forms.Label label5;
+        private System.Windows.Forms.Label label4;
+        private System.Windows.Forms.Label label3;
+        private System.Windows.Forms.Label label2;
+        private MaximStyle.MaximGroupBox groupBox7;
+        private System.Windows.Forms.Label label19;
+        private System.Windows.Forms.TextBox tbMAX30001WriteData;
+        private MaximStyle.MaximButton btnMAX30001ReadReg;
+        private System.Windows.Forms.TextBox tbMAX30001Address;
+        private System.Windows.Forms.Label label20;
+        private System.Windows.Forms.TextBox tbMAX30001ReadData;
+        private MaximStyle.MaximButton btnMAX30001WriteReg;
+        private System.Windows.Forms.Label label21;
+        private System.Windows.Forms.Label label22;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HspGuiSourceV301/HSPGui/CustomControls/PrimitivesView.cs	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,259 @@
+/*******************************************************************************
+* Copyright (C) 2016 Maxim Integrated Products, Inc., All rights Reserved.
+* 
+* This software is protected by copyright laws of the United States and
+* of foreign countries. This material may also be protected by patent laws
+* and technology transfer regulations of the United States and of foreign
+* countries. This software is furnished under a license agreement and/or a
+* nondisclosure agreement and may only be used or reproduced in accordance
+* with the terms of those agreements. Dissemination of this information to
+* any party or parties not specified in the license agreement and/or
+* nondisclosure agreement is expressly prohibited.
+*
+* The above copyright notice and this permission notice shall be included
+* in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+* OTHER DEALINGS IN THE SOFTWARE.
+*
+* Except as contained in this notice, the name of Maxim Integrated
+* Products, Inc. shall not be used except as stated in the Maxim Integrated
+* Products, Inc. Branding Policy.
+*
+* The mere transfer of this software does not imply any licenses
+* of trade secrets, proprietary technology, copyrights, patents,
+* trademarks, maskwork rights, or any other form of intellectual
+* property whatsoever. Maxim Integrated Products, Inc. retains all
+* ownership rights.
+*******************************************************************************
+*/
+
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Drawing;
+using System.Data;
+using System.Linq;
+using System.Text;
+using System.Windows.Forms;
+using System.Globalization;
+
+namespace HealthSensorPlatform.CustomControls
+{
+    public partial class PrimitivesView : UserControl
+    {
+        public PrimitivesView()
+        {
+            InitializeComponent();
+        }
+
+        public RPCSupport.RPCClient rpcClient { get; set; }
+        public RPCSupport.Devices.I2cDevice i2cDevice { get; set; }
+        public RPCSupport.Devices.SpiDevice spiDevice { get; set; }
+        public RPCSupport.Devices.MAX30101 max30101 { get; set; }
+        public RPCSupport.Devices.MAX30205 max30205 { get; set; }
+        public RPCSupport.Devices.MAX30001 max30001 { get; set; }
+        public RPCSupport.Devices.LIS2HD lis2hd { get; set; }
+
+        private void PrimitivesView_Load(object sender, EventArgs e)
+        {
+ 
+        }
+
+        private void btnRawRpcEnter_Click(object sender, EventArgs e)
+        {
+            String request = tbCommandLine.Text + "\r\n";
+            String reply = rpcClient.RawRpcCall(request, true);
+            //txt_Status.Text += request;
+            //txt_Status.Text += reply + "\r\n";
+        }
+
+        private void btnI2cReadReg_Click(object sender, EventArgs e)
+        {
+            byte instance;
+            byte slaveAddress;
+            byte address;
+            if (byte.TryParse(tbI2cInstance.Text, NumberStyles.HexNumber, CultureInfo.CurrentCulture, out instance))
+            {
+                if (byte.TryParse(tbI2cSlaveAddress.Text, NumberStyles.HexNumber, CultureInfo.CurrentCulture, out slaveAddress))
+                {
+                    if (byte.TryParse(tbI2cAddress.Text, NumberStyles.HexNumber, CultureInfo.CurrentCulture, out address))
+                    {
+                        byte value = i2cDevice.ReadReg(instance, slaveAddress, address);
+                        tbI2cReadData.Text = value.ToString("X2");
+                    }
+                }
+            }
+        }
+
+        private void btnI2cWriteReg_Click(object sender, EventArgs e)
+        {
+            byte instance;
+            byte slaveAddress;
+            byte address;
+            byte data;
+            if (byte.TryParse(tbI2cInstance.Text, NumberStyles.HexNumber, CultureInfo.CurrentCulture, out instance))
+            {
+                if (byte.TryParse(tbI2cSlaveAddress.Text, NumberStyles.HexNumber, CultureInfo.CurrentCulture, out slaveAddress))
+                {
+                    if (byte.TryParse(tbI2cAddress.Text, NumberStyles.HexNumber, CultureInfo.CurrentCulture, out address))
+                    {
+                        if (byte.TryParse(tbI2cWriteData.Text, NumberStyles.HexNumber, CultureInfo.CurrentCulture, out data))
+                        {
+                            i2cDevice.WriteReg(instance, slaveAddress, address, data);
+                        }
+                    }
+                }
+            }
+        }
+
+        private void btnMAX30101ReadReg_Click(object sender, EventArgs e)
+        {
+            byte address;
+            if (byte.TryParse(tbMAX30101Address.Text, NumberStyles.HexNumber, CultureInfo.CurrentCulture, out address))
+            {
+                byte value = max30101.ReadReg(address);
+                tbMAX30101ReadData.Text = value.ToString("X2");
+            }
+        }
+
+        private void btnSpiWriteReg_Click(object sender, EventArgs e)
+        {
+            byte data;
+            byte address;
+            if (byte.TryParse(tbMAX30101WriteData.Text, NumberStyles.HexNumber, CultureInfo.CurrentCulture, out data))
+            {
+                if (byte.TryParse(tbMAX30101Address.Text, NumberStyles.HexNumber, CultureInfo.CurrentCulture, out address))
+                {
+                    max30101.WriteReg(address, data);
+                }
+            }
+        }
+
+        private void btnMAX30205ReadReg_Click(object sender, EventArgs e)
+        {
+            byte address;
+            if (byte.TryParse(tbMAX30205Address.Text, NumberStyles.HexNumber, CultureInfo.CurrentCulture, out address))
+            {
+                byte value = max30205.ReadReg(address);
+                tbMAX30205ReadData.Text = value.ToString("X2");
+            }
+        }
+
+        private void btnMAX30205WriteReg_Click(object sender, EventArgs e)
+        {
+            byte data;
+            byte address;
+            if (byte.TryParse(tbMAX30205WriteData.Text, NumberStyles.HexNumber, CultureInfo.CurrentCulture, out data))
+            {
+                if (byte.TryParse(tbMAX30205Address.Text, NumberStyles.HexNumber, CultureInfo.CurrentCulture, out address))
+                {
+                    max30205.WriteReg(address, data);
+                }
+            }
+        }
+
+        private void btnLIS2HDReadReg_Click(object sender, EventArgs e)
+        {
+            byte address;
+            if (byte.TryParse(tbLIS2HDAddress.Text, NumberStyles.HexNumber, CultureInfo.CurrentCulture, out address))
+            {
+                byte value = lis2hd.ReadReg(address);
+                tbLIS2HDReadData.Text = value.ToString("X2");
+            }
+        }
+
+        private void btnLIS2HDWriteReg_Click(object sender, EventArgs e)
+        {
+            byte data;
+            byte address;
+            if (byte.TryParse(tbLIS2HDWriteData.Text, NumberStyles.HexNumber, CultureInfo.CurrentCulture, out data))
+            {
+                if (byte.TryParse(tbLIS2HDAddress.Text, NumberStyles.HexNumber, CultureInfo.CurrentCulture, out address))
+                {
+                    lis2hd.WriteReg(address, data);
+                }
+            }
+        }
+
+        private void btnSpiReadReg_Click(object sender, EventArgs e)
+        {
+
+        }
+
+        private void btnI2cWriteData_Click(object sender, EventArgs e)
+        {
+
+        }
+
+        private void btnShowHideRpcLog_Click(object sender, EventArgs e)
+        {
+            if (rpcClient.IsRpcLogShown() == false)
+            {
+                rpcClient.ShowRpcLog(true);
+                btnShowHideRpcLog.Text = "Hide RPC Log";
+            }
+            else
+            {
+                rpcClient.ShowRpcLog(false);
+                btnShowHideRpcLog.Text = "Show RPC Log";
+            }
+        }
+
+        private void btnMAX30001ReadReg_Click(object sender, EventArgs e)
+        {
+            byte address;
+            if (byte.TryParse(tbMAX30001Address.Text, NumberStyles.HexNumber, CultureInfo.CurrentCulture, out address))
+            {
+                int value = max30001.ReadReg(address);
+                tbMAX30001ReadData.Text = value.ToString("X4");
+            }
+        }
+
+        private void btnMAX30001WriteReg_Click(object sender, EventArgs e)
+        {
+            int data;
+            byte address;
+            if (int.TryParse(tbMAX30001WriteData.Text, NumberStyles.HexNumber, CultureInfo.CurrentCulture, out data))
+            {
+                if (byte.TryParse(tbMAX30001Address.Text, NumberStyles.HexNumber, CultureInfo.CurrentCulture, out address))
+                {
+                    max30001.WriteReg(address, data);
+                }
+            }
+        }
+
+        /*
+ 
+                 void LogRpcRequest(string request)
+                {
+                    txt_Status.Text += request;
+                }
+
+                void LogRpcReply(string reply)
+                {
+                    txt_Status.Text += reply + "\r\n";
+                }
+
+                private void txt_Status_TextChanged(object sender, EventArgs e)
+                {
+                    //Scroll to the bottom of the textbox when text is added
+                    txt_Status.SelectionStart = txt_Status.Text.Length;
+                    txt_Status.ScrollToCaret();
+                    txt_Status.Refresh();
+                }
+
+                private void btn_Clear_Click(object sender, EventArgs e)
+                {
+                    //clear the status box
+                    txt_Status.Text = "";
+                }
+         */
+
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HspGuiSourceV301/HSPGui/CustomControls/PrimitivesView.resx	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,120 @@
+<?xml version="1.0" encoding="utf-8"?>
+<root>
+  <!-- 
+    Microsoft ResX Schema 
+    
+    Version 2.0
+    
+    The primary goals of this format is to allow a simple XML format 
+    that is mostly human readable. The generation and parsing of the 
+    various data types are done through the TypeConverter classes 
+    associated with the data types.
+    
+    Example:
+    
+    ... ado.net/XML headers & schema ...
+    <resheader name="resmimetype">text/microsoft-resx</resheader>
+    <resheader name="version">2.0</resheader>
+    <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+    <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+    <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
+    <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+    <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+        <value>[base64 mime encoded serialized .NET Framework object]</value>
+    </data>
+    <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+        <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
+        <comment>This is a comment</comment>
+    </data>
+                
+    There are any number of "resheader" rows that contain simple 
+    name/value pairs.
+    
+    Each data row contains a name, and value. The row also contains a 
+    type or mimetype. Type corresponds to a .NET class that support 
+    text/value conversion through the TypeConverter architecture. 
+    Classes that don't support this are serialized and stored with the 
+    mimetype set.
+    
+    The mimetype is used for serialized objects, and tells the 
+    ResXResourceReader how to depersist the object. This is currently not 
+    extensible. For a given mimetype the value must be set accordingly:
+    
+    Note - application/x-microsoft.net.object.binary.base64 is the format 
+    that the ResXResourceWriter will generate, however the reader can 
+    read any of the formats listed below.
+    
+    mimetype: application/x-microsoft.net.object.binary.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
+            : and then encoded with base64 encoding.
+    
+    mimetype: application/x-microsoft.net.object.soap.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+            : and then encoded with base64 encoding.
+
+    mimetype: application/x-microsoft.net.object.bytearray.base64
+    value   : The object must be serialized into a byte array 
+            : using a System.ComponentModel.TypeConverter
+            : and then encoded with base64 encoding.
+    -->
+  <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+    <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
+    <xsd:element name="root" msdata:IsDataSet="true">
+      <xsd:complexType>
+        <xsd:choice maxOccurs="unbounded">
+          <xsd:element name="metadata">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" />
+              </xsd:sequence>
+              <xsd:attribute name="name" use="required" type="xsd:string" />
+              <xsd:attribute name="type" type="xsd:string" />
+              <xsd:attribute name="mimetype" type="xsd:string" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="assembly">
+            <xsd:complexType>
+              <xsd:attribute name="alias" type="xsd:string" />
+              <xsd:attribute name="name" type="xsd:string" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="data">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+                <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
+              <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+              <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="resheader">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" />
+            </xsd:complexType>
+          </xsd:element>
+        </xsd:choice>
+      </xsd:complexType>
+    </xsd:element>
+  </xsd:schema>
+  <resheader name="resmimetype">
+    <value>text/microsoft-resx</value>
+  </resheader>
+  <resheader name="version">
+    <value>2.0</value>
+  </resheader>
+  <resheader name="reader">
+    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <resheader name="writer">
+    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+</root>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HspGuiSourceV301/HSPGui/CustomControls/RegisterExportView.Designer.cs	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,247 @@
+namespace HealthSensorPlatform.CustomControls
+{
+    partial class RegisterExportView
+    {
+        /// <summary> 
+        /// Required designer variable.
+        /// </summary>
+        private System.ComponentModel.IContainer components = null;
+
+        /// <summary> 
+        /// Clean up any resources being used.
+        /// </summary>
+        /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
+        protected override void Dispose(bool disposing)
+        {
+            if (disposing && (components != null))
+            {
+                components.Dispose();
+            }
+            base.Dispose(disposing);
+        }
+
+        #region Component Designer generated code
+
+        /// <summary> 
+        /// Required method for Designer support - do not modify 
+        /// the contents of this method with the code editor.
+        /// </summary>
+        private void InitializeComponent()
+        {
+            this.tableLayoutPanel1 = new System.Windows.Forms.TableLayoutPanel();
+            this.listViewRight = new System.Windows.Forms.ListBox();
+            this.listViewLeft = new System.Windows.Forms.ListBox();
+            this.label2 = new System.Windows.Forms.Label();
+            this.label3 = new System.Windows.Forms.Label();
+            this.tableLayoutPanel2 = new System.Windows.Forms.TableLayoutPanel();
+            this.btnRight = new MaximStyle.MaximButton();
+            this.btnLeft = new MaximStyle.MaximButton();
+            this.btnExport = new MaximStyle.MaximButton();
+            this.btnCancel = new MaximStyle.MaximButton();
+            this.tableLayoutPanel3 = new System.Windows.Forms.TableLayoutPanel();
+            this.label1 = new System.Windows.Forms.Label();
+            this.tableLayoutPanel1.SuspendLayout();
+            this.tableLayoutPanel2.SuspendLayout();
+            this.tableLayoutPanel3.SuspendLayout();
+            this.SuspendLayout();
+            // 
+            // tableLayoutPanel1
+            // 
+            this.tableLayoutPanel1.BackColor = System.Drawing.Color.White;
+            this.tableLayoutPanel1.ColumnCount = 5;
+            this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 25F));
+            this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 50F));
+            this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 60F));
+            this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 50F));
+            this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 21F));
+            this.tableLayoutPanel1.Controls.Add(this.listViewRight, 3, 1);
+            this.tableLayoutPanel1.Controls.Add(this.listViewLeft, 1, 1);
+            this.tableLayoutPanel1.Controls.Add(this.label2, 1, 0);
+            this.tableLayoutPanel1.Controls.Add(this.label3, 3, 0);
+            this.tableLayoutPanel1.Controls.Add(this.tableLayoutPanel2, 2, 1);
+            this.tableLayoutPanel1.Controls.Add(this.btnExport, 3, 3);
+            this.tableLayoutPanel1.Controls.Add(this.btnCancel, 1, 3);
+            this.tableLayoutPanel1.Dock = System.Windows.Forms.DockStyle.Fill;
+            this.tableLayoutPanel1.Font = new System.Drawing.Font("Arial", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+            this.tableLayoutPanel1.Location = new System.Drawing.Point(0, 26);
+            this.tableLayoutPanel1.Name = "tableLayoutPanel1";
+            this.tableLayoutPanel1.RowCount = 4;
+            this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 20F));
+            this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F));
+            this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 5F));
+            this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 50F));
+            this.tableLayoutPanel1.Size = new System.Drawing.Size(392, 415);
+            this.tableLayoutPanel1.TabIndex = 2;
+            // 
+            // listViewRight
+            // 
+            this.listViewRight.Dock = System.Windows.Forms.DockStyle.Fill;
+            this.listViewRight.Font = new System.Drawing.Font("Arial", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+            this.listViewRight.ItemHeight = 15;
+            this.listViewRight.Location = new System.Drawing.Point(231, 23);
+            this.listViewRight.Name = "listViewRight";
+            this.listViewRight.Size = new System.Drawing.Size(137, 334);
+            this.listViewRight.TabIndex = 1;
+            // 
+            // listViewLeft
+            // 
+            this.listViewLeft.BackColor = System.Drawing.SystemColors.Window;
+            this.listViewLeft.Dock = System.Windows.Forms.DockStyle.Fill;
+            this.listViewLeft.Font = new System.Drawing.Font("Arial", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+            this.listViewLeft.ForeColor = System.Drawing.SystemColors.MenuText;
+            this.listViewLeft.ItemHeight = 15;
+            this.listViewLeft.Location = new System.Drawing.Point(28, 23);
+            this.listViewLeft.Name = "listViewLeft";
+            this.listViewLeft.Size = new System.Drawing.Size(137, 334);
+            this.listViewLeft.TabIndex = 2;
+            // 
+            // label2
+            // 
+            this.label2.AutoSize = true;
+            this.label2.Dock = System.Windows.Forms.DockStyle.Bottom;
+            this.label2.Font = new System.Drawing.Font("Arial", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+            this.label2.Location = new System.Drawing.Point(28, 5);
+            this.label2.Name = "label2";
+            this.label2.Size = new System.Drawing.Size(137, 15);
+            this.label2.TabIndex = 4;
+            this.label2.Text = "Available Devices";
+            // 
+            // label3
+            // 
+            this.label3.AutoSize = true;
+            this.label3.Dock = System.Windows.Forms.DockStyle.Bottom;
+            this.label3.Font = new System.Drawing.Font("Arial", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+            this.label3.Location = new System.Drawing.Point(231, 5);
+            this.label3.Name = "label3";
+            this.label3.Size = new System.Drawing.Size(137, 15);
+            this.label3.TabIndex = 5;
+            this.label3.Text = "Selected Devices";
+            // 
+            // tableLayoutPanel2
+            // 
+            this.tableLayoutPanel2.ColumnCount = 1;
+            this.tableLayoutPanel2.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F));
+            this.tableLayoutPanel2.Controls.Add(this.btnRight, 0, 1);
+            this.tableLayoutPanel2.Controls.Add(this.btnLeft, 0, 3);
+            this.tableLayoutPanel2.Font = new System.Drawing.Font("Arial", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+            this.tableLayoutPanel2.Location = new System.Drawing.Point(171, 23);
+            this.tableLayoutPanel2.Name = "tableLayoutPanel2";
+            this.tableLayoutPanel2.RowCount = 5;
+            this.tableLayoutPanel2.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 40.81633F));
+            this.tableLayoutPanel2.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 40F));
+            this.tableLayoutPanel2.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 18.36735F));
+            this.tableLayoutPanel2.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 40F));
+            this.tableLayoutPanel2.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 40.81633F));
+            this.tableLayoutPanel2.Size = new System.Drawing.Size(54, 334);
+            this.tableLayoutPanel2.TabIndex = 8;
+            // 
+            // btnRight
+            // 
+            this.btnRight.Anchor = System.Windows.Forms.AnchorStyles.Top;
+            this.btnRight.Font = new System.Drawing.Font("Arial", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+            this.btnRight.Location = new System.Drawing.Point(12, 106);
+            this.btnRight.Name = "btnRight";
+            this.btnRight.Size = new System.Drawing.Size(30, 30);
+            this.btnRight.TabIndex = 0;
+            this.btnRight.Text = ">>";
+            this.btnRight.UseVisualStyleBackColor = true;
+            this.btnRight.Click += new System.EventHandler(this.btnRight_Click);
+            // 
+            // btnLeft
+            // 
+            this.btnLeft.Anchor = System.Windows.Forms.AnchorStyles.Top;
+            this.btnLeft.Font = new System.Drawing.Font("Arial", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+            this.btnLeft.Location = new System.Drawing.Point(12, 192);
+            this.btnLeft.Name = "btnLeft";
+            this.btnLeft.Size = new System.Drawing.Size(30, 30);
+            this.btnLeft.TabIndex = 1;
+            this.btnLeft.Text = "<<";
+            this.btnLeft.UseVisualStyleBackColor = true;
+            this.btnLeft.Click += new System.EventHandler(this.btnLeft_Click);
+            // 
+            // btnExport
+            // 
+            this.btnExport.Anchor = System.Windows.Forms.AnchorStyles.Top;
+            this.btnExport.Font = new System.Drawing.Font("Arial", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+            this.btnExport.Location = new System.Drawing.Point(262, 368);
+            this.btnExport.Name = "btnExport";
+            this.btnExport.Size = new System.Drawing.Size(75, 23);
+            this.btnExport.TabIndex = 6;
+            this.btnExport.Text = "Export";
+            this.btnExport.UseVisualStyleBackColor = true;
+            this.btnExport.Click += new System.EventHandler(this.btnExport_Click);
+            // 
+            // btnCancel
+            // 
+            this.btnCancel.Anchor = System.Windows.Forms.AnchorStyles.Top;
+            this.btnCancel.Font = new System.Drawing.Font("Arial", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+            this.btnCancel.Location = new System.Drawing.Point(59, 368);
+            this.btnCancel.Name = "btnCancel";
+            this.btnCancel.Size = new System.Drawing.Size(75, 23);
+            this.btnCancel.TabIndex = 7;
+            this.btnCancel.Text = "Cancel";
+            this.btnCancel.UseVisualStyleBackColor = true;
+            this.btnCancel.Click += new System.EventHandler(this.btnCancel_Click);
+            // 
+            // tableLayoutPanel3
+            // 
+            this.tableLayoutPanel3.BackColor = System.Drawing.Color.White;
+            this.tableLayoutPanel3.ColumnCount = 3;
+            this.tableLayoutPanel3.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 20F));
+            this.tableLayoutPanel3.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F));
+            this.tableLayoutPanel3.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 20F));
+            this.tableLayoutPanel3.Controls.Add(this.label1, 1, 0);
+            this.tableLayoutPanel3.Dock = System.Windows.Forms.DockStyle.Top;
+            this.tableLayoutPanel3.Font = new System.Drawing.Font("Arial", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+            this.tableLayoutPanel3.Location = new System.Drawing.Point(0, 0);
+            this.tableLayoutPanel3.Name = "tableLayoutPanel3";
+            this.tableLayoutPanel3.RowCount = 1;
+            this.tableLayoutPanel3.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F));
+            this.tableLayoutPanel3.Size = new System.Drawing.Size(392, 26);
+            this.tableLayoutPanel3.TabIndex = 4;
+            // 
+            // label1
+            // 
+            this.label1.AutoSize = true;
+            this.label1.Dock = System.Windows.Forms.DockStyle.Bottom;
+            this.label1.Font = new System.Drawing.Font("Arial", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+            this.label1.Location = new System.Drawing.Point(23, 11);
+            this.label1.Name = "label1";
+            this.label1.Size = new System.Drawing.Size(346, 15);
+            this.label1.TabIndex = 4;
+            this.label1.Text = "Select Devices for Register Export";
+            this.label1.TextAlign = System.Drawing.ContentAlignment.TopCenter;
+            // 
+            // RegisterExportView
+            // 
+            this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
+            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+            this.Controls.Add(this.tableLayoutPanel1);
+            this.Controls.Add(this.tableLayoutPanel3);
+            this.Name = "RegisterExportView";
+            this.Size = new System.Drawing.Size(392, 441);
+            this.tableLayoutPanel1.ResumeLayout(false);
+            this.tableLayoutPanel1.PerformLayout();
+            this.tableLayoutPanel2.ResumeLayout(false);
+            this.tableLayoutPanel3.ResumeLayout(false);
+            this.tableLayoutPanel3.PerformLayout();
+            this.ResumeLayout(false);
+
+        }
+
+        #endregion
+
+        private System.Windows.Forms.TableLayoutPanel tableLayoutPanel1;
+        private System.Windows.Forms.ListBox listViewLeft;
+        private System.Windows.Forms.Label label2;
+        private MaximStyle.MaximButton btnExport;
+        private MaximStyle.MaximButton btnCancel;
+        private System.Windows.Forms.TableLayoutPanel tableLayoutPanel3;
+        private System.Windows.Forms.TableLayoutPanel tableLayoutPanel2;
+        private MaximStyle.MaximButton btnRight;
+        private MaximStyle.MaximButton btnLeft;
+        private System.Windows.Forms.Label label1;
+        private System.Windows.Forms.ListBox listViewRight;
+        private System.Windows.Forms.Label label3;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HspGuiSourceV301/HSPGui/CustomControls/RegisterExportView.cs	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,119 @@
+/*******************************************************************************
+* Copyright (C) 2016 Maxim Integrated Products, Inc., All rights Reserved.
+* 
+* This software is protected by copyright laws of the United States and
+* of foreign countries. This material may also be protected by patent laws
+* and technology transfer regulations of the United States and of foreign
+* countries. This software is furnished under a license agreement and/or a
+* nondisclosure agreement and may only be used or reproduced in accordance
+* with the terms of those agreements. Dissemination of this information to
+* any party or parties not specified in the license agreement and/or
+* nondisclosure agreement is expressly prohibited.
+*
+* The above copyright notice and this permission notice shall be included
+* in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+* OTHER DEALINGS IN THE SOFTWARE.
+*
+* Except as contained in this notice, the name of Maxim Integrated
+* Products, Inc. shall not be used except as stated in the Maxim Integrated
+* Products, Inc. Branding Policy.
+*
+* The mere transfer of this software does not imply any licenses
+* of trade secrets, proprietary technology, copyrights, patents,
+* trademarks, maskwork rights, or any other form of intellectual
+* property whatsoever. Maxim Integrated Products, Inc. retains all
+* ownership rights.
+*******************************************************************************
+*/
+
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Drawing;
+using System.Data;
+using System.Linq;
+using System.Text;
+using System.Windows.Forms;
+
+namespace HealthSensorPlatform.CustomControls
+{
+    public partial class RegisterExportView : UserControl
+    {
+        /* Constructors */
+        public RegisterExportView()
+        {
+            InitializeComponent();
+        }
+
+        /* Properties */
+        public ListBox.ObjectCollection ItemsLeft
+        {
+            get
+            {
+                return listViewLeft.Items;
+            }
+        }
+        public ListBox.ObjectCollection ItemsRight
+        {
+            get
+            {
+                return listViewRight.Items;
+            }
+        }
+
+        /* Events */
+        public event EventHandler<RegisterExportEventArgs> Complete;
+
+        /* Methods */
+        private void btnExport_Click(object sender, EventArgs e)
+        {
+            if (Complete != null)
+                Complete(this, new RegisterExportEventArgs() { Button = Button.Export });
+        }
+
+        private void btnCancel_Click(object sender, EventArgs e)
+        {
+            if (Complete != null)
+                Complete(this, new RegisterExportEventArgs() { Button = Button.Cancel });
+        }
+
+        private void btnRight_Click(object sender, EventArgs e)
+        {
+            if (listViewLeft.SelectedItem != null)
+            {
+                listViewRight.Items.Add(listViewLeft.SelectedItem);
+                listViewLeft.Items.Remove(listViewLeft.SelectedItem);
+            }
+        }
+
+        private void btnLeft_Click(object sender, EventArgs e)
+        {
+            if (listViewRight.SelectedItem != null)
+            {
+                listViewLeft.Items.Add(listViewRight.SelectedItem);
+                listViewRight.Items.Remove(listViewRight.SelectedItem);
+            }
+        }
+
+        /* Enum */
+        public enum Button
+        {
+            Export,
+            Cancel
+        }
+
+    }
+
+    public class RegisterExportEventArgs : EventArgs
+    {
+        public RegisterExportView.Button Button;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HspGuiSourceV301/HSPGui/CustomControls/RegisterExportView.resx	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,120 @@
+<?xml version="1.0" encoding="utf-8"?>
+<root>
+  <!-- 
+    Microsoft ResX Schema 
+    
+    Version 2.0
+    
+    The primary goals of this format is to allow a simple XML format 
+    that is mostly human readable. The generation and parsing of the 
+    various data types are done through the TypeConverter classes 
+    associated with the data types.
+    
+    Example:
+    
+    ... ado.net/XML headers & schema ...
+    <resheader name="resmimetype">text/microsoft-resx</resheader>
+    <resheader name="version">2.0</resheader>
+    <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+    <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+    <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
+    <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+    <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+        <value>[base64 mime encoded serialized .NET Framework object]</value>
+    </data>
+    <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+        <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
+        <comment>This is a comment</comment>
+    </data>
+                
+    There are any number of "resheader" rows that contain simple 
+    name/value pairs.
+    
+    Each data row contains a name, and value. The row also contains a 
+    type or mimetype. Type corresponds to a .NET class that support 
+    text/value conversion through the TypeConverter architecture. 
+    Classes that don't support this are serialized and stored with the 
+    mimetype set.
+    
+    The mimetype is used for serialized objects, and tells the 
+    ResXResourceReader how to depersist the object. This is currently not 
+    extensible. For a given mimetype the value must be set accordingly:
+    
+    Note - application/x-microsoft.net.object.binary.base64 is the format 
+    that the ResXResourceWriter will generate, however the reader can 
+    read any of the formats listed below.
+    
+    mimetype: application/x-microsoft.net.object.binary.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
+            : and then encoded with base64 encoding.
+    
+    mimetype: application/x-microsoft.net.object.soap.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+            : and then encoded with base64 encoding.
+
+    mimetype: application/x-microsoft.net.object.bytearray.base64
+    value   : The object must be serialized into a byte array 
+            : using a System.ComponentModel.TypeConverter
+            : and then encoded with base64 encoding.
+    -->
+  <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+    <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
+    <xsd:element name="root" msdata:IsDataSet="true">
+      <xsd:complexType>
+        <xsd:choice maxOccurs="unbounded">
+          <xsd:element name="metadata">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" />
+              </xsd:sequence>
+              <xsd:attribute name="name" use="required" type="xsd:string" />
+              <xsd:attribute name="type" type="xsd:string" />
+              <xsd:attribute name="mimetype" type="xsd:string" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="assembly">
+            <xsd:complexType>
+              <xsd:attribute name="alias" type="xsd:string" />
+              <xsd:attribute name="name" type="xsd:string" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="data">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+                <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
+              <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+              <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="resheader">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" />
+            </xsd:complexType>
+          </xsd:element>
+        </xsd:choice>
+      </xsd:complexType>
+    </xsd:element>
+  </xsd:schema>
+  <resheader name="resmimetype">
+    <value>text/microsoft-resx</value>
+  </resheader>
+  <resheader name="version">
+    <value>2.0</value>
+  </resheader>
+  <resheader name="reader">
+    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <resheader name="writer">
+    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+</root>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HspGuiSourceV301/HSPGui/CustomControls/RegisterView.cs	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,765 @@
+/*******************************************************************************
+* Copyright (C) 2016 Maxim Integrated Products, Inc., All rights Reserved.
+* 
+* This software is protected by copyright laws of the United States and
+* of foreign countries. This material may also be protected by patent laws
+* and technology transfer regulations of the United States and of foreign
+* countries. This software is furnished under a license agreement and/or a
+* nondisclosure agreement and may only be used or reproduced in accordance
+* with the terms of those agreements. Dissemination of this information to
+* any party or parties not specified in the license agreement and/or
+* nondisclosure agreement is expressly prohibited.
+*
+* The above copyright notice and this permission notice shall be included
+* in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+* OTHER DEALINGS IN THE SOFTWARE.
+*
+* Except as contained in this notice, the name of Maxim Integrated
+* Products, Inc. shall not be used except as stated in the Maxim Integrated
+* Products, Inc. Branding Policy.
+*
+* The mere transfer of this software does not imply any licenses
+* of trade secrets, proprietary technology, copyrights, patents,
+* trademarks, maskwork rights, or any other form of intellectual
+* property whatsoever. Maxim Integrated Products, Inc. retains all
+* ownership rights.
+*******************************************************************************
+*/
+
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Drawing;
+using System.Data;
+using System.Linq;
+using System.Text;
+using System.Text.RegularExpressions;
+using System.Windows.Forms;
+using System.IO;
+
+using HealthSensorPlatform.DeviceDescriptions;
+using HealthSensorPlatform.CustomControls;
+using RPCSupport.DeviceSupport;
+//using Maxim.MAX30101GUI.DeviceDescriptions;
+//using Maxim.MAX30101;
+
+namespace Maxim.CustomControls
+{
+    public partial class RegisterView : UserControl, IDeviceView
+    {
+        private bool connected = false;
+        public bool Connected
+        {
+            get
+            {
+                return connected;
+            }
+            set 
+            {
+                connected = value;
+            }
+        }
+
+        public string DeviceName;
+
+        public DeviceController Controller
+        {
+            get { return controller; }
+        }
+        private DeviceController controller;
+
+
+        /// <summary>
+        /// Value of current selected register 
+        /// </summary>
+        int RegisterValue;
+
+        Label[] bitLabels = new Label[24];
+        
+        Font RegularFont;
+        Font BoldFont;
+
+        public event RegisterWriteCompleteHandler RegisterWriteComplete;
+        public delegate void RegisterWriteCompleteHandler(object sender, RegisterArgs e);
+
+        public event CellBeginEditHandler CellBeginEdit;
+        public delegate void CellBeginEditHandler(object sender, DataGridViewCellCancelEventArgs e);
+
+        public RegisterView()
+        {
+            //accelDevice = new AccelDevice();
+            InitializeComponent();
+
+            // Initialize font styles for label
+            RegularFont = new Font(lblBit00.Font, FontStyle.Regular); 
+            BoldFont = new Font(lblBit00.Font, FontStyle.Bold);
+
+            // References to all bit labels
+            for(int i = 0; i < 24; i++)
+            {
+                string labelName = "lblBit" + i.ToString("D2");
+                bitLabels[i] = (Label)panelRegisterBits.Controls[labelName];
+            }
+
+            dgv_Registers.CellBeginEdit += OnCellBeginEdit; // Pass thru event
+            dgv_Registers.SelectionChanged += dgv_Registers_SelectionChanged;
+            dgv_Registers.CellEndEdit += dgv_Registers_CellEndEdit;
+        }
+
+        public void SetController(DeviceController controller)
+        {
+            Clear();
+            this.controller = controller;
+        }
+
+        /// <summary>
+        /// RegisterInfo register value to string
+        /// </summary>
+        /// <param name="reg"></param>
+        /// <returns></returns>
+        private string FormatData(RegisterInfo reg)
+        {
+            return reg.dataField.ToString("X" + (reg.numBytes * 2).ToString());
+        }
+
+        /// <summary>
+        /// Populate register tables
+        /// </summary>
+        public void DisplayRegisters()
+        {
+            if (dgv_Registers.RowCount == 0)
+            {
+                //add rows to table
+                foreach (RegisterInfo reg in controller.InfoArray)
+                {
+                    //get the number of bytes of the register
+                    int numBytes = reg.numBytes;
+
+                    String dataStr = FormatData(reg);
+                    //add a row to the table with the register address, name, and value
+                    dgv_Registers.Rows.Add(reg.address.ToString("X2") + "h", reg.detailedName, dataStr);
+                }
+                
+                //resize length of table to the number of rows
+                if (dgv_Registers.RowCount > 8)
+                {
+                    dgv_Registers.Height = (dgv_Registers.RowCount - 1) * 23 + 42;
+                    dgv_RegDes.Height = dgv_Registers.Height;
+                }
+                else
+                {
+                    dgv_Registers.Height = 7 * 23 + 42;
+                    dgv_RegDes.Height = dgv_Registers.Height;
+                }
+            }
+            else //the table has already been populated with rows
+            {
+                //update the value column with the new value in the ADC registers
+                for (int i = 0; i < dgv_Registers.Rows.Count; i++)
+                {
+                    RegisterInfo reg = controller.InfoArray[i];
+                    int numBytes = reg.numBytes;
+                    String dataStr = FormatData(reg);
+                    //add a row to the table with the register address, name, and value
+                    dgv_Registers[col_Value.Index, i].Value = dataStr;
+                }
+            }
+        }
+
+        public void Clear()
+        {
+            dgv_Registers.Rows.Clear();
+            dgv_Registers.Refresh();
+        }
+
+        public string RegistersToString()
+        {
+            //RegisterProcess registerProcess;
+            StringBuilder sb = new StringBuilder();
+            string dataStr;
+            string[][] bitDescriptions;
+            int longestRow;
+
+            //registerProcess = new RegisterProcess(controller.InfoArray);
+            
+            bitDescriptions = new string[controller.InfoArray.Length + 4][];
+
+            UpdateRegisterIndexWidth();
+
+            // Generate register data to string
+            for (int i = 0; i < controller.InfoArray.Length; i++)
+            {
+                RegisterInfo reg = controller.InfoArray[i];
+
+                bitDescriptions[i] = new string[reg.description.list.Count];
+
+                for (int k = 0; k < reg.description.list.Count; k++)
+                {
+                    RegisterBitDescriptions.RegisterBitDescription b = reg.description.list[k];
+                    int bitValue = (reg.dataField >> b.Index) & ((1 << b.Width) - 1); // MAX30001 only
+                    bitDescriptions[i][k] = b.name + " = " + bitValue.ToString("X") + "h";
+                }
+            }
+
+            // Find longest row for how deep to loop to print out all registers bits
+            longestRow = controller.InfoArray.Length + 1;
+            for (int j = 0; j < controller.InfoArray.Length; j++ )
+            {
+                if (controller.InfoArray[j].description.list.Count > longestRow)
+                {
+                    longestRow = controller.InfoArray[j].description.list.Count + 1;
+                }
+            }
+
+            for (int i = 0; i < longestRow; i++)
+            {
+                if (i < controller.InfoArray.Length) // register map
+                {
+                    RegisterInfo reg = controller.InfoArray[i];
+
+                    dataStr = FormatData(reg);
+
+                    sb.Append(this.DeviceName);
+                    sb.Append(", ");
+                    sb.Append(reg.address.ToString("X2"));
+                    sb.Append("h, ");
+                    sb.Append(reg.detailedName);
+                    sb.Append(", ");
+                    sb.Append(dataStr);
+                    sb.Append("h");
+                    sb.Append(", ");
+                    sb.Append(", ");
+                }
+                else // finished with register map, just have descriptions
+                {
+                    sb.Append(", ");
+                    sb.Append(", ");
+                    sb.Append(", ");
+                    sb.Append(", ");
+                    sb.Append(", ");
+                }
+
+                if (i == 0) // Register name and values
+                {
+                    for (int k = 0; k < controller.InfoArray.Length; k++)
+                    {
+                        if (controller.InfoArray[k].type != RegisterInfo.RegisterType.WriteOnly)
+                        {
+                            sb.Append(controller.InfoArray[k].name);
+                            sb.Append(" = ");
+                            sb.Append(FormatData(controller.InfoArray[k]));
+                            sb.Append("h");
+                            sb.Append(", ");
+                        }
+                    }
+                }
+                else // descriptions
+                {
+                    for (int k = 0; k < controller.InfoArray.Length; k++)
+                    {
+                        if (controller.InfoArray[k].type != RegisterInfo.RegisterType.WriteOnly)
+                        {
+                            if (i - 1 < bitDescriptions[k].Length)
+                            {
+                                sb.Append(bitDescriptions[k][i - 1]);
+                            }
+                            sb.Append(',');
+                        }
+                    }
+                }
+                sb.Append(Environment.NewLine);
+            }
+
+            /*
+            foreach(RegisterInfo reg in controller.InfoArray)
+            {
+                if (reg.address == 1 || reg.address == 8 || reg.address == 9 || reg.address == 10)
+                    continue;
+
+                sb.Append("% ");
+                sb.Append(reg.name);
+                sb.Append(" (");
+                sb.Append(reg.address.ToString("X2"));
+                sb.Append("h)");
+                sb.Append(" = ");
+                sb.Append(FormatData(reg));
+                sb.Append("h\n");
+
+                foreach(RegisterBitDescriptions.RegisterBitDescription b in reg.description.list)
+                {
+                    int bitValue = (RegisterData(reg) >> b.Index) & ((1 << b.Width) - 1); // MAX30001 only
+                    sb.Append("% ");
+                    sb.Append(b.name);
+                    sb.Append(" = ");
+                    sb.Append(bitValue.ToString("X"));
+                    sb.Append("h\n");
+                }
+            }
+            */
+            return sb.ToString().TrimEnd(Environment.NewLine.ToCharArray());
+        }
+
+        /// <summary>
+        /// Register selection change display register description and update display bits
+        /// </summary>
+        /// <param name="sender"></param>
+        /// <param name="e"></param>
+        private void dgv_Registers_SelectionChanged(object sender, EventArgs e)
+        {
+            UpdateRegisters();
+        }
+
+        private void UpdateRegisters()
+        {
+            //get the index of the row selected
+            int row = dgv_Registers.CurrentRow.Index;
+
+            //make sure there is bit description info and then display it
+            if (controller.InfoArray[row].description != null)
+            {
+                lbl_bitDes.Text = "Bit Description: " + controller.InfoArray[row].name + " Register";
+                UpdateRegisterDesTable(controller.InfoArray[row].description);
+                RegisterValue = Int32.Parse((string)(dgv_Registers[2, row].Value), System.Globalization.NumberStyles.HexNumber);
+                UpdateRegisterBits(controller.InfoArray[row].description, RegisterValue);
+            }
+        }
+
+        /// <summary>
+        /// Fill register description table
+        /// </summary>
+        /// <param name="bitsDes"></param>
+        public void UpdateRegisterDesTable(RegisterBitDescriptions bitsDes)
+        {
+            //int numBits = bitsDes.Count;
+
+            dgv_RegDes.Rows.Clear();
+
+            foreach (RegisterBitDescriptions.RegisterBitDescription b in bitsDes.list)
+            {
+                dgv_RegDes.Rows.Add(b.bit, b.name, b.description);
+            }
+
+        }
+
+        public void UpdateRegisterBits()
+        {
+            int row;
+
+            if (dgv_Registers.CurrentRow != null)
+            {
+                row = dgv_Registers.CurrentRow.Index;
+
+                if (controller.InfoArray[row].description != null)
+                {
+                    RegisterValue = Int32.Parse((string)(dgv_Registers[2, row].Value), System.Globalization.NumberStyles.HexNumber);
+                    UpdateRegisterBits(controller.InfoArray[row].description, RegisterValue);
+                }
+            }
+        }
+
+        public void UpdateRegisterIndexWidth()
+        {
+            RegisterInfo[] info = controller.InfoArray;
+
+            foreach(RegisterInfo regInfo in info) // Registers
+            {
+                foreach (RegisterBitDescriptions.RegisterBitDescription b in regInfo.description.list) // Bits
+                {
+                    string[] numbers = Regex.Split(b.bit, @"\D+"); // Bits [20:17]
+                    string registerBitName;
+                    int number1 = -1;
+                    int number2 = -1;
+
+                    // Find Bit Range
+                    foreach (string value in numbers)
+                    {
+                        if (value != String.Empty)
+                        {
+                            if (number1 == -1) // First number found
+                                number1 = Int32.Parse(value);
+                            else // Second number found
+                                number2 = Int32.Parse(value);
+                        }
+                    }
+
+                    if (number2 == -1) // Single Number: single bit field (example: Bit 20)
+                    {
+                        b.Width = 1;
+                        b.Index = number1;
+                    }
+                    else // Multiple Bits: multiple bit field (example: Bit [20:17])
+                    {
+                        registerBitName = Regex.Replace(b.name, @"\[\d+:\d+\]", String.Empty); // Remove [#.#] from bit field name
+
+                        for (int i = number1; i >= number2; i--)
+                        {
+                            bitLabels[i].Text = registerBitName + "[" + (i - number2) + "]"; // Calculate bit field number
+                        }
+
+                        b.Index = number2;
+                        b.Width = number1 - number2 + 1; 
+
+                    }
+                }
+            }
+        }
+
+        /// <summary>
+        /// Fill bit table
+        /// </summary>
+        /// <param name="bitDes"></param>
+        /// <param name="regValue"></param>
+        public void UpdateRegisterBits(RegisterBitDescriptions bitDes, int regValue)
+        {
+            // Reset Bit State
+            for (int i = 0; i < 24; i++ )
+            {
+                bitLabels[i].Text = "-";
+
+                // Set label based on bit state
+                if (((regValue >> i) & 0x01) == 0x01)
+                    bitLabels[i].Font = BoldFont;
+                else
+                    bitLabels[i].Font = RegularFont;
+            }
+
+            foreach (RegisterBitDescriptions.RegisterBitDescription b in bitDes.list)
+            {
+                string[] numbers = Regex.Split(b.bit, @"\D+"); // Bits [20:17]
+                string registerBitName;
+                int number1 = -1;
+                int number2 = -1;
+
+                // Find Bit Range
+                foreach (string value in numbers)
+                {
+                    if (value != String.Empty)
+                    {
+                        if (number1 == -1) // First number found
+                            number1 = Int32.Parse(value);
+                        else // Second number found
+                            number2 = Int32.Parse(value);
+                    }
+                }
+
+                if (number2 == -1) // Single Number: single bit field (example: Bit 20)
+                {
+                    bitLabels[number1].Text = b.name;
+                }
+                else // Multiple Bits: multiple bit field (example: Bit [20:17])
+                {
+                    registerBitName = Regex.Replace(b.name, @"\[\d+:\d+\]", String.Empty); // Remove [#.#] from bit field name
+
+                    for (int i = number1; i >= number2; i--)
+                    {
+                        bitLabels[i].Text = registerBitName + "[" + (i - number2) + "]"; // Calculate bit field number
+                    }
+                    
+                }
+            }
+        }
+
+        /// <summary>
+        /// Parse user input and write register
+        /// </summary>
+        /// <param name="sender"></param>
+        /// <param name="e"></param>
+        private void dgv_Registers_CellEndEdit(object sender, DataGridViewCellEventArgs e)
+        {
+            //check if hardware is connected
+            //if (online && !COMMConnected())
+            //    return;
+
+            RegisterInfo reg = controller.InfoArray[e.RowIndex];
+            byte address = (byte)reg.address;
+            byte numBytes = (byte)reg.numBytes;
+
+            int[] data = reg.data;
+
+            string value = (string)dgv_Registers[col_Value.Index, e.RowIndex].Value;
+            string error = ValidateHexValue(value, numBytes);
+
+            if (error == "Valid")
+            {
+                //erase error text if one exist
+                if (dgv_Registers[col_Value.Index, e.RowIndex].ErrorText != String.Empty)
+                    dgv_Registers[col_Value.Index, e.RowIndex].ErrorText = String.Empty;
+
+                //convert string hex to number hex
+                int hex = Int32.Parse(value, System.Globalization.NumberStyles.HexNumber);
+
+                //write value back to GUI with correct number of characters
+                dgv_Registers[col_Value.Index, e.RowIndex].Value = hex.ToString("X" + numBytes * 2);
+
+                WriteRegister(reg, hex);
+
+                if (RegisterWriteComplete != null)
+                {
+                    RegisterWriteComplete(this, new RegisterArgs { Register = address });
+                }
+
+            }
+            else//value is not valid
+            {
+                byte zero = 0;
+                dgv_Registers[col_Value.Index, e.RowIndex].Value = zero.ToString("X" + numBytes * 2); //enter zeros with correct number of characters
+                dgv_Registers[col_Value.Index, e.RowIndex].ErrorText = error;    //add error text
+            }
+
+            UpdateRegisters();
+        }
+
+        /// <summary>
+        /// Write data to register
+        /// </summary>
+        /// <param name="reg"></param>
+        /// <param name="hex"></param>
+        public void WriteRegister(RegisterInfo reg, int hex)
+        {
+            byte numBytes = (byte)reg.numBytes;
+            int[] data = reg.data;
+
+            switch (numBytes)
+            {
+                case 4:
+                    data[0] = (byte)(hex >> 24);
+                    data[1] = (byte)(hex >> 16);
+                    data[2] = (byte)(hex >> 8);
+                    data[3] = (byte)hex;
+                    break;
+                case 3:
+                    hex &= 0x00FFFFFF;//clear bits not used
+                    data[0] = (byte)(hex >> 16);
+                    data[1] = (byte)(hex >> 8);
+                    data[2] = (byte)hex;
+                    break;
+                case 2:
+                    hex &= 0x0000FFFF;//clear bits not used
+                    data[0] = (byte)(hex >> 8);
+                    data[1] = (byte)hex;
+                    break;
+                case 1:
+                    hex &= 0x000000FF;//clear bits not used
+                    data[0] = (byte)hex;
+                    break;
+            }
+            controller.WriteRegister(reg);
+        }
+
+        /// <summary>
+        /// Verify hex
+        /// </summary>
+        /// <param name="value"></param>
+        /// <param name="numBytes"></param>
+        /// <returns></returns>
+        public String ValidateHexValue(String value, byte numBytes)
+        {
+            char[] character = new char[numBytes * 2];
+            String error = "Valid";
+
+            if (value == null)
+            {
+                error = "Empty Value";
+                return error;
+            }
+
+            //check to see if too many characters were entered
+            if (value.Length > numBytes * 2)
+                error = "Too many characters";
+            else
+            {
+                character = value.ToCharArray();    //split string into character array
+
+                for (int i = 0; i < value.Length; i++)
+                {
+                    if (Char.IsLetterOrDigit(character[i])) //check for letter and digits
+                    {
+                        if (Char.IsLower(character[i]))
+                            character[i] = Char.ToUpper(character[i]); //changed letter to upper case
+
+                        //check A-F
+                        if (character[i] > 'F')
+                            error = "Invalid Letter";
+                    }
+                    else
+                        error = "Invalid Character";
+                }
+            }
+            return error;
+        }
+
+        public void WriteAll()
+        {
+            if (Connected)
+                controller.WriteAll();
+            DisplayRegisters();
+        }
+
+        /// <summary>
+        /// Read all button handler
+        /// </summary>
+        /// <param name="sender"></param>
+        /// <param name="e"></param>
+        private void btn_ReadAll_Click(object sender, EventArgs e)
+        {
+            ReadAll();
+        }
+
+        /// <summary>
+        /// Read all registers and display results
+        /// </summary>
+        public void ReadAll()
+        {
+            if (Connected)
+                controller.ReadAll();
+            DisplayRegisters();
+            UpdateRegisterBits();
+        }
+
+        public RegisterInfo RegisterAddress(int address)
+        {
+            for(int i = 0; i < controller.InfoArray.Length; i++)
+            {
+                if (controller.InfoArray[i].address == address)
+                    return controller.InfoArray[i];
+            }
+
+            return null;
+        }
+
+        /// <summary>
+        /// Read register handler
+        /// </summary>
+        /// <param name="sender"></param>
+        /// <param name="e"></param>
+        private void btnRead_Click(object sender, EventArgs e)
+        {
+            if (connected)
+            {
+                controller.ReadRegister(controller.InfoArray[dgv_Registers.SelectedRows[0].Index]);
+                DisplayRegisters();
+                UpdateRegisterBits();
+            }
+        }
+
+        /// <summary>
+        /// Toggle register bit handler
+        /// </summary>
+        /// <param name="sender"></param>
+        /// <param name="e"></param>
+        private void lblBit_Click(object sender, EventArgs e)
+        {
+            Label lbl = (Label)sender;
+
+            string[] number = Regex.Split(lbl.Name, @"\D+");
+
+            if (lbl.Font.Bold == true)
+                lbl.Font = RegularFont;
+            else
+                lbl.Font = BoldFont;
+
+            foreach(string value in number)
+            {
+                if (value != String.Empty)
+                {
+                    int bitNumber = Int32.Parse(value);
+
+                    RegisterValue &= ~(1 << bitNumber); // clear bit
+                    RegisterValue |= ((lbl.Font.Bold == true ? 1 : 0) << bitNumber); // set bit
+                }
+            }
+        }
+
+        /// <summary>
+        /// Write register button handler
+        /// </summary>
+        /// <param name="sender"></param>
+        /// <param name="e"></param>
+        private void btnWrite_Click(object sender, EventArgs e)
+        {
+            if (connected)
+            {
+                WriteRegister(controller.InfoArray[dgv_Registers.SelectedRows[0].Index], RegisterValue);
+                controller.ReadRegister(controller.InfoArray[dgv_Registers.SelectedRows[0].Index]);
+                DisplayRegisters();
+            }
+        }
+
+        /// <summary>
+        /// On cell begin edit
+        /// </summary>
+        /// <param name="sender"></param>
+        /// <param name="e"></param>
+        private void OnCellBeginEdit(object sender, DataGridViewCellCancelEventArgs e)
+        {
+            if (CellBeginEdit != null)
+            {
+                CellBeginEdit(sender, e);
+            }
+        } 
+
+        private void DataGridViewColumns(DataGridView listview, SizeF factor)
+        {
+            foreach (DataGridViewColumn column in listview.Columns)
+            {
+                column.Width = (int)Math.Round(column.Width * factor.Width);
+            }
+        }
+
+        protected override void ScaleControl(SizeF factor, BoundsSpecified specified)
+        {
+            base.ScaleControl(factor, specified);
+            DataGridViewColumns(dgv_RegDes, factor);
+            DataGridViewColumns(dgv_Registers, factor);
+        }
+        /*
+        public class RegisterProcess
+        {
+            RegisterBit[][] Data;
+
+            public RegisterProcess(RegisterInfo[] info)
+            {
+                Data = new RegisterBit[info.Length][];
+				
+				for (int i = 0; i < info.Length; i++)
+				{
+					Data[i] = new RegisterBit[info[i].description.list.Count];
+					
+					for (int j = 0; j < info[i].description.list.Count; j++)
+					{
+						int fieldValue;
+                        fieldValue = (info[i].dataField >> info[i].description.list[j].Index) & info[i].description.list[j].Width;
+						Data[i][j] = new RegisterBit(info[i].description.list[j].name, fieldValue);
+					}
+				}
+            }
+
+            class RegisterBit
+            {
+                string Name;
+                int Data;
+				
+				public RegisterBit(string name, int data)
+				{
+					Name = name;
+					Data = data;
+				}
+            }
+        }
+        */
+
+        public class RegisterArgs : EventArgs
+        {
+            public int Register;
+        }
+
+
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HspGuiSourceV301/HSPGui/CustomControls/RegisterView.designer.cs	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,922 @@
+namespace Maxim.CustomControls
+{
+    partial class RegisterView
+    {
+        /// <summary> 
+        /// Required designer variable.
+        /// </summary>
+        private System.ComponentModel.IContainer components = null;
+
+        /// <summary> 
+        /// Clean up any resources being used.
+        /// </summary>
+        /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
+        protected override void Dispose(bool disposing)
+        {
+            if (disposing && (components != null))
+            {
+                components.Dispose();
+            }
+            base.Dispose(disposing);
+        }
+
+        #region Component Designer generated code
+
+        /// <summary> 
+        /// Required method for Designer support - do not modify 
+        /// the contents of this method with the code editor.
+        /// </summary>
+        private void InitializeComponent()
+        {
+            System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle21 = new System.Windows.Forms.DataGridViewCellStyle();
+            System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle22 = new System.Windows.Forms.DataGridViewCellStyle();
+            System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle24 = new System.Windows.Forms.DataGridViewCellStyle();
+            System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle23 = new System.Windows.Forms.DataGridViewCellStyle();
+            System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle25 = new System.Windows.Forms.DataGridViewCellStyle();
+            System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle29 = new System.Windows.Forms.DataGridViewCellStyle();
+            System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle30 = new System.Windows.Forms.DataGridViewCellStyle();
+            System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle26 = new System.Windows.Forms.DataGridViewCellStyle();
+            System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle27 = new System.Windows.Forms.DataGridViewCellStyle();
+            System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle28 = new System.Windows.Forms.DataGridViewCellStyle();
+            this.tableLayoutPanelRegisters = new System.Windows.Forms.TableLayoutPanel();
+            this.btn_ReadAll = new MaximStyle.MaximButton();
+            this.panel1 = new System.Windows.Forms.Panel();
+            this.dgv_Registers = new System.Windows.Forms.DataGridView();
+            this.col_Address = new System.Windows.Forms.DataGridViewTextBoxColumn();
+            this.col_Register = new System.Windows.Forms.DataGridViewTextBoxColumn();
+            this.col_Value = new System.Windows.Forms.DataGridViewTextBoxColumn();
+            this.dgv_RegDes = new System.Windows.Forms.DataGridView();
+            this.col_bit = new System.Windows.Forms.DataGridViewTextBoxColumn();
+            this.dataGridViewTextBoxColumn3 = new System.Windows.Forms.DataGridViewTextBoxColumn();
+            this.col_Des = new System.Windows.Forms.DataGridViewTextBoxColumn();
+            this.lbl_bitDes = new System.Windows.Forms.Label();
+            this.lbl_Note = new System.Windows.Forms.Label();
+            this.lblHeader7 = new System.Windows.Forms.Label();
+            this.lblHeader6 = new System.Windows.Forms.Label();
+            this.lblHeader5 = new System.Windows.Forms.Label();
+            this.lblHeader4 = new System.Windows.Forms.Label();
+            this.lblHeader3 = new System.Windows.Forms.Label();
+            this.lblHeader2 = new System.Windows.Forms.Label();
+            this.lblHeader1 = new System.Windows.Forms.Label();
+            this.lblHeader0 = new System.Windows.Forms.Label();
+            this.lblBit23 = new System.Windows.Forms.Label();
+            this.lblBit22 = new System.Windows.Forms.Label();
+            this.lblBit21 = new System.Windows.Forms.Label();
+            this.lblBit20 = new System.Windows.Forms.Label();
+            this.lblBit19 = new System.Windows.Forms.Label();
+            this.lblBit18 = new System.Windows.Forms.Label();
+            this.lblBit17 = new System.Windows.Forms.Label();
+            this.lblBit16 = new System.Windows.Forms.Label();
+            this.lblBit15 = new System.Windows.Forms.Label();
+            this.lblBit14 = new System.Windows.Forms.Label();
+            this.lblBit13 = new System.Windows.Forms.Label();
+            this.lblBit12 = new System.Windows.Forms.Label();
+            this.lblBit11 = new System.Windows.Forms.Label();
+            this.lblBit10 = new System.Windows.Forms.Label();
+            this.lblBit09 = new System.Windows.Forms.Label();
+            this.lblBit08 = new System.Windows.Forms.Label();
+            this.panelRegisterBits = new System.Windows.Forms.Panel();
+            this.label1 = new System.Windows.Forms.Label();
+            this.btnWrite = new MaximStyle.MaximButton();
+            this.btnRead = new MaximStyle.MaximButton();
+            this.lblBit07 = new System.Windows.Forms.Label();
+            this.lblBit06 = new System.Windows.Forms.Label();
+            this.lblBit05 = new System.Windows.Forms.Label();
+            this.lblBit04 = new System.Windows.Forms.Label();
+            this.lblBit03 = new System.Windows.Forms.Label();
+            this.lblBit02 = new System.Windows.Forms.Label();
+            this.lblBit01 = new System.Windows.Forms.Label();
+            this.lblBit00 = new System.Windows.Forms.Label();
+            this.tableLayoutPanel1 = new System.Windows.Forms.TableLayoutPanel();
+            this.tableLayoutPanel2 = new System.Windows.Forms.TableLayoutPanel();
+            this.panel2 = new System.Windows.Forms.Panel();
+            this.tableLayoutPanelRegisters.SuspendLayout();
+            this.panel1.SuspendLayout();
+            ((System.ComponentModel.ISupportInitialize)(this.dgv_Registers)).BeginInit();
+            ((System.ComponentModel.ISupportInitialize)(this.dgv_RegDes)).BeginInit();
+            this.panelRegisterBits.SuspendLayout();
+            this.SuspendLayout();
+            // 
+            // tableLayoutPanelRegisters
+            // 
+            this.tableLayoutPanelRegisters.BackColor = System.Drawing.Color.White;
+            this.tableLayoutPanelRegisters.ColumnCount = 2;
+            this.tableLayoutPanelRegisters.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 300F));
+            this.tableLayoutPanelRegisters.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F));
+            this.tableLayoutPanelRegisters.Controls.Add(this.btn_ReadAll, 0, 0);
+            this.tableLayoutPanelRegisters.Controls.Add(this.panel1, 0, 1);
+            this.tableLayoutPanelRegisters.Controls.Add(this.dgv_RegDes, 1, 1);
+            this.tableLayoutPanelRegisters.Controls.Add(this.lbl_bitDes, 1, 0);
+            this.tableLayoutPanelRegisters.Controls.Add(this.lbl_Note, 0, 2);
+            this.tableLayoutPanelRegisters.Dock = System.Windows.Forms.DockStyle.Fill;
+            this.tableLayoutPanelRegisters.Location = new System.Drawing.Point(0, 30);
+            this.tableLayoutPanelRegisters.Name = "tableLayoutPanelRegisters";
+            this.tableLayoutPanelRegisters.Padding = new System.Windows.Forms.Padding(4);
+            this.tableLayoutPanelRegisters.RowCount = 3;
+            this.tableLayoutPanelRegisters.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 7.878448F));
+            this.tableLayoutPanelRegisters.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 87.11311F));
+            this.tableLayoutPanelRegisters.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 5.008441F));
+            this.tableLayoutPanelRegisters.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 20F));
+            this.tableLayoutPanelRegisters.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 20F));
+            this.tableLayoutPanelRegisters.Size = new System.Drawing.Size(894, 348);
+            this.tableLayoutPanelRegisters.TabIndex = 7;
+            // 
+            // btn_ReadAll
+            // 
+            this.btn_ReadAll.Anchor = System.Windows.Forms.AnchorStyles.Left;
+            this.btn_ReadAll.Location = new System.Drawing.Point(7, 7);
+            this.btn_ReadAll.Name = "btn_ReadAll";
+            this.btn_ReadAll.Size = new System.Drawing.Size(120, 20);
+            this.btn_ReadAll.TabIndex = 0;
+            this.btn_ReadAll.Text = "Read All";
+            this.btn_ReadAll.UseVisualStyleBackColor = true;
+            this.btn_ReadAll.Click += new System.EventHandler(this.btn_ReadAll_Click);
+            // 
+            // panel1
+            // 
+            this.panel1.AutoScroll = true;
+            this.panel1.Controls.Add(this.dgv_Registers);
+            this.panel1.Dock = System.Windows.Forms.DockStyle.Fill;
+            this.panel1.Location = new System.Drawing.Point(7, 33);
+            this.panel1.Name = "panel1";
+            this.panel1.Size = new System.Drawing.Size(294, 290);
+            this.panel1.TabIndex = 5;
+            // 
+            // dgv_Registers
+            // 
+            this.dgv_Registers.AllowUserToAddRows = false;
+            this.dgv_Registers.AllowUserToDeleteRows = false;
+            this.dgv_Registers.AllowUserToResizeColumns = false;
+            this.dgv_Registers.AllowUserToResizeRows = false;
+            dataGridViewCellStyle21.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(221)))), ((int)(((byte)(221)))), ((int)(((byte)(221)))));
+            this.dgv_Registers.AlternatingRowsDefaultCellStyle = dataGridViewCellStyle21;
+            this.dgv_Registers.BackgroundColor = System.Drawing.Color.White;
+            this.dgv_Registers.BorderStyle = System.Windows.Forms.BorderStyle.Fixed3D;
+            dataGridViewCellStyle22.Alignment = System.Windows.Forms.DataGridViewContentAlignment.MiddleCenter;
+            dataGridViewCellStyle22.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(221)))), ((int)(((byte)(221)))), ((int)(((byte)(221)))));
+            dataGridViewCellStyle22.Font = new System.Drawing.Font("Arial", 9F);
+            dataGridViewCellStyle22.WrapMode = System.Windows.Forms.DataGridViewTriState.True;
+            this.dgv_Registers.ColumnHeadersDefaultCellStyle = dataGridViewCellStyle22;
+            this.dgv_Registers.ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize;
+            this.dgv_Registers.Columns.AddRange(new System.Windows.Forms.DataGridViewColumn[] {
+            this.col_Address,
+            this.col_Register,
+            this.col_Value});
+            dataGridViewCellStyle24.Alignment = System.Windows.Forms.DataGridViewContentAlignment.MiddleLeft;
+            dataGridViewCellStyle24.BackColor = System.Drawing.SystemColors.Window;
+            dataGridViewCellStyle24.Font = new System.Drawing.Font("Arial", 9F);
+            dataGridViewCellStyle24.ForeColor = System.Drawing.Color.Black;
+            dataGridViewCellStyle24.SelectionBackColor = System.Drawing.Color.FromArgb(((int)(((byte)(0)))), ((int)(((byte)(178)))), ((int)(((byte)(169)))));
+            dataGridViewCellStyle24.SelectionForeColor = System.Drawing.SystemColors.HighlightText;
+            dataGridViewCellStyle24.WrapMode = System.Windows.Forms.DataGridViewTriState.False;
+            this.dgv_Registers.DefaultCellStyle = dataGridViewCellStyle24;
+            this.dgv_Registers.Dock = System.Windows.Forms.DockStyle.Fill;
+            this.dgv_Registers.Location = new System.Drawing.Point(0, 0);
+            this.dgv_Registers.Margin = new System.Windows.Forms.Padding(3, 4, 3, 4);
+            this.dgv_Registers.MultiSelect = false;
+            this.dgv_Registers.Name = "dgv_Registers";
+            this.dgv_Registers.RowHeadersVisible = false;
+            this.dgv_Registers.RowHeadersWidthSizeMode = System.Windows.Forms.DataGridViewRowHeadersWidthSizeMode.DisableResizing;
+            this.dgv_Registers.ScrollBars = System.Windows.Forms.ScrollBars.Vertical;
+            this.dgv_Registers.SelectionMode = System.Windows.Forms.DataGridViewSelectionMode.FullRowSelect;
+            this.dgv_Registers.Size = new System.Drawing.Size(294, 290);
+            this.dgv_Registers.StandardTab = true;
+            this.dgv_Registers.TabIndex = 1;
+            this.dgv_Registers.SelectionChanged += new System.EventHandler(this.dgv_Registers_SelectionChanged);
+            // 
+            // col_Address
+            // 
+            this.col_Address.HeaderText = "Address";
+            this.col_Address.Name = "col_Address";
+            this.col_Address.ReadOnly = true;
+            this.col_Address.Resizable = System.Windows.Forms.DataGridViewTriState.False;
+            this.col_Address.SortMode = System.Windows.Forms.DataGridViewColumnSortMode.NotSortable;
+            this.col_Address.Width = 60;
+            // 
+            // col_Register
+            // 
+            this.col_Register.HeaderText = "Register";
+            this.col_Register.Name = "col_Register";
+            this.col_Register.ReadOnly = true;
+            this.col_Register.Resizable = System.Windows.Forms.DataGridViewTriState.False;
+            this.col_Register.SortMode = System.Windows.Forms.DataGridViewColumnSortMode.NotSortable;
+            this.col_Register.Width = 190;
+            // 
+            // col_Value
+            // 
+            this.col_Value.AutoSizeMode = System.Windows.Forms.DataGridViewAutoSizeColumnMode.Fill;
+            dataGridViewCellStyle23.ForeColor = System.Drawing.SystemColors.ControlText;
+            this.col_Value.DefaultCellStyle = dataGridViewCellStyle23;
+            this.col_Value.HeaderText = "Value (Hex)";
+            this.col_Value.Name = "col_Value";
+            this.col_Value.Resizable = System.Windows.Forms.DataGridViewTriState.False;
+            this.col_Value.SortMode = System.Windows.Forms.DataGridViewColumnSortMode.NotSortable;
+            // 
+            // dgv_RegDes
+            // 
+            this.dgv_RegDes.AllowUserToAddRows = false;
+            this.dgv_RegDes.AllowUserToDeleteRows = false;
+            this.dgv_RegDes.AllowUserToResizeColumns = false;
+            this.dgv_RegDes.AllowUserToResizeRows = false;
+            this.dgv_RegDes.AutoSizeRowsMode = System.Windows.Forms.DataGridViewAutoSizeRowsMode.AllCells;
+            this.dgv_RegDes.BackgroundColor = System.Drawing.Color.White;
+            this.dgv_RegDes.BorderStyle = System.Windows.Forms.BorderStyle.Fixed3D;
+            dataGridViewCellStyle25.Alignment = System.Windows.Forms.DataGridViewContentAlignment.MiddleCenter;
+            dataGridViewCellStyle25.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(221)))), ((int)(((byte)(221)))), ((int)(((byte)(221)))));
+            dataGridViewCellStyle25.Font = new System.Drawing.Font("Arial", 9F);
+            dataGridViewCellStyle25.WrapMode = System.Windows.Forms.DataGridViewTriState.True;
+            this.dgv_RegDes.ColumnHeadersDefaultCellStyle = dataGridViewCellStyle25;
+            this.dgv_RegDes.ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize;
+            this.dgv_RegDes.Columns.AddRange(new System.Windows.Forms.DataGridViewColumn[] {
+            this.col_bit,
+            this.dataGridViewTextBoxColumn3,
+            this.col_Des});
+            dataGridViewCellStyle29.Alignment = System.Windows.Forms.DataGridViewContentAlignment.MiddleLeft;
+            dataGridViewCellStyle29.BackColor = System.Drawing.SystemColors.Window;
+            dataGridViewCellStyle29.Font = new System.Drawing.Font("Arial", 9F);
+            dataGridViewCellStyle29.ForeColor = System.Drawing.Color.Black;
+            dataGridViewCellStyle29.SelectionBackColor = System.Drawing.Color.White;
+            dataGridViewCellStyle29.SelectionForeColor = System.Drawing.Color.Black;
+            dataGridViewCellStyle29.WrapMode = System.Windows.Forms.DataGridViewTriState.False;
+            this.dgv_RegDes.DefaultCellStyle = dataGridViewCellStyle29;
+            this.dgv_RegDes.Dock = System.Windows.Forms.DockStyle.Fill;
+            this.dgv_RegDes.Location = new System.Drawing.Point(307, 34);
+            this.dgv_RegDes.Margin = new System.Windows.Forms.Padding(3, 4, 3, 4);
+            this.dgv_RegDes.MultiSelect = false;
+            this.dgv_RegDes.Name = "dgv_RegDes";
+            this.dgv_RegDes.ReadOnly = true;
+            dataGridViewCellStyle30.Alignment = System.Windows.Forms.DataGridViewContentAlignment.MiddleLeft;
+            dataGridViewCellStyle30.BackColor = System.Drawing.SystemColors.Control;
+            dataGridViewCellStyle30.Font = new System.Drawing.Font("Arial", 9F);
+            dataGridViewCellStyle30.ForeColor = System.Drawing.SystemColors.WindowText;
+            dataGridViewCellStyle30.SelectionBackColor = System.Drawing.SystemColors.Control;
+            dataGridViewCellStyle30.SelectionForeColor = System.Drawing.Color.Black;
+            dataGridViewCellStyle30.WrapMode = System.Windows.Forms.DataGridViewTriState.True;
+            this.dgv_RegDes.RowHeadersDefaultCellStyle = dataGridViewCellStyle30;
+            this.dgv_RegDes.RowHeadersVisible = false;
+            this.dgv_RegDes.RowHeadersWidthSizeMode = System.Windows.Forms.DataGridViewRowHeadersWidthSizeMode.AutoSizeToDisplayedHeaders;
+            this.dgv_RegDes.ScrollBars = System.Windows.Forms.ScrollBars.Vertical;
+            this.dgv_RegDes.SelectionMode = System.Windows.Forms.DataGridViewSelectionMode.FullRowSelect;
+            this.dgv_RegDes.Size = new System.Drawing.Size(580, 288);
+            this.dgv_RegDes.StandardTab = true;
+            this.dgv_RegDes.TabIndex = 3;
+            // 
+            // col_bit
+            // 
+            dataGridViewCellStyle26.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(221)))), ((int)(((byte)(221)))), ((int)(((byte)(221)))));
+            dataGridViewCellStyle26.Font = new System.Drawing.Font("Arial", 9.75F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+            dataGridViewCellStyle26.ForeColor = System.Drawing.Color.Black;
+            dataGridViewCellStyle26.SelectionBackColor = System.Drawing.Color.FromArgb(((int)(((byte)(221)))), ((int)(((byte)(221)))), ((int)(((byte)(221)))));
+            dataGridViewCellStyle26.SelectionForeColor = System.Drawing.Color.Black;
+            this.col_bit.DefaultCellStyle = dataGridViewCellStyle26;
+            this.col_bit.HeaderText = "Bit";
+            this.col_bit.Name = "col_bit";
+            this.col_bit.ReadOnly = true;
+            this.col_bit.Resizable = System.Windows.Forms.DataGridViewTriState.False;
+            this.col_bit.SortMode = System.Windows.Forms.DataGridViewColumnSortMode.NotSortable;
+            this.col_bit.Width = 80;
+            // 
+            // dataGridViewTextBoxColumn3
+            // 
+            dataGridViewCellStyle27.ForeColor = System.Drawing.SystemColors.ControlText;
+            this.dataGridViewTextBoxColumn3.DefaultCellStyle = dataGridViewCellStyle27;
+            this.dataGridViewTextBoxColumn3.HeaderText = "Name";
+            this.dataGridViewTextBoxColumn3.Name = "dataGridViewTextBoxColumn3";
+            this.dataGridViewTextBoxColumn3.ReadOnly = true;
+            this.dataGridViewTextBoxColumn3.Resizable = System.Windows.Forms.DataGridViewTriState.False;
+            this.dataGridViewTextBoxColumn3.SortMode = System.Windows.Forms.DataGridViewColumnSortMode.NotSortable;
+            this.dataGridViewTextBoxColumn3.Width = 140;
+            // 
+            // col_Des
+            // 
+            this.col_Des.AutoSizeMode = System.Windows.Forms.DataGridViewAutoSizeColumnMode.Fill;
+            dataGridViewCellStyle28.WrapMode = System.Windows.Forms.DataGridViewTriState.True;
+            this.col_Des.DefaultCellStyle = dataGridViewCellStyle28;
+            this.col_Des.HeaderText = "Description";
+            this.col_Des.Name = "col_Des";
+            this.col_Des.ReadOnly = true;
+            this.col_Des.Resizable = System.Windows.Forms.DataGridViewTriState.False;
+            this.col_Des.SortMode = System.Windows.Forms.DataGridViewColumnSortMode.NotSortable;
+            // 
+            // lbl_bitDes
+            // 
+            this.lbl_bitDes.AutoSize = true;
+            this.lbl_bitDes.Dock = System.Windows.Forms.DockStyle.Bottom;
+            this.lbl_bitDes.Location = new System.Drawing.Point(307, 17);
+            this.lbl_bitDes.Name = "lbl_bitDes";
+            this.lbl_bitDes.Size = new System.Drawing.Size(580, 13);
+            this.lbl_bitDes.TabIndex = 2;
+            this.lbl_bitDes.Text = "Bit Descriptions";
+            // 
+            // lbl_Note
+            // 
+            this.lbl_Note.AutoSize = true;
+            this.lbl_Note.Location = new System.Drawing.Point(7, 326);
+            this.lbl_Note.Name = "lbl_Note";
+            this.lbl_Note.Size = new System.Drawing.Size(207, 13);
+            this.lbl_Note.TabIndex = 4;
+            this.lbl_Note.Text = "Note: Double Click \"Value\" Column to Edit";
+            // 
+            // lblHeader7
+            // 
+            this.lblHeader7.Anchor = System.Windows.Forms.AnchorStyles.Top;
+            this.lblHeader7.BackColor = System.Drawing.Color.White;
+            this.lblHeader7.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+            this.lblHeader7.Location = new System.Drawing.Point(31, 12);
+            this.lblHeader7.Name = "lblHeader7";
+            this.lblHeader7.Size = new System.Drawing.Size(100, 13);
+            this.lblHeader7.TabIndex = 0;
+            this.lblHeader7.Text = "23 / 15 / 7";
+            this.lblHeader7.TextAlign = System.Drawing.ContentAlignment.TopCenter;
+            // 
+            // lblHeader6
+            // 
+            this.lblHeader6.Anchor = System.Windows.Forms.AnchorStyles.Top;
+            this.lblHeader6.BackColor = System.Drawing.Color.White;
+            this.lblHeader6.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+            this.lblHeader6.Location = new System.Drawing.Point(134, 12);
+            this.lblHeader6.Name = "lblHeader6";
+            this.lblHeader6.Size = new System.Drawing.Size(100, 13);
+            this.lblHeader6.TabIndex = 1;
+            this.lblHeader6.Text = "22 / 14 / 6";
+            this.lblHeader6.TextAlign = System.Drawing.ContentAlignment.TopCenter;
+            // 
+            // lblHeader5
+            // 
+            this.lblHeader5.Anchor = System.Windows.Forms.AnchorStyles.Top;
+            this.lblHeader5.BackColor = System.Drawing.Color.White;
+            this.lblHeader5.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+            this.lblHeader5.Location = new System.Drawing.Point(237, 12);
+            this.lblHeader5.Name = "lblHeader5";
+            this.lblHeader5.Size = new System.Drawing.Size(100, 13);
+            this.lblHeader5.TabIndex = 2;
+            this.lblHeader5.Text = "21 / 13 / 5";
+            this.lblHeader5.TextAlign = System.Drawing.ContentAlignment.TopCenter;
+            // 
+            // lblHeader4
+            // 
+            this.lblHeader4.Anchor = System.Windows.Forms.AnchorStyles.Top;
+            this.lblHeader4.BackColor = System.Drawing.Color.White;
+            this.lblHeader4.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+            this.lblHeader4.Location = new System.Drawing.Point(340, 12);
+            this.lblHeader4.Name = "lblHeader4";
+            this.lblHeader4.Size = new System.Drawing.Size(100, 13);
+            this.lblHeader4.TabIndex = 3;
+            this.lblHeader4.Text = "20 / 12 / 4";
+            this.lblHeader4.TextAlign = System.Drawing.ContentAlignment.TopCenter;
+            // 
+            // lblHeader3
+            // 
+            this.lblHeader3.Anchor = System.Windows.Forms.AnchorStyles.Top;
+            this.lblHeader3.BackColor = System.Drawing.Color.White;
+            this.lblHeader3.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+            this.lblHeader3.Location = new System.Drawing.Point(443, 12);
+            this.lblHeader3.Name = "lblHeader3";
+            this.lblHeader3.Size = new System.Drawing.Size(100, 13);
+            this.lblHeader3.TabIndex = 4;
+            this.lblHeader3.Text = "19 / 11 / 3";
+            this.lblHeader3.TextAlign = System.Drawing.ContentAlignment.TopCenter;
+            // 
+            // lblHeader2
+            // 
+            this.lblHeader2.Anchor = System.Windows.Forms.AnchorStyles.Top;
+            this.lblHeader2.BackColor = System.Drawing.Color.White;
+            this.lblHeader2.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+            this.lblHeader2.Location = new System.Drawing.Point(546, 12);
+            this.lblHeader2.Name = "lblHeader2";
+            this.lblHeader2.Size = new System.Drawing.Size(100, 13);
+            this.lblHeader2.TabIndex = 5;
+            this.lblHeader2.Text = "18 / 10 / 2";
+            this.lblHeader2.TextAlign = System.Drawing.ContentAlignment.TopCenter;
+            // 
+            // lblHeader1
+            // 
+            this.lblHeader1.Anchor = System.Windows.Forms.AnchorStyles.Top;
+            this.lblHeader1.BackColor = System.Drawing.Color.White;
+            this.lblHeader1.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+            this.lblHeader1.Location = new System.Drawing.Point(649, 12);
+            this.lblHeader1.Name = "lblHeader1";
+            this.lblHeader1.Size = new System.Drawing.Size(100, 13);
+            this.lblHeader1.TabIndex = 6;
+            this.lblHeader1.Text = "17 / 9 / 1";
+            this.lblHeader1.TextAlign = System.Drawing.ContentAlignment.TopCenter;
+            // 
+            // lblHeader0
+            // 
+            this.lblHeader0.Anchor = System.Windows.Forms.AnchorStyles.Top;
+            this.lblHeader0.BackColor = System.Drawing.Color.White;
+            this.lblHeader0.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+            this.lblHeader0.Location = new System.Drawing.Point(752, 12);
+            this.lblHeader0.Name = "lblHeader0";
+            this.lblHeader0.Size = new System.Drawing.Size(100, 13);
+            this.lblHeader0.TabIndex = 7;
+            this.lblHeader0.Text = "16 / 8 / 0";
+            this.lblHeader0.TextAlign = System.Drawing.ContentAlignment.TopCenter;
+            // 
+            // lblBit23
+            // 
+            this.lblBit23.Anchor = System.Windows.Forms.AnchorStyles.None;
+            this.lblBit23.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(224)))), ((int)(((byte)(224)))), ((int)(((byte)(224)))));
+            this.lblBit23.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+            this.lblBit23.Location = new System.Drawing.Point(31, 37);
+            this.lblBit23.Name = "lblBit23";
+            this.lblBit23.Size = new System.Drawing.Size(100, 13);
+            this.lblBit23.TabIndex = 8;
+            this.lblBit23.Text = "BIT_23";
+            this.lblBit23.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
+            this.lblBit23.Click += new System.EventHandler(this.lblBit_Click);
+            // 
+            // lblBit22
+            // 
+            this.lblBit22.Anchor = System.Windows.Forms.AnchorStyles.None;
+            this.lblBit22.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(224)))), ((int)(((byte)(224)))), ((int)(((byte)(224)))));
+            this.lblBit22.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+            this.lblBit22.Location = new System.Drawing.Point(134, 37);
+            this.lblBit22.Name = "lblBit22";
+            this.lblBit22.Size = new System.Drawing.Size(100, 13);
+            this.lblBit22.TabIndex = 9;
+            this.lblBit22.Text = "BIT_22";
+            this.lblBit22.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
+            this.lblBit22.Click += new System.EventHandler(this.lblBit_Click);
+            // 
+            // lblBit21
+            // 
+            this.lblBit21.Anchor = System.Windows.Forms.AnchorStyles.None;
+            this.lblBit21.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(224)))), ((int)(((byte)(224)))), ((int)(((byte)(224)))));
+            this.lblBit21.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+            this.lblBit21.Location = new System.Drawing.Point(237, 37);
+            this.lblBit21.Name = "lblBit21";
+            this.lblBit21.Size = new System.Drawing.Size(100, 13);
+            this.lblBit21.TabIndex = 10;
+            this.lblBit21.Text = "BIT_21";
+            this.lblBit21.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
+            this.lblBit21.Click += new System.EventHandler(this.lblBit_Click);
+            // 
+            // lblBit20
+            // 
+            this.lblBit20.Anchor = System.Windows.Forms.AnchorStyles.None;
+            this.lblBit20.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(224)))), ((int)(((byte)(224)))), ((int)(((byte)(224)))));
+            this.lblBit20.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+            this.lblBit20.Location = new System.Drawing.Point(340, 37);
+            this.lblBit20.Name = "lblBit20";
+            this.lblBit20.Size = new System.Drawing.Size(100, 13);
+            this.lblBit20.TabIndex = 11;
+            this.lblBit20.Text = "BIT_20";
+            this.lblBit20.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
+            this.lblBit20.Click += new System.EventHandler(this.lblBit_Click);
+            // 
+            // lblBit19
+            // 
+            this.lblBit19.Anchor = System.Windows.Forms.AnchorStyles.None;
+            this.lblBit19.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(224)))), ((int)(((byte)(224)))), ((int)(((byte)(224)))));
+            this.lblBit19.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+            this.lblBit19.Location = new System.Drawing.Point(443, 37);
+            this.lblBit19.Name = "lblBit19";
+            this.lblBit19.Size = new System.Drawing.Size(100, 13);
+            this.lblBit19.TabIndex = 12;
+            this.lblBit19.Text = "BIT_19";
+            this.lblBit19.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
+            this.lblBit19.Click += new System.EventHandler(this.lblBit_Click);
+            // 
+            // lblBit18
+            // 
+            this.lblBit18.Anchor = System.Windows.Forms.AnchorStyles.None;
+            this.lblBit18.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(224)))), ((int)(((byte)(224)))), ((int)(((byte)(224)))));
+            this.lblBit18.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+            this.lblBit18.Location = new System.Drawing.Point(546, 37);
+            this.lblBit18.Name = "lblBit18";
+            this.lblBit18.Size = new System.Drawing.Size(100, 13);
+            this.lblBit18.TabIndex = 13;
+            this.lblBit18.Text = "BIT_18";
+            this.lblBit18.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
+            this.lblBit18.Click += new System.EventHandler(this.lblBit_Click);
+            // 
+            // lblBit17
+            // 
+            this.lblBit17.Anchor = System.Windows.Forms.AnchorStyles.None;
+            this.lblBit17.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(224)))), ((int)(((byte)(224)))), ((int)(((byte)(224)))));
+            this.lblBit17.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+            this.lblBit17.Location = new System.Drawing.Point(649, 37);
+            this.lblBit17.Name = "lblBit17";
+            this.lblBit17.Size = new System.Drawing.Size(100, 13);
+            this.lblBit17.TabIndex = 14;
+            this.lblBit17.Text = "BIT_17";
+            this.lblBit17.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
+            this.lblBit17.Click += new System.EventHandler(this.lblBit_Click);
+            // 
+            // lblBit16
+            // 
+            this.lblBit16.Anchor = System.Windows.Forms.AnchorStyles.None;
+            this.lblBit16.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(224)))), ((int)(((byte)(224)))), ((int)(((byte)(224)))));
+            this.lblBit16.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+            this.lblBit16.Location = new System.Drawing.Point(752, 37);
+            this.lblBit16.Name = "lblBit16";
+            this.lblBit16.Size = new System.Drawing.Size(100, 13);
+            this.lblBit16.TabIndex = 15;
+            this.lblBit16.Text = "BIT_16";
+            this.lblBit16.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
+            this.lblBit16.Click += new System.EventHandler(this.lblBit_Click);
+            // 
+            // lblBit15
+            // 
+            this.lblBit15.Anchor = System.Windows.Forms.AnchorStyles.None;
+            this.lblBit15.BackColor = System.Drawing.Color.White;
+            this.lblBit15.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+            this.lblBit15.Location = new System.Drawing.Point(31, 64);
+            this.lblBit15.Name = "lblBit15";
+            this.lblBit15.Size = new System.Drawing.Size(100, 13);
+            this.lblBit15.TabIndex = 16;
+            this.lblBit15.Text = "BIT_15";
+            this.lblBit15.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
+            this.lblBit15.Click += new System.EventHandler(this.lblBit_Click);
+            // 
+            // lblBit14
+            // 
+            this.lblBit14.Anchor = System.Windows.Forms.AnchorStyles.None;
+            this.lblBit14.BackColor = System.Drawing.Color.White;
+            this.lblBit14.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+            this.lblBit14.Location = new System.Drawing.Point(134, 64);
+            this.lblBit14.Name = "lblBit14";
+            this.lblBit14.Size = new System.Drawing.Size(100, 13);
+            this.lblBit14.TabIndex = 17;
+            this.lblBit14.Text = "BIT_14";
+            this.lblBit14.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
+            this.lblBit14.Click += new System.EventHandler(this.lblBit_Click);
+            // 
+            // lblBit13
+            // 
+            this.lblBit13.Anchor = System.Windows.Forms.AnchorStyles.None;
+            this.lblBit13.BackColor = System.Drawing.Color.White;
+            this.lblBit13.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+            this.lblBit13.Location = new System.Drawing.Point(237, 64);
+            this.lblBit13.Name = "lblBit13";
+            this.lblBit13.Size = new System.Drawing.Size(100, 13);
+            this.lblBit13.TabIndex = 18;
+            this.lblBit13.Text = "BIT_13";
+            this.lblBit13.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
+            this.lblBit13.Click += new System.EventHandler(this.lblBit_Click);
+            // 
+            // lblBit12
+            // 
+            this.lblBit12.Anchor = System.Windows.Forms.AnchorStyles.None;
+            this.lblBit12.BackColor = System.Drawing.Color.White;
+            this.lblBit12.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+            this.lblBit12.Location = new System.Drawing.Point(340, 64);
+            this.lblBit12.Name = "lblBit12";
+            this.lblBit12.Size = new System.Drawing.Size(100, 13);
+            this.lblBit12.TabIndex = 19;
+            this.lblBit12.Text = "BIT_12";
+            this.lblBit12.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
+            this.lblBit12.Click += new System.EventHandler(this.lblBit_Click);
+            // 
+            // lblBit11
+            // 
+            this.lblBit11.Anchor = System.Windows.Forms.AnchorStyles.None;
+            this.lblBit11.BackColor = System.Drawing.Color.White;
+            this.lblBit11.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+            this.lblBit11.Location = new System.Drawing.Point(443, 64);
+            this.lblBit11.Name = "lblBit11";
+            this.lblBit11.Size = new System.Drawing.Size(100, 13);
+            this.lblBit11.TabIndex = 20;
+            this.lblBit11.Text = "BIT_11";
+            this.lblBit11.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
+            this.lblBit11.Click += new System.EventHandler(this.lblBit_Click);
+            // 
+            // lblBit10
+            // 
+            this.lblBit10.Anchor = System.Windows.Forms.AnchorStyles.None;
+            this.lblBit10.BackColor = System.Drawing.Color.White;
+            this.lblBit10.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+            this.lblBit10.Location = new System.Drawing.Point(546, 64);
+            this.lblBit10.Name = "lblBit10";
+            this.lblBit10.Size = new System.Drawing.Size(100, 13);
+            this.lblBit10.TabIndex = 21;
+            this.lblBit10.Text = "BIT_10";
+            this.lblBit10.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
+            this.lblBit10.Click += new System.EventHandler(this.lblBit_Click);
+            // 
+            // lblBit09
+            // 
+            this.lblBit09.Anchor = System.Windows.Forms.AnchorStyles.None;
+            this.lblBit09.BackColor = System.Drawing.Color.White;
+            this.lblBit09.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+            this.lblBit09.Location = new System.Drawing.Point(649, 64);
+            this.lblBit09.Name = "lblBit09";
+            this.lblBit09.Size = new System.Drawing.Size(100, 13);
+            this.lblBit09.TabIndex = 22;
+            this.lblBit09.Text = "BIT_09";
+            this.lblBit09.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
+            this.lblBit09.Click += new System.EventHandler(this.lblBit_Click);
+            // 
+            // lblBit08
+            // 
+            this.lblBit08.Anchor = System.Windows.Forms.AnchorStyles.None;
+            this.lblBit08.BackColor = System.Drawing.Color.White;
+            this.lblBit08.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+            this.lblBit08.Location = new System.Drawing.Point(752, 64);
+            this.lblBit08.Name = "lblBit08";
+            this.lblBit08.Size = new System.Drawing.Size(100, 13);
+            this.lblBit08.TabIndex = 23;
+            this.lblBit08.Text = "BIT_08";
+            this.lblBit08.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
+            this.lblBit08.Click += new System.EventHandler(this.lblBit_Click);
+            // 
+            // panelRegisterBits
+            // 
+            this.panelRegisterBits.BackColor = System.Drawing.Color.White;
+            this.panelRegisterBits.Controls.Add(this.label1);
+            this.panelRegisterBits.Controls.Add(this.btnWrite);
+            this.panelRegisterBits.Controls.Add(this.btnRead);
+            this.panelRegisterBits.Controls.Add(this.lblBit07);
+            this.panelRegisterBits.Controls.Add(this.lblBit06);
+            this.panelRegisterBits.Controls.Add(this.lblBit05);
+            this.panelRegisterBits.Controls.Add(this.lblBit04);
+            this.panelRegisterBits.Controls.Add(this.lblBit03);
+            this.panelRegisterBits.Controls.Add(this.lblBit02);
+            this.panelRegisterBits.Controls.Add(this.lblBit01);
+            this.panelRegisterBits.Controls.Add(this.lblBit00);
+            this.panelRegisterBits.Controls.Add(this.lblBit15);
+            this.panelRegisterBits.Controls.Add(this.lblBit14);
+            this.panelRegisterBits.Controls.Add(this.lblBit23);
+            this.panelRegisterBits.Controls.Add(this.lblBit21);
+            this.panelRegisterBits.Controls.Add(this.lblBit22);
+            this.panelRegisterBits.Controls.Add(this.lblBit12);
+            this.panelRegisterBits.Controls.Add(this.lblHeader7);
+            this.panelRegisterBits.Controls.Add(this.lblBit11);
+            this.panelRegisterBits.Controls.Add(this.lblBit20);
+            this.panelRegisterBits.Controls.Add(this.lblBit10);
+            this.panelRegisterBits.Controls.Add(this.lblHeader6);
+            this.panelRegisterBits.Controls.Add(this.lblBit09);
+            this.panelRegisterBits.Controls.Add(this.lblBit19);
+            this.panelRegisterBits.Controls.Add(this.lblBit08);
+            this.panelRegisterBits.Controls.Add(this.lblHeader0);
+            this.panelRegisterBits.Controls.Add(this.lblBit18);
+            this.panelRegisterBits.Controls.Add(this.lblHeader5);
+            this.panelRegisterBits.Controls.Add(this.lblBit17);
+            this.panelRegisterBits.Controls.Add(this.lblHeader1);
+            this.panelRegisterBits.Controls.Add(this.lblBit16);
+            this.panelRegisterBits.Controls.Add(this.lblBit13);
+            this.panelRegisterBits.Controls.Add(this.lblHeader4);
+            this.panelRegisterBits.Controls.Add(this.lblHeader2);
+            this.panelRegisterBits.Controls.Add(this.lblHeader3);
+            this.panelRegisterBits.Controls.Add(this.tableLayoutPanel1);
+            this.panelRegisterBits.Controls.Add(this.tableLayoutPanel2);
+            this.panelRegisterBits.Dock = System.Windows.Forms.DockStyle.Bottom;
+            this.panelRegisterBits.Location = new System.Drawing.Point(0, 378);
+            this.panelRegisterBits.Name = "panelRegisterBits";
+            this.panelRegisterBits.Size = new System.Drawing.Size(894, 136);
+            this.panelRegisterBits.TabIndex = 2;
+            // 
+            // label1
+            // 
+            this.label1.Anchor = System.Windows.Forms.AnchorStyles.Top;
+            this.label1.AutoSize = true;
+            this.label1.Location = new System.Drawing.Point(48, 115);
+            this.label1.Name = "label1";
+            this.label1.Size = new System.Drawing.Size(515, 13);
+            this.label1.TabIndex = 36;
+            this.label1.Text = "Note: Click text to set or clear bit and \"Write\" to commit to device. Bold text i" +
+    "s logic 1. Regular text is logic 0.";
+            // 
+            // btnWrite
+            // 
+            this.btnWrite.Anchor = System.Windows.Forms.AnchorStyles.Top;
+            this.btnWrite.Location = new System.Drawing.Point(793, 110);
+            this.btnWrite.Name = "btnWrite";
+            this.btnWrite.Size = new System.Drawing.Size(55, 23);
+            this.btnWrite.TabIndex = 35;
+            this.btnWrite.Text = "Write";
+            this.btnWrite.UseVisualStyleBackColor = true;
+            this.btnWrite.Click += new System.EventHandler(this.btnWrite_Click);
+            // 
+            // btnRead
+            // 
+            this.btnRead.Anchor = System.Windows.Forms.AnchorStyles.Top;
+            this.btnRead.Location = new System.Drawing.Point(728, 110);
+            this.btnRead.Name = "btnRead";
+            this.btnRead.Size = new System.Drawing.Size(59, 23);
+            this.btnRead.TabIndex = 34;
+            this.btnRead.Text = "Read";
+            this.btnRead.UseVisualStyleBackColor = true;
+            this.btnRead.Click += new System.EventHandler(this.btnRead_Click);
+            // 
+            // lblBit07
+            // 
+            this.lblBit07.Anchor = System.Windows.Forms.AnchorStyles.None;
+            this.lblBit07.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(224)))), ((int)(((byte)(224)))), ((int)(((byte)(224)))));
+            this.lblBit07.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+            this.lblBit07.Location = new System.Drawing.Point(31, 87);
+            this.lblBit07.Name = "lblBit07";
+            this.lblBit07.Size = new System.Drawing.Size(100, 13);
+            this.lblBit07.TabIndex = 25;
+            this.lblBit07.Text = "BIT_07";
+            this.lblBit07.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
+            this.lblBit07.Click += new System.EventHandler(this.lblBit_Click);
+            // 
+            // lblBit06
+            // 
+            this.lblBit06.Anchor = System.Windows.Forms.AnchorStyles.None;
+            this.lblBit06.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(224)))), ((int)(((byte)(224)))), ((int)(((byte)(224)))));
+            this.lblBit06.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+            this.lblBit06.Location = new System.Drawing.Point(134, 87);
+            this.lblBit06.Name = "lblBit06";
+            this.lblBit06.Size = new System.Drawing.Size(100, 13);
+            this.lblBit06.TabIndex = 26;
+            this.lblBit06.Text = "BIT_06";
+            this.lblBit06.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
+            this.lblBit06.Click += new System.EventHandler(this.lblBit_Click);
+            // 
+            // lblBit05
+            // 
+            this.lblBit05.Anchor = System.Windows.Forms.AnchorStyles.None;
+            this.lblBit05.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(224)))), ((int)(((byte)(224)))), ((int)(((byte)(224)))));
+            this.lblBit05.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+            this.lblBit05.Location = new System.Drawing.Point(237, 87);
+            this.lblBit05.Name = "lblBit05";
+            this.lblBit05.Size = new System.Drawing.Size(100, 13);
+            this.lblBit05.TabIndex = 24;
+            this.lblBit05.Text = "BIT_05";
+            this.lblBit05.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
+            this.lblBit05.Click += new System.EventHandler(this.lblBit_Click);
+            // 
+            // lblBit04
+            // 
+            this.lblBit04.Anchor = System.Windows.Forms.AnchorStyles.None;
+            this.lblBit04.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(224)))), ((int)(((byte)(224)))), ((int)(((byte)(224)))));
+            this.lblBit04.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+            this.lblBit04.Location = new System.Drawing.Point(340, 87);
+            this.lblBit04.Name = "lblBit04";
+            this.lblBit04.Size = new System.Drawing.Size(100, 13);
+            this.lblBit04.TabIndex = 27;
+            this.lblBit04.Text = "BIT_04";
+            this.lblBit04.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
+            this.lblBit04.Click += new System.EventHandler(this.lblBit_Click);
+            // 
+            // lblBit03
+            // 
+            this.lblBit03.Anchor = System.Windows.Forms.AnchorStyles.None;
+            this.lblBit03.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(224)))), ((int)(((byte)(224)))), ((int)(((byte)(224)))));
+            this.lblBit03.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+            this.lblBit03.Location = new System.Drawing.Point(443, 87);
+            this.lblBit03.Name = "lblBit03";
+            this.lblBit03.Size = new System.Drawing.Size(100, 13);
+            this.lblBit03.TabIndex = 28;
+            this.lblBit03.Text = "BIT_03";
+            this.lblBit03.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
+            this.lblBit03.Click += new System.EventHandler(this.lblBit_Click);
+            // 
+            // lblBit02
+            // 
+            this.lblBit02.Anchor = System.Windows.Forms.AnchorStyles.None;
+            this.lblBit02.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(224)))), ((int)(((byte)(224)))), ((int)(((byte)(224)))));
+            this.lblBit02.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+            this.lblBit02.Location = new System.Drawing.Point(546, 87);
+            this.lblBit02.Name = "lblBit02";
+            this.lblBit02.Size = new System.Drawing.Size(100, 13);
+            this.lblBit02.TabIndex = 29;
+            this.lblBit02.Text = "BIT_02";
+            this.lblBit02.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
+            this.lblBit02.Click += new System.EventHandler(this.lblBit_Click);
+            // 
+            // lblBit01
+            // 
+            this.lblBit01.Anchor = System.Windows.Forms.AnchorStyles.None;
+            this.lblBit01.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(224)))), ((int)(((byte)(224)))), ((int)(((byte)(224)))));
+            this.lblBit01.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+            this.lblBit01.Location = new System.Drawing.Point(649, 87);
+            this.lblBit01.Name = "lblBit01";
+            this.lblBit01.Size = new System.Drawing.Size(100, 13);
+            this.lblBit01.TabIndex = 30;
+            this.lblBit01.Text = "BIT_01";
+            this.lblBit01.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
+            this.lblBit01.Click += new System.EventHandler(this.lblBit_Click);
+            // 
+            // lblBit00
+            // 
+            this.lblBit00.Anchor = System.Windows.Forms.AnchorStyles.None;
+            this.lblBit00.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(224)))), ((int)(((byte)(224)))), ((int)(((byte)(224)))));
+            this.lblBit00.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+            this.lblBit00.Location = new System.Drawing.Point(752, 87);
+            this.lblBit00.Name = "lblBit00";
+            this.lblBit00.Size = new System.Drawing.Size(100, 13);
+            this.lblBit00.TabIndex = 31;
+            this.lblBit00.Text = "BIT_00";
+            this.lblBit00.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
+            this.lblBit00.Click += new System.EventHandler(this.lblBit_Click);
+            // 
+            // tableLayoutPanel1
+            // 
+            this.tableLayoutPanel1.Anchor = System.Windows.Forms.AnchorStyles.None;
+            this.tableLayoutPanel1.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(224)))), ((int)(((byte)(224)))), ((int)(((byte)(224)))));
+            this.tableLayoutPanel1.ColumnCount = 1;
+            this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F));
+            this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 20F));
+            this.tableLayoutPanel1.Location = new System.Drawing.Point(0, 31);
+            this.tableLayoutPanel1.Name = "tableLayoutPanel1";
+            this.tableLayoutPanel1.RowCount = 1;
+            this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F));
+            this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 24F));
+            this.tableLayoutPanel1.Size = new System.Drawing.Size(894, 24);
+            this.tableLayoutPanel1.TabIndex = 32;
+            // 
+            // tableLayoutPanel2
+            // 
+            this.tableLayoutPanel2.Anchor = System.Windows.Forms.AnchorStyles.None;
+            this.tableLayoutPanel2.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(224)))), ((int)(((byte)(224)))), ((int)(((byte)(224)))));
+            this.tableLayoutPanel2.ColumnCount = 1;
+            this.tableLayoutPanel2.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F));
+            this.tableLayoutPanel2.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 20F));
+            this.tableLayoutPanel2.Location = new System.Drawing.Point(0, 82);
+            this.tableLayoutPanel2.Name = "tableLayoutPanel2";
+            this.tableLayoutPanel2.RowCount = 1;
+            this.tableLayoutPanel2.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F));
+            this.tableLayoutPanel2.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 24F));
+            this.tableLayoutPanel2.Size = new System.Drawing.Size(894, 24);
+            this.tableLayoutPanel2.TabIndex = 33;
+            // 
+            // panel2
+            // 
+            this.panel2.BackColor = System.Drawing.Color.White;
+            this.panel2.Dock = System.Windows.Forms.DockStyle.Top;
+            this.panel2.Location = new System.Drawing.Point(0, 0);
+            this.panel2.Name = "panel2";
+            this.panel2.Size = new System.Drawing.Size(894, 30);
+            this.panel2.TabIndex = 2;
+            // 
+            // RegisterView
+            // 
+            this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
+            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+            this.Controls.Add(this.tableLayoutPanelRegisters);
+            this.Controls.Add(this.panel2);
+            this.Controls.Add(this.panelRegisterBits);
+            this.Name = "RegisterView";
+            this.Size = new System.Drawing.Size(894, 514);
+            this.tableLayoutPanelRegisters.ResumeLayout(false);
+            this.tableLayoutPanelRegisters.PerformLayout();
+            this.panel1.ResumeLayout(false);
+            ((System.ComponentModel.ISupportInitialize)(this.dgv_Registers)).EndInit();
+            ((System.ComponentModel.ISupportInitialize)(this.dgv_RegDes)).EndInit();
+            this.panelRegisterBits.ResumeLayout(false);
+            this.panelRegisterBits.PerformLayout();
+            this.ResumeLayout(false);
+
+        }
+
+        #endregion
+
+        private System.Windows.Forms.TableLayoutPanel tableLayoutPanelRegisters;
+        private MaximStyle.MaximButton btn_ReadAll;
+        private System.Windows.Forms.Panel panel1;
+        private System.Windows.Forms.DataGridView dgv_Registers;
+        private System.Windows.Forms.DataGridViewTextBoxColumn col_Address;
+        private System.Windows.Forms.DataGridViewTextBoxColumn col_Register;
+        private System.Windows.Forms.DataGridViewTextBoxColumn col_Value;
+        private System.Windows.Forms.DataGridView dgv_RegDes;
+        private System.Windows.Forms.DataGridViewTextBoxColumn col_bit;
+        private System.Windows.Forms.DataGridViewTextBoxColumn dataGridViewTextBoxColumn3;
+        private System.Windows.Forms.DataGridViewTextBoxColumn col_Des;
+        private System.Windows.Forms.Label lbl_bitDes;
+        private System.Windows.Forms.Label lbl_Note;
+        private System.Windows.Forms.Label lblHeader7;
+        private System.Windows.Forms.Label lblHeader6;
+        private System.Windows.Forms.Label lblHeader5;
+        private System.Windows.Forms.Label lblHeader4;
+        private System.Windows.Forms.Label lblHeader3;
+        private System.Windows.Forms.Label lblHeader2;
+        private System.Windows.Forms.Label lblHeader1;
+        private System.Windows.Forms.Label lblHeader0;
+        private System.Windows.Forms.Label lblBit23;
+        private System.Windows.Forms.Label lblBit22;
+        private System.Windows.Forms.Label lblBit20;
+        private System.Windows.Forms.Label lblBit19;
+        private System.Windows.Forms.Label lblBit18;
+        private System.Windows.Forms.Label lblBit17;
+        private System.Windows.Forms.Label lblBit16;
+        private System.Windows.Forms.Label lblBit15;
+        private System.Windows.Forms.Label lblBit14;
+        private System.Windows.Forms.Label lblBit13;
+        private System.Windows.Forms.Label lblBit21;
+        private System.Windows.Forms.Label lblBit12;
+        private System.Windows.Forms.Label lblBit11;
+        private System.Windows.Forms.Label lblBit10;
+        private System.Windows.Forms.Label lblBit09;
+        private System.Windows.Forms.Label lblBit08;
+        private System.Windows.Forms.Panel panelRegisterBits;
+        private System.Windows.Forms.Label lblBit07;
+        private System.Windows.Forms.Label lblBit06;
+        private System.Windows.Forms.Label lblBit05;
+        private System.Windows.Forms.Label lblBit04;
+        private System.Windows.Forms.Label lblBit03;
+        private System.Windows.Forms.Label lblBit02;
+        private System.Windows.Forms.Label lblBit01;
+        private System.Windows.Forms.Label lblBit00;
+        private System.Windows.Forms.TableLayoutPanel tableLayoutPanel1;
+        private System.Windows.Forms.TableLayoutPanel tableLayoutPanel2;
+        private System.Windows.Forms.Panel panel2;
+        private MaximStyle.MaximButton btnWrite;
+        private MaximStyle.MaximButton btnRead;
+        private System.Windows.Forms.Label label1;
+
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HspGuiSourceV301/HSPGui/CustomControls/RegisterView.resx	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,138 @@
+<?xml version="1.0" encoding="utf-8"?>
+<root>
+  <!-- 
+    Microsoft ResX Schema 
+    
+    Version 2.0
+    
+    The primary goals of this format is to allow a simple XML format 
+    that is mostly human readable. The generation and parsing of the 
+    various data types are done through the TypeConverter classes 
+    associated with the data types.
+    
+    Example:
+    
+    ... ado.net/XML headers & schema ...
+    <resheader name="resmimetype">text/microsoft-resx</resheader>
+    <resheader name="version">2.0</resheader>
+    <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+    <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+    <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
+    <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+    <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+        <value>[base64 mime encoded serialized .NET Framework object]</value>
+    </data>
+    <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+        <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
+        <comment>This is a comment</comment>
+    </data>
+                
+    There are any number of "resheader" rows that contain simple 
+    name/value pairs.
+    
+    Each data row contains a name, and value. The row also contains a 
+    type or mimetype. Type corresponds to a .NET class that support 
+    text/value conversion through the TypeConverter architecture. 
+    Classes that don't support this are serialized and stored with the 
+    mimetype set.
+    
+    The mimetype is used for serialized objects, and tells the 
+    ResXResourceReader how to depersist the object. This is currently not 
+    extensible. For a given mimetype the value must be set accordingly:
+    
+    Note - application/x-microsoft.net.object.binary.base64 is the format 
+    that the ResXResourceWriter will generate, however the reader can 
+    read any of the formats listed below.
+    
+    mimetype: application/x-microsoft.net.object.binary.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
+            : and then encoded with base64 encoding.
+    
+    mimetype: application/x-microsoft.net.object.soap.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+            : and then encoded with base64 encoding.
+
+    mimetype: application/x-microsoft.net.object.bytearray.base64
+    value   : The object must be serialized into a byte array 
+            : using a System.ComponentModel.TypeConverter
+            : and then encoded with base64 encoding.
+    -->
+  <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+    <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
+    <xsd:element name="root" msdata:IsDataSet="true">
+      <xsd:complexType>
+        <xsd:choice maxOccurs="unbounded">
+          <xsd:element name="metadata">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" />
+              </xsd:sequence>
+              <xsd:attribute name="name" use="required" type="xsd:string" />
+              <xsd:attribute name="type" type="xsd:string" />
+              <xsd:attribute name="mimetype" type="xsd:string" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="assembly">
+            <xsd:complexType>
+              <xsd:attribute name="alias" type="xsd:string" />
+              <xsd:attribute name="name" type="xsd:string" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="data">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+                <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
+              <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+              <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="resheader">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" />
+            </xsd:complexType>
+          </xsd:element>
+        </xsd:choice>
+      </xsd:complexType>
+    </xsd:element>
+  </xsd:schema>
+  <resheader name="resmimetype">
+    <value>text/microsoft-resx</value>
+  </resheader>
+  <resheader name="version">
+    <value>2.0</value>
+  </resheader>
+  <resheader name="reader">
+    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <resheader name="writer">
+    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <metadata name="col_Address.UserAddedColumn" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
+    <value>True</value>
+  </metadata>
+  <metadata name="col_Register.UserAddedColumn" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
+    <value>True</value>
+  </metadata>
+  <metadata name="col_Value.UserAddedColumn" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
+    <value>True</value>
+  </metadata>
+  <metadata name="col_bit.UserAddedColumn" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
+    <value>True</value>
+  </metadata>
+  <metadata name="dataGridViewTextBoxColumn3.UserAddedColumn" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
+    <value>True</value>
+  </metadata>
+  <metadata name="col_Des.UserAddedColumn" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
+    <value>True</value>
+  </metadata>
+</root>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HspGuiSourceV301/HSPGui/CustomControls/StreamingStartStopEventArgs.cs	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,54 @@
+/*******************************************************************************
+* Copyright (C) 2016 Maxim Integrated Products, Inc., All rights Reserved.
+* 
+* This software is protected by copyright laws of the United States and
+* of foreign countries. This material may also be protected by patent laws
+* and technology transfer regulations of the United States and of foreign
+* countries. This software is furnished under a license agreement and/or a
+* nondisclosure agreement and may only be used or reproduced in accordance
+* with the terms of those agreements. Dissemination of this information to
+* any party or parties not specified in the license agreement and/or
+* nondisclosure agreement is expressly prohibited.
+*
+* The above copyright notice and this permission notice shall be included
+* in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+* OTHER DEALINGS IN THE SOFTWARE.
+*
+* Except as contained in this notice, the name of Maxim Integrated
+* Products, Inc. shall not be used except as stated in the Maxim Integrated
+* Products, Inc. Branding Policy.
+*
+* The mere transfer of this software does not imply any licenses
+* of trade secrets, proprietary technology, copyrights, patents,
+* trademarks, maskwork rights, or any other form of intellectual
+* property whatsoever. Maxim Integrated Products, Inc. retains all
+* ownership rights.
+*******************************************************************************
+*/
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace HealthSensorPlatform.CustomControls
+{
+    /// <summary>
+    /// Streaming state
+    /// </summary>
+    public class StreamingStartStopEventArgs : EventArgs
+    {
+        /// <summary>
+        /// true: streaming has started
+        /// false: streaming has stopped
+        /// </summary>
+        public bool state { get; set; }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HspGuiSourceV301/HSPGui/CustomControls/TemperatureView.Designer.cs	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,840 @@
+namespace HealthSensorPlatform.CustomControls
+{
+    partial class TemperatureView
+    {
+        /// <summary> 
+        /// Required designer variable.
+        /// </summary>
+        private System.ComponentModel.IContainer components = null;
+
+        /// <summary> 
+        /// Clean up any resources being used.
+        /// </summary>
+        /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
+        protected override void Dispose(bool disposing)
+        {
+            if (disposing && (components != null))
+            {
+                components.Dispose();
+            }
+            base.Dispose(disposing);
+        }
+
+        #region Component Designer generated code
+
+        /// <summary> 
+        /// Required method for Designer support - do not modify 
+        /// the contents of this method with the code editor.
+        /// </summary>
+        private void InitializeComponent()
+        {
+            this.components = new System.ComponentModel.Container();
+            this.grpConfigurationRegister2 = new MaximStyle.MaximGroupBox();
+            this.label5 = new System.Windows.Forms.Label();
+            this.lblConfigRegister2 = new System.Windows.Forms.Label();
+            this.chkShutdown2 = new MaximStyle.MaximCheckBox();
+            this.chkComparatorInterrupt2 = new MaximStyle.MaximCheckBox();
+            this.chkOSPolarity2 = new MaximStyle.MaximCheckBox();
+            this.chkFaultQueue02 = new MaximStyle.MaximCheckBox();
+            this.chkFaultQueue12 = new MaximStyle.MaximCheckBox();
+            this.chkDataFormat2 = new MaximStyle.MaximCheckBox();
+            this.chkTimeout2 = new MaximStyle.MaximCheckBox();
+            this.chkOneShot2 = new MaximStyle.MaximCheckBox();
+            this.label6 = new System.Windows.Forms.Label();
+            this.maximGroupBox12 = new MaximStyle.MaximGroupBox();
+            this.lblUnits4 = new System.Windows.Forms.Label();
+            this.lblUnits3 = new System.Windows.Forms.Label();
+            this.lblHysteresis2 = new System.Windows.Forms.Label();
+            this.lblOvertemperature2 = new System.Windows.Forms.Label();
+            this.txtHysteresis2 = new System.Windows.Forms.TextBox();
+            this.txtOvertemperature2 = new System.Windows.Forms.TextBox();
+            this.label41 = new System.Windows.Forms.Label();
+            this.label42 = new System.Windows.Forms.Label();
+            this.maximGroupBox13 = new MaximStyle.MaximGroupBox();
+            this.lblTemperatureHex2 = new System.Windows.Forms.Label();
+            this.lblUnits6 = new System.Windows.Forms.Label();
+            this.lblTemperature2 = new System.Windows.Forms.Label();
+            this.grpConfigurationRegister1 = new MaximStyle.MaximGroupBox();
+            this.lblConfigRegister1 = new System.Windows.Forms.Label();
+            this.chkShutdown1 = new MaximStyle.MaximCheckBox();
+            this.chkFaultQueue01 = new MaximStyle.MaximCheckBox();
+            this.chkFaultQueue11 = new MaximStyle.MaximCheckBox();
+            this.chkDataFormat1 = new MaximStyle.MaximCheckBox();
+            this.chkTimeout1 = new MaximStyle.MaximCheckBox();
+            this.chkOSPolarity1 = new MaximStyle.MaximCheckBox();
+            this.label4 = new System.Windows.Forms.Label();
+            this.chkOneShot1 = new MaximStyle.MaximCheckBox();
+            this.label3 = new System.Windows.Forms.Label();
+            this.chkComparatorInterrupt1 = new MaximStyle.MaximCheckBox();
+            this.maximGroupBox10 = new MaximStyle.MaximGroupBox();
+            this.lblUnits2 = new System.Windows.Forms.Label();
+            this.lblUnits1 = new System.Windows.Forms.Label();
+            this.lblHysteresis1 = new System.Windows.Forms.Label();
+            this.lblOvertemperature1 = new System.Windows.Forms.Label();
+            this.txtHysteresis1 = new System.Windows.Forms.TextBox();
+            this.txtOvertemperature1 = new System.Windows.Forms.TextBox();
+            this.label36 = new System.Windows.Forms.Label();
+            this.label34 = new System.Windows.Forms.Label();
+            this.maximGroupBox8 = new MaximStyle.MaximGroupBox();
+            this.lblTemperature1 = new System.Windows.Forms.Label();
+            this.lblTemperatureHex1 = new System.Windows.Forms.Label();
+            this.lblUnits5 = new System.Windows.Forms.Label();
+            this.maximGroupBox7 = new MaximStyle.MaximGroupBox();
+            this.maximButton1 = new MaximStyle.MaximButton();
+            this.label2 = new System.Windows.Forms.Label();
+            this.cboRefreshRate = new MaximStyle.MaximComboBox();
+            this.label1 = new System.Windows.Forms.Label();
+            this.tglCelsiusFahrenheit = new MaximStyle.MaximToggleButton();
+            this.errorProvider1 = new System.Windows.Forms.ErrorProvider(this.components);
+            this.timer1 = new System.Windows.Forms.Timer(this.components);
+            this.label7 = new System.Windows.Forms.Label();
+            this.grpConfigurationRegister2.SuspendLayout();
+            this.maximGroupBox12.SuspendLayout();
+            this.maximGroupBox13.SuspendLayout();
+            this.grpConfigurationRegister1.SuspendLayout();
+            this.maximGroupBox10.SuspendLayout();
+            this.maximGroupBox8.SuspendLayout();
+            this.maximGroupBox7.SuspendLayout();
+            ((System.ComponentModel.ISupportInitialize)(this.errorProvider1)).BeginInit();
+            this.SuspendLayout();
+            // 
+            // grpConfigurationRegister2
+            // 
+            this.grpConfigurationRegister2.BackgroundColor = System.Drawing.Color.White;
+            this.grpConfigurationRegister2.Controls.Add(this.lblConfigRegister2);
+            this.grpConfigurationRegister2.Controls.Add(this.chkShutdown2);
+            this.grpConfigurationRegister2.Controls.Add(this.chkComparatorInterrupt2);
+            this.grpConfigurationRegister2.Controls.Add(this.chkOSPolarity2);
+            this.grpConfigurationRegister2.Controls.Add(this.chkFaultQueue02);
+            this.grpConfigurationRegister2.Controls.Add(this.chkFaultQueue12);
+            this.grpConfigurationRegister2.Controls.Add(this.chkDataFormat2);
+            this.grpConfigurationRegister2.Controls.Add(this.chkTimeout2);
+            this.grpConfigurationRegister2.Controls.Add(this.chkOneShot2);
+            this.grpConfigurationRegister2.Controls.Add(this.label5);
+            this.grpConfigurationRegister2.Controls.Add(this.label6);
+            this.grpConfigurationRegister2.Font = new System.Drawing.Font("Arial", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+            this.grpConfigurationRegister2.Location = new System.Drawing.Point(544, 270);
+            this.grpConfigurationRegister2.Name = "grpConfigurationRegister2";
+            this.grpConfigurationRegister2.Size = new System.Drawing.Size(244, 250);
+            this.grpConfigurationRegister2.TabIndex = 13;
+            this.grpConfigurationRegister2.TabStop = false;
+            this.grpConfigurationRegister2.Text = "Configuration Register (Bottom)";
+            // 
+            // label5
+            // 
+            this.label5.AutoSize = true;
+            this.label5.Location = new System.Drawing.Point(45, 40);
+            this.label5.Name = "label5";
+            this.label5.Size = new System.Drawing.Size(57, 16);
+            this.label5.TabIndex = 11;
+            this.label5.Text = "_______";
+            // 
+            // lblConfigRegister2
+            // 
+            this.lblConfigRegister2.AutoSize = true;
+            this.lblConfigRegister2.Location = new System.Drawing.Point(84, 221);
+            this.lblConfigRegister2.Name = "lblConfigRegister2";
+            this.lblConfigRegister2.Size = new System.Drawing.Size(37, 16);
+            this.lblConfigRegister2.TabIndex = 9;
+            this.lblConfigRegister2.Text = "(00h)";
+            // 
+            // chkShutdown2
+            // 
+            this.chkShutdown2.AutoSize = true;
+            this.chkShutdown2.Location = new System.Drawing.Point(32, 205);
+            this.chkShutdown2.Name = "chkShutdown2";
+            this.chkShutdown2.Size = new System.Drawing.Size(84, 20);
+            this.chkShutdown2.TabIndex = 7;
+            this.chkShutdown2.Text = "Shutdown";
+            this.chkShutdown2.UseVisualStyleBackColor = true;
+            // 
+            // chkComparatorInterrupt2
+            // 
+            this.chkComparatorInterrupt2.AutoSize = true;
+            this.chkComparatorInterrupt2.Location = new System.Drawing.Point(32, 180);
+            this.chkComparatorInterrupt2.Name = "chkComparatorInterrupt2";
+            this.chkComparatorInterrupt2.Size = new System.Drawing.Size(145, 20);
+            this.chkComparatorInterrupt2.TabIndex = 6;
+            this.chkComparatorInterrupt2.Text = "Comparator/Interrupt";
+            this.chkComparatorInterrupt2.UseVisualStyleBackColor = true;
+            // 
+            // chkOSPolarity2
+            // 
+            this.chkOSPolarity2.AutoSize = true;
+            this.chkOSPolarity2.Location = new System.Drawing.Point(32, 155);
+            this.chkOSPolarity2.Name = "chkOSPolarity2";
+            this.chkOSPolarity2.Size = new System.Drawing.Size(94, 20);
+            this.chkOSPolarity2.TabIndex = 5;
+            this.chkOSPolarity2.Text = "OS Polarity";
+            this.chkOSPolarity2.UseVisualStyleBackColor = true;
+            // 
+            // chkFaultQueue02
+            // 
+            this.chkFaultQueue02.AutoSize = true;
+            this.chkFaultQueue02.Location = new System.Drawing.Point(32, 131);
+            this.chkFaultQueue02.Name = "chkFaultQueue02";
+            this.chkFaultQueue02.Size = new System.Drawing.Size(117, 20);
+            this.chkFaultQueue02.TabIndex = 4;
+            this.chkFaultQueue02.Text = "Fault Queue [0]";
+            this.chkFaultQueue02.UseVisualStyleBackColor = true;
+            // 
+            // chkFaultQueue12
+            // 
+            this.chkFaultQueue12.AutoSize = true;
+            this.chkFaultQueue12.Location = new System.Drawing.Point(32, 105);
+            this.chkFaultQueue12.Name = "chkFaultQueue12";
+            this.chkFaultQueue12.Size = new System.Drawing.Size(117, 20);
+            this.chkFaultQueue12.TabIndex = 3;
+            this.chkFaultQueue12.Text = "Fault Queue [1]";
+            this.chkFaultQueue12.UseVisualStyleBackColor = true;
+            // 
+            // chkDataFormat2
+            // 
+            this.chkDataFormat2.AutoSize = true;
+            this.chkDataFormat2.Location = new System.Drawing.Point(32, 80);
+            this.chkDataFormat2.Name = "chkDataFormat2";
+            this.chkDataFormat2.Size = new System.Drawing.Size(99, 20);
+            this.chkDataFormat2.TabIndex = 2;
+            this.chkDataFormat2.Text = "Data Format";
+            this.chkDataFormat2.UseVisualStyleBackColor = true;
+            this.chkDataFormat2.Click += new System.EventHandler(this.chkDataFormat1_Click);
+            // 
+            // chkTimeout2
+            // 
+            this.chkTimeout2.AutoSize = true;
+            this.chkTimeout2.Location = new System.Drawing.Point(32, 55);
+            this.chkTimeout2.Name = "chkTimeout2";
+            this.chkTimeout2.Size = new System.Drawing.Size(73, 20);
+            this.chkTimeout2.TabIndex = 1;
+            this.chkTimeout2.Text = "Timeout";
+            this.chkTimeout2.UseVisualStyleBackColor = true;
+            // 
+            // chkOneShot2
+            // 
+            this.chkOneShot2.AutoSize = true;
+            this.chkOneShot2.Location = new System.Drawing.Point(32, 29);
+            this.chkOneShot2.Name = "chkOneShot2";
+            this.chkOneShot2.Size = new System.Drawing.Size(82, 20);
+            this.chkOneShot2.TabIndex = 0;
+            this.chkOneShot2.Text = "One-Shot";
+            this.chkOneShot2.UseVisualStyleBackColor = true;
+            // 
+            // label6
+            // 
+            this.label6.AutoSize = true;
+            this.label6.Location = new System.Drawing.Point(46, 165);
+            this.label6.Name = "label6";
+            this.label6.Size = new System.Drawing.Size(78, 16);
+            this.label6.TabIndex = 11;
+            this.label6.Text = "__________";
+            // 
+            // maximGroupBox12
+            // 
+            this.maximGroupBox12.BackgroundColor = System.Drawing.Color.White;
+            this.maximGroupBox12.Controls.Add(this.lblUnits4);
+            this.maximGroupBox12.Controls.Add(this.lblUnits3);
+            this.maximGroupBox12.Controls.Add(this.lblHysteresis2);
+            this.maximGroupBox12.Controls.Add(this.lblOvertemperature2);
+            this.maximGroupBox12.Controls.Add(this.txtHysteresis2);
+            this.maximGroupBox12.Controls.Add(this.txtOvertemperature2);
+            this.maximGroupBox12.Controls.Add(this.label41);
+            this.maximGroupBox12.Controls.Add(this.label42);
+            this.maximGroupBox12.Font = new System.Drawing.Font("Arial", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+            this.maximGroupBox12.Location = new System.Drawing.Point(544, 123);
+            this.maximGroupBox12.Name = "maximGroupBox12";
+            this.maximGroupBox12.Size = new System.Drawing.Size(244, 141);
+            this.maximGroupBox12.TabIndex = 14;
+            this.maximGroupBox12.TabStop = false;
+            this.maximGroupBox12.Text = "Overtemperature Shutdown (Bottom)";
+            // 
+            // lblUnits4
+            // 
+            this.lblUnits4.AutoSize = true;
+            this.lblUnits4.Location = new System.Drawing.Point(86, 113);
+            this.lblUnits4.Name = "lblUnits4";
+            this.lblUnits4.Size = new System.Drawing.Size(22, 16);
+            this.lblUnits4.TabIndex = 11;
+            this.lblUnits4.Text = "°C";
+            // 
+            // lblUnits3
+            // 
+            this.lblUnits3.AutoSize = true;
+            this.lblUnits3.Location = new System.Drawing.Point(86, 54);
+            this.lblUnits3.Name = "lblUnits3";
+            this.lblUnits3.Size = new System.Drawing.Size(22, 16);
+            this.lblUnits3.TabIndex = 10;
+            this.lblUnits3.Text = "°C";
+            // 
+            // lblHysteresis2
+            // 
+            this.lblHysteresis2.AutoSize = true;
+            this.lblHysteresis2.Location = new System.Drawing.Point(113, 115);
+            this.lblHysteresis2.Name = "lblHysteresis2";
+            this.lblHysteresis2.Size = new System.Drawing.Size(53, 16);
+            this.lblHysteresis2.TabIndex = 5;
+            this.lblHysteresis2.Text = "(4B00h)";
+            // 
+            // lblOvertemperature2
+            // 
+            this.lblOvertemperature2.AutoSize = true;
+            this.lblOvertemperature2.Location = new System.Drawing.Point(113, 54);
+            this.lblOvertemperature2.Name = "lblOvertemperature2";
+            this.lblOvertemperature2.Size = new System.Drawing.Size(51, 16);
+            this.lblOvertemperature2.TabIndex = 4;
+            this.lblOvertemperature2.Text = "(5000h)";
+            // 
+            // txtHysteresis2
+            // 
+            this.errorProvider1.SetIconAlignment(this.txtHysteresis2, System.Windows.Forms.ErrorIconAlignment.MiddleLeft);
+            this.txtHysteresis2.Location = new System.Drawing.Point(22, 110);
+            this.txtHysteresis2.Name = "txtHysteresis2";
+            this.txtHysteresis2.Size = new System.Drawing.Size(63, 22);
+            this.txtHysteresis2.TabIndex = 3;
+            this.txtHysteresis2.Text = "75.00";
+            // 
+            // txtOvertemperature2
+            // 
+            this.errorProvider1.SetIconAlignment(this.txtOvertemperature2, System.Windows.Forms.ErrorIconAlignment.MiddleLeft);
+            this.txtOvertemperature2.Location = new System.Drawing.Point(22, 50);
+            this.txtOvertemperature2.Name = "txtOvertemperature2";
+            this.txtOvertemperature2.Size = new System.Drawing.Size(63, 22);
+            this.txtOvertemperature2.TabIndex = 2;
+            this.txtOvertemperature2.Text = "80.00";
+            // 
+            // label41
+            // 
+            this.label41.AutoSize = true;
+            this.label41.Location = new System.Drawing.Point(19, 92);
+            this.label41.Name = "label41";
+            this.label41.Size = new System.Drawing.Size(70, 16);
+            this.label41.TabIndex = 1;
+            this.label41.Text = "Hysteresis";
+            // 
+            // label42
+            // 
+            this.label42.AutoSize = true;
+            this.label42.Location = new System.Drawing.Point(19, 32);
+            this.label42.Name = "label42";
+            this.label42.Size = new System.Drawing.Size(103, 16);
+            this.label42.TabIndex = 0;
+            this.label42.Text = "Overtemperature";
+            // 
+            // maximGroupBox13
+            // 
+            this.maximGroupBox13.BackgroundColor = System.Drawing.Color.White;
+            this.maximGroupBox13.Controls.Add(this.lblTemperatureHex2);
+            this.maximGroupBox13.Controls.Add(this.lblUnits6);
+            this.maximGroupBox13.Controls.Add(this.lblTemperature2);
+            this.maximGroupBox13.Font = new System.Drawing.Font("Arial", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+            this.maximGroupBox13.Location = new System.Drawing.Point(544, 3);
+            this.maximGroupBox13.Name = "maximGroupBox13";
+            this.maximGroupBox13.Size = new System.Drawing.Size(244, 114);
+            this.maximGroupBox13.TabIndex = 12;
+            this.maximGroupBox13.TabStop = false;
+            this.maximGroupBox13.Text = "MAX30205 Temperature (Bottom)";
+            // 
+            // lblTemperatureHex2
+            // 
+            this.lblTemperatureHex2.AutoSize = true;
+            this.lblTemperatureHex2.Location = new System.Drawing.Point(97, 77);
+            this.lblTemperatureHex2.Name = "lblTemperatureHex2";
+            this.lblTemperatureHex2.Size = new System.Drawing.Size(51, 16);
+            this.lblTemperatureHex2.TabIndex = 3;
+            this.lblTemperatureHex2.Text = "(1900h)";
+            // 
+            // lblUnits6
+            // 
+            this.lblUnits6.AutoSize = true;
+            this.lblUnits6.Font = new System.Drawing.Font("Arial", 18F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+            this.lblUnits6.Location = new System.Drawing.Point(154, 43);
+            this.lblUnits6.Name = "lblUnits6";
+            this.lblUnits6.Size = new System.Drawing.Size(39, 27);
+            this.lblUnits6.TabIndex = 2;
+            this.lblUnits6.Text = "°C";
+            // 
+            // lblTemperature2
+            // 
+            this.lblTemperature2.AutoSize = true;
+            this.lblTemperature2.Font = new System.Drawing.Font("Arial", 18F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+            this.lblTemperature2.Location = new System.Drawing.Point(76, 43);
+            this.lblTemperature2.Name = "lblTemperature2";
+            this.lblTemperature2.Size = new System.Drawing.Size(67, 27);
+            this.lblTemperature2.TabIndex = 0;
+            this.lblTemperature2.Text = "---.---";
+            // 
+            // grpConfigurationRegister1
+            // 
+            this.grpConfigurationRegister1.BackgroundColor = System.Drawing.Color.White;
+            this.grpConfigurationRegister1.Controls.Add(this.lblConfigRegister1);
+            this.grpConfigurationRegister1.Controls.Add(this.chkShutdown1);
+            this.grpConfigurationRegister1.Controls.Add(this.chkFaultQueue01);
+            this.grpConfigurationRegister1.Controls.Add(this.chkFaultQueue11);
+            this.grpConfigurationRegister1.Controls.Add(this.chkDataFormat1);
+            this.grpConfigurationRegister1.Controls.Add(this.chkTimeout1);
+            this.grpConfigurationRegister1.Controls.Add(this.chkOSPolarity1);
+            this.grpConfigurationRegister1.Controls.Add(this.label4);
+            this.grpConfigurationRegister1.Controls.Add(this.chkOneShot1);
+            this.grpConfigurationRegister1.Controls.Add(this.label3);
+            this.grpConfigurationRegister1.Controls.Add(this.chkComparatorInterrupt1);
+            this.grpConfigurationRegister1.Font = new System.Drawing.Font("Arial", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+            this.grpConfigurationRegister1.Location = new System.Drawing.Point(285, 270);
+            this.grpConfigurationRegister1.Name = "grpConfigurationRegister1";
+            this.grpConfigurationRegister1.Size = new System.Drawing.Size(242, 250);
+            this.grpConfigurationRegister1.TabIndex = 10;
+            this.grpConfigurationRegister1.TabStop = false;
+            this.grpConfigurationRegister1.Text = "Configuration Register (Top)";
+            // 
+            // lblConfigRegister1
+            // 
+            this.lblConfigRegister1.AutoSize = true;
+            this.lblConfigRegister1.BackColor = System.Drawing.Color.White;
+            this.lblConfigRegister1.Location = new System.Drawing.Point(97, 223);
+            this.lblConfigRegister1.Name = "lblConfigRegister1";
+            this.lblConfigRegister1.Size = new System.Drawing.Size(37, 16);
+            this.lblConfigRegister1.TabIndex = 8;
+            this.lblConfigRegister1.Text = "(00h)";
+            // 
+            // chkShutdown1
+            // 
+            this.chkShutdown1.AutoSize = true;
+            this.chkShutdown1.BackColor = System.Drawing.Color.White;
+            this.chkShutdown1.Location = new System.Drawing.Point(32, 205);
+            this.chkShutdown1.Name = "chkShutdown1";
+            this.chkShutdown1.Size = new System.Drawing.Size(84, 20);
+            this.chkShutdown1.TabIndex = 7;
+            this.chkShutdown1.Text = "Shutdown";
+            this.chkShutdown1.UseVisualStyleBackColor = false;
+            // 
+            // chkFaultQueue01
+            // 
+            this.chkFaultQueue01.AutoSize = true;
+            this.chkFaultQueue01.BackColor = System.Drawing.Color.White;
+            this.chkFaultQueue01.Location = new System.Drawing.Point(32, 130);
+            this.chkFaultQueue01.Name = "chkFaultQueue01";
+            this.chkFaultQueue01.Size = new System.Drawing.Size(117, 20);
+            this.chkFaultQueue01.TabIndex = 4;
+            this.chkFaultQueue01.Text = "Fault Queue [0]";
+            this.chkFaultQueue01.UseVisualStyleBackColor = false;
+            // 
+            // chkFaultQueue11
+            // 
+            this.chkFaultQueue11.AutoSize = true;
+            this.chkFaultQueue11.BackColor = System.Drawing.Color.White;
+            this.chkFaultQueue11.Location = new System.Drawing.Point(32, 105);
+            this.chkFaultQueue11.Name = "chkFaultQueue11";
+            this.chkFaultQueue11.Size = new System.Drawing.Size(117, 20);
+            this.chkFaultQueue11.TabIndex = 3;
+            this.chkFaultQueue11.Text = "Fault Queue [1]";
+            this.chkFaultQueue11.UseVisualStyleBackColor = false;
+            // 
+            // chkDataFormat1
+            // 
+            this.chkDataFormat1.AutoSize = true;
+            this.chkDataFormat1.BackColor = System.Drawing.Color.White;
+            this.chkDataFormat1.Location = new System.Drawing.Point(32, 80);
+            this.chkDataFormat1.Name = "chkDataFormat1";
+            this.chkDataFormat1.Size = new System.Drawing.Size(99, 20);
+            this.chkDataFormat1.TabIndex = 2;
+            this.chkDataFormat1.Text = "Data Format";
+            this.chkDataFormat1.UseVisualStyleBackColor = false;
+            this.chkDataFormat1.Click += new System.EventHandler(this.chkDataFormat1_Click);
+            // 
+            // chkTimeout1
+            // 
+            this.chkTimeout1.AutoSize = true;
+            this.chkTimeout1.BackColor = System.Drawing.Color.White;
+            this.chkTimeout1.Location = new System.Drawing.Point(32, 55);
+            this.chkTimeout1.Name = "chkTimeout1";
+            this.chkTimeout1.Size = new System.Drawing.Size(73, 20);
+            this.chkTimeout1.TabIndex = 1;
+            this.chkTimeout1.Text = "Timeout";
+            this.chkTimeout1.UseVisualStyleBackColor = false;
+            // 
+            // chkOSPolarity1
+            // 
+            this.chkOSPolarity1.AutoSize = true;
+            this.chkOSPolarity1.BackColor = System.Drawing.Color.White;
+            this.chkOSPolarity1.Location = new System.Drawing.Point(32, 155);
+            this.chkOSPolarity1.Name = "chkOSPolarity1";
+            this.chkOSPolarity1.Size = new System.Drawing.Size(94, 20);
+            this.chkOSPolarity1.TabIndex = 5;
+            this.chkOSPolarity1.Text = "OS Polarity";
+            this.chkOSPolarity1.UseVisualStyleBackColor = false;
+            // 
+            // label4
+            // 
+            this.label4.AutoSize = true;
+            this.label4.Location = new System.Drawing.Point(47, 165);
+            this.label4.Name = "label4";
+            this.label4.Size = new System.Drawing.Size(78, 16);
+            this.label4.TabIndex = 10;
+            this.label4.Text = "__________";
+            // 
+            // chkOneShot1
+            // 
+            this.chkOneShot1.AutoSize = true;
+            this.chkOneShot1.BackColor = System.Drawing.Color.White;
+            this.chkOneShot1.Location = new System.Drawing.Point(32, 29);
+            this.chkOneShot1.Name = "chkOneShot1";
+            this.chkOneShot1.Size = new System.Drawing.Size(82, 20);
+            this.chkOneShot1.TabIndex = 0;
+            this.chkOneShot1.Text = "One-Shot";
+            this.chkOneShot1.UseVisualStyleBackColor = false;
+            // 
+            // label3
+            // 
+            this.label3.AutoSize = true;
+            this.label3.Location = new System.Drawing.Point(45, 40);
+            this.label3.Name = "label3";
+            this.label3.Size = new System.Drawing.Size(57, 16);
+            this.label3.TabIndex = 9;
+            this.label3.Text = "_______";
+            // 
+            // chkComparatorInterrupt1
+            // 
+            this.chkComparatorInterrupt1.AutoSize = true;
+            this.chkComparatorInterrupt1.BackColor = System.Drawing.Color.White;
+            this.chkComparatorInterrupt1.Location = new System.Drawing.Point(32, 179);
+            this.chkComparatorInterrupt1.Name = "chkComparatorInterrupt1";
+            this.chkComparatorInterrupt1.Size = new System.Drawing.Size(145, 20);
+            this.chkComparatorInterrupt1.TabIndex = 6;
+            this.chkComparatorInterrupt1.Text = "Comparator/Interrupt";
+            this.chkComparatorInterrupt1.UseVisualStyleBackColor = false;
+            // 
+            // maximGroupBox10
+            // 
+            this.maximGroupBox10.BackgroundColor = System.Drawing.Color.White;
+            this.maximGroupBox10.Controls.Add(this.lblUnits2);
+            this.maximGroupBox10.Controls.Add(this.lblUnits1);
+            this.maximGroupBox10.Controls.Add(this.lblHysteresis1);
+            this.maximGroupBox10.Controls.Add(this.lblOvertemperature1);
+            this.maximGroupBox10.Controls.Add(this.txtHysteresis1);
+            this.maximGroupBox10.Controls.Add(this.txtOvertemperature1);
+            this.maximGroupBox10.Controls.Add(this.label36);
+            this.maximGroupBox10.Controls.Add(this.label34);
+            this.maximGroupBox10.Font = new System.Drawing.Font("Arial", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+            this.maximGroupBox10.Location = new System.Drawing.Point(285, 123);
+            this.maximGroupBox10.Name = "maximGroupBox10";
+            this.maximGroupBox10.Size = new System.Drawing.Size(242, 141);
+            this.maximGroupBox10.TabIndex = 11;
+            this.maximGroupBox10.TabStop = false;
+            this.maximGroupBox10.Text = "Overtemperature Shutdown (Top)";
+            // 
+            // lblUnits2
+            // 
+            this.lblUnits2.AutoSize = true;
+            this.lblUnits2.BackColor = System.Drawing.Color.White;
+            this.lblUnits2.Location = new System.Drawing.Point(85, 113);
+            this.lblUnits2.Name = "lblUnits2";
+            this.lblUnits2.Size = new System.Drawing.Size(22, 16);
+            this.lblUnits2.TabIndex = 9;
+            this.lblUnits2.Text = "°C";
+            // 
+            // lblUnits1
+            // 
+            this.lblUnits1.AutoSize = true;
+            this.lblUnits1.BackColor = System.Drawing.Color.White;
+            this.lblUnits1.Location = new System.Drawing.Point(87, 54);
+            this.lblUnits1.Name = "lblUnits1";
+            this.lblUnits1.Size = new System.Drawing.Size(22, 16);
+            this.lblUnits1.TabIndex = 8;
+            this.lblUnits1.Text = "°C";
+            // 
+            // lblHysteresis1
+            // 
+            this.lblHysteresis1.AutoSize = true;
+            this.lblHysteresis1.BackColor = System.Drawing.Color.White;
+            this.lblHysteresis1.Location = new System.Drawing.Point(119, 113);
+            this.lblHysteresis1.Name = "lblHysteresis1";
+            this.lblHysteresis1.Size = new System.Drawing.Size(53, 16);
+            this.lblHysteresis1.TabIndex = 5;
+            this.lblHysteresis1.Text = "(4B00h)";
+            // 
+            // lblOvertemperature1
+            // 
+            this.lblOvertemperature1.AutoSize = true;
+            this.lblOvertemperature1.BackColor = System.Drawing.Color.White;
+            this.lblOvertemperature1.Location = new System.Drawing.Point(119, 54);
+            this.lblOvertemperature1.Name = "lblOvertemperature1";
+            this.lblOvertemperature1.Size = new System.Drawing.Size(51, 16);
+            this.lblOvertemperature1.TabIndex = 4;
+            this.lblOvertemperature1.Text = "(5000h)";
+            // 
+            // txtHysteresis1
+            // 
+            this.errorProvider1.SetIconAlignment(this.txtHysteresis1, System.Windows.Forms.ErrorIconAlignment.MiddleLeft);
+            this.txtHysteresis1.Location = new System.Drawing.Point(22, 110);
+            this.txtHysteresis1.Name = "txtHysteresis1";
+            this.txtHysteresis1.Size = new System.Drawing.Size(63, 22);
+            this.txtHysteresis1.TabIndex = 3;
+            this.txtHysteresis1.Text = "75.00";
+            // 
+            // txtOvertemperature1
+            // 
+            this.errorProvider1.SetIconAlignment(this.txtOvertemperature1, System.Windows.Forms.ErrorIconAlignment.MiddleLeft);
+            this.txtOvertemperature1.Location = new System.Drawing.Point(22, 50);
+            this.txtOvertemperature1.Name = "txtOvertemperature1";
+            this.txtOvertemperature1.Size = new System.Drawing.Size(63, 22);
+            this.txtOvertemperature1.TabIndex = 2;
+            this.txtOvertemperature1.Text = "80.00";
+            // 
+            // label36
+            // 
+            this.label36.AutoSize = true;
+            this.label36.BackColor = System.Drawing.Color.White;
+            this.label36.Location = new System.Drawing.Point(19, 92);
+            this.label36.Name = "label36";
+            this.label36.Size = new System.Drawing.Size(70, 16);
+            this.label36.TabIndex = 1;
+            this.label36.Text = "Hysteresis";
+            // 
+            // label34
+            // 
+            this.label34.AutoSize = true;
+            this.label34.BackColor = System.Drawing.Color.White;
+            this.label34.Location = new System.Drawing.Point(19, 32);
+            this.label34.Name = "label34";
+            this.label34.Size = new System.Drawing.Size(103, 16);
+            this.label34.TabIndex = 0;
+            this.label34.Text = "Overtemperature";
+            // 
+            // maximGroupBox8
+            // 
+            this.maximGroupBox8.BackgroundColor = System.Drawing.Color.White;
+            this.maximGroupBox8.Controls.Add(this.lblTemperature1);
+            this.maximGroupBox8.Controls.Add(this.lblTemperatureHex1);
+            this.maximGroupBox8.Controls.Add(this.lblUnits5);
+            this.maximGroupBox8.Font = new System.Drawing.Font("Arial", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+            this.maximGroupBox8.Location = new System.Drawing.Point(285, 3);
+            this.maximGroupBox8.Name = "maximGroupBox8";
+            this.maximGroupBox8.Size = new System.Drawing.Size(242, 114);
+            this.maximGroupBox8.TabIndex = 9;
+            this.maximGroupBox8.TabStop = false;
+            this.maximGroupBox8.Text = "MAX30205 Temperature (Top)";
+            // 
+            // lblTemperature1
+            // 
+            this.lblTemperature1.BackColor = System.Drawing.Color.White;
+            this.lblTemperature1.Font = new System.Drawing.Font("Arial", 18F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+            this.lblTemperature1.Location = new System.Drawing.Point(52, 40);
+            this.lblTemperature1.Name = "lblTemperature1";
+            this.lblTemperature1.Size = new System.Drawing.Size(98, 29);
+            this.lblTemperature1.TabIndex = 0;
+            this.lblTemperature1.Text = "---.---";
+            this.lblTemperature1.TextAlign = System.Drawing.ContentAlignment.MiddleRight;
+            this.lblTemperature1.Click += new System.EventHandler(this.lblTemperature1_Click);
+            // 
+            // lblTemperatureHex1
+            // 
+            this.lblTemperatureHex1.AutoSize = true;
+            this.lblTemperatureHex1.BackColor = System.Drawing.Color.White;
+            this.lblTemperatureHex1.Location = new System.Drawing.Point(93, 77);
+            this.lblTemperatureHex1.Name = "lblTemperatureHex1";
+            this.lblTemperatureHex1.Size = new System.Drawing.Size(51, 16);
+            this.lblTemperatureHex1.TabIndex = 2;
+            this.lblTemperatureHex1.Text = "(1900h)";
+            // 
+            // lblUnits5
+            // 
+            this.lblUnits5.AutoSize = true;
+            this.lblUnits5.BackColor = System.Drawing.Color.White;
+            this.lblUnits5.Font = new System.Drawing.Font("Arial", 18F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+            this.lblUnits5.Location = new System.Drawing.Point(145, 41);
+            this.lblUnits5.Name = "lblUnits5";
+            this.lblUnits5.Size = new System.Drawing.Size(39, 27);
+            this.lblUnits5.TabIndex = 1;
+            this.lblUnits5.Text = "°C";
+            // 
+            // maximGroupBox7
+            // 
+            this.maximGroupBox7.BackgroundColor = System.Drawing.Color.White;
+            this.maximGroupBox7.Controls.Add(this.maximButton1);
+            this.maximGroupBox7.Controls.Add(this.label2);
+            this.maximGroupBox7.Controls.Add(this.cboRefreshRate);
+            this.maximGroupBox7.Controls.Add(this.label1);
+            this.maximGroupBox7.Controls.Add(this.tglCelsiusFahrenheit);
+            this.maximGroupBox7.Font = new System.Drawing.Font("Arial", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+            this.maximGroupBox7.Location = new System.Drawing.Point(25, 3);
+            this.maximGroupBox7.Name = "maximGroupBox7";
+            this.maximGroupBox7.Size = new System.Drawing.Size(242, 114);
+            this.maximGroupBox7.TabIndex = 8;
+            this.maximGroupBox7.TabStop = false;
+            this.maximGroupBox7.Text = "Settings";
+            // 
+            // maximButton1
+            // 
+            this.maximButton1.Location = new System.Drawing.Point(54, 80);
+            this.maximButton1.Name = "maximButton1";
+            this.maximButton1.Size = new System.Drawing.Size(128, 28);
+            this.maximButton1.TabIndex = 4;
+            this.maximButton1.Text = "Read All Registers";
+            this.maximButton1.UseVisualStyleBackColor = true;
+            this.maximButton1.Click += new System.EventHandler(this.maximButton1_Click);
+            // 
+            // label2
+            // 
+            this.label2.AutoSize = true;
+            this.label2.BackColor = System.Drawing.Color.White;
+            this.label2.Location = new System.Drawing.Point(183, 55);
+            this.label2.Name = "label2";
+            this.label2.Size = new System.Drawing.Size(15, 16);
+            this.label2.TabIndex = 3;
+            this.label2.Text = "s";
+            // 
+            // cboRefreshRate
+            // 
+            this.cboRefreshRate.BackColor = System.Drawing.Color.White;
+            this.cboRefreshRate.DropDownHeight = 200;
+            this.cboRefreshRate.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
+            this.cboRefreshRate.DropDownWidth = 50;
+            this.cboRefreshRate.Items.AddRange(new object[] {
+            "10",
+            "20",
+            "30",
+            "40",
+            "50",
+            "60"});
+            this.cboRefreshRate.Location = new System.Drawing.Point(127, 53);
+            this.cboRefreshRate.Name = "cboRefreshRate";
+            this.cboRefreshRate.Size = new System.Drawing.Size(50, 21);
+            this.cboRefreshRate.TabIndex = 2;
+            this.cboRefreshRate.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
+            this.cboRefreshRate.TextAlignDropDownList = System.Windows.Forms.HorizontalAlignment.Left;
+            this.cboRefreshRate.SelectedIndexChanged += new System.EventHandler(this.cboRefreshRate_SelectedIndexChanged);
+            // 
+            // label1
+            // 
+            this.label1.AutoSize = true;
+            this.label1.BackColor = System.Drawing.Color.White;
+            this.label1.Location = new System.Drawing.Point(43, 56);
+            this.label1.Name = "label1";
+            this.label1.Size = new System.Drawing.Size(91, 16);
+            this.label1.TabIndex = 1;
+            this.label1.Text = "Refresh Rate: ";
+            // 
+            // tglCelsiusFahrenheit
+            // 
+            this.tglCelsiusFahrenheit.AutoSize = true;
+            this.tglCelsiusFahrenheit.Location = new System.Drawing.Point(50, 28);
+            this.tglCelsiusFahrenheit.Name = "tglCelsiusFahrenheit";
+            this.tglCelsiusFahrenheit.Size = new System.Drawing.Size(147, 21);
+            this.tglCelsiusFahrenheit.TabIndex = 0;
+            this.tglCelsiusFahrenheit.Text = "Celsius/Fahrenheit";
+            this.tglCelsiusFahrenheit.UseVisualStyleBackColor = true;
+            this.tglCelsiusFahrenheit.CheckedChanged += new System.EventHandler(this.tglCelsiusFahrenheit_CheckedChanged_1);
+            // 
+            // errorProvider1
+            // 
+            this.errorProvider1.ContainerControl = this;
+            // 
+            // timer1
+            // 
+            this.timer1.Enabled = true;
+            this.timer1.Interval = 20000;
+            this.timer1.Tick += new System.EventHandler(this.timer1_Tick);
+            // 
+            // label7
+            // 
+            this.label7.Location = new System.Drawing.Point(25, 123);
+            this.label7.Name = "label7";
+            this.label7.Size = new System.Drawing.Size(206, 86);
+            this.label7.TabIndex = 15;
+            this.label7.Text = "Note: The top temperature sensor is the side which contains the power switch and " +
+    "LED. The bottom side contains the optical sensor module.";
+            // 
+            // TemperatureView
+            // 
+            this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
+            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+            this.Controls.Add(this.label7);
+            this.Controls.Add(this.grpConfigurationRegister1);
+            this.Controls.Add(this.grpConfigurationRegister2);
+            this.Controls.Add(this.maximGroupBox12);
+            this.Controls.Add(this.maximGroupBox13);
+            this.Controls.Add(this.maximGroupBox7);
+            this.Controls.Add(this.maximGroupBox10);
+            this.Controls.Add(this.maximGroupBox8);
+            this.Name = "TemperatureView";
+            this.Size = new System.Drawing.Size(804, 529);
+            this.grpConfigurationRegister2.ResumeLayout(false);
+            this.grpConfigurationRegister2.PerformLayout();
+            this.maximGroupBox12.ResumeLayout(false);
+            this.maximGroupBox12.PerformLayout();
+            this.maximGroupBox13.ResumeLayout(false);
+            this.maximGroupBox13.PerformLayout();
+            this.grpConfigurationRegister1.ResumeLayout(false);
+            this.grpConfigurationRegister1.PerformLayout();
+            this.maximGroupBox10.ResumeLayout(false);
+            this.maximGroupBox10.PerformLayout();
+            this.maximGroupBox8.ResumeLayout(false);
+            this.maximGroupBox8.PerformLayout();
+            this.maximGroupBox7.ResumeLayout(false);
+            this.maximGroupBox7.PerformLayout();
+            ((System.ComponentModel.ISupportInitialize)(this.errorProvider1)).EndInit();
+            this.ResumeLayout(false);
+
+        }
+
+        #endregion
+
+        private MaximStyle.MaximGroupBox grpConfigurationRegister2;
+        private MaximStyle.MaximCheckBox chkShutdown2;
+        private MaximStyle.MaximCheckBox chkComparatorInterrupt2;
+        private MaximStyle.MaximCheckBox chkOSPolarity2;
+        private MaximStyle.MaximCheckBox chkFaultQueue02;
+        private MaximStyle.MaximCheckBox chkFaultQueue12;
+        private MaximStyle.MaximCheckBox chkDataFormat2;
+        private MaximStyle.MaximCheckBox chkTimeout2;
+        private MaximStyle.MaximCheckBox chkOneShot2;
+        private MaximStyle.MaximGroupBox maximGroupBox12;
+        private System.Windows.Forms.Label lblUnits4;
+        private System.Windows.Forms.Label lblUnits3;
+        private System.Windows.Forms.Label lblHysteresis2;
+        private System.Windows.Forms.Label lblOvertemperature2;
+        private System.Windows.Forms.TextBox txtHysteresis2;
+        private System.Windows.Forms.TextBox txtOvertemperature2;
+        private System.Windows.Forms.Label label41;
+        private System.Windows.Forms.Label label42;
+        private MaximStyle.MaximGroupBox maximGroupBox13;
+        private System.Windows.Forms.Label lblTemperatureHex2;
+        private System.Windows.Forms.Label lblUnits6;
+        private System.Windows.Forms.Label lblTemperature2;
+        private MaximStyle.MaximGroupBox grpConfigurationRegister1;
+        private MaximStyle.MaximCheckBox chkShutdown1;
+        private MaximStyle.MaximCheckBox chkComparatorInterrupt1;
+        private MaximStyle.MaximCheckBox chkOSPolarity1;
+        private MaximStyle.MaximCheckBox chkFaultQueue01;
+        private MaximStyle.MaximCheckBox chkFaultQueue11;
+        private MaximStyle.MaximCheckBox chkDataFormat1;
+        private MaximStyle.MaximCheckBox chkTimeout1;
+        private MaximStyle.MaximCheckBox chkOneShot1;
+        private MaximStyle.MaximGroupBox maximGroupBox10;
+        private System.Windows.Forms.Label lblUnits2;
+        private System.Windows.Forms.Label lblUnits1;
+        private System.Windows.Forms.Label lblHysteresis1;
+        private System.Windows.Forms.Label lblOvertemperature1;
+        private System.Windows.Forms.TextBox txtHysteresis1;
+        private System.Windows.Forms.TextBox txtOvertemperature1;
+        private System.Windows.Forms.Label label36;
+        private System.Windows.Forms.Label label34;
+        private MaximStyle.MaximGroupBox maximGroupBox8;
+        private System.Windows.Forms.Label lblTemperatureHex1;
+        private System.Windows.Forms.Label lblUnits5;
+        private System.Windows.Forms.Label lblTemperature1;
+        private MaximStyle.MaximGroupBox maximGroupBox7;
+        private MaximStyle.MaximToggleButton tglCelsiusFahrenheit;
+        private System.Windows.Forms.ErrorProvider errorProvider1;
+        private System.Windows.Forms.Timer timer1;
+        private System.Windows.Forms.Label lblConfigRegister2;
+        private System.Windows.Forms.Label lblConfigRegister1;
+        private MaximStyle.MaximComboBox cboRefreshRate;
+        private System.Windows.Forms.Label label1;
+        private MaximStyle.MaximButton maximButton1;
+        private System.Windows.Forms.Label label2;
+        private System.Windows.Forms.Label label4;
+        private System.Windows.Forms.Label label3;
+        private System.Windows.Forms.Label label5;
+        private System.Windows.Forms.Label label6;
+        private System.Windows.Forms.Label label7;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HspGuiSourceV301/HSPGui/CustomControls/TemperatureView.cs	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,571 @@
+/*******************************************************************************
+* Copyright (C) 2016 Maxim Integrated Products, Inc., All rights Reserved.
+* 
+* This software is protected by copyright laws of the United States and
+* of foreign countries. This material may also be protected by patent laws
+* and technology transfer regulations of the United States and of foreign
+* countries. This software is furnished under a license agreement and/or a
+* nondisclosure agreement and may only be used or reproduced in accordance
+* with the terms of those agreements. Dissemination of this information to
+* any party or parties not specified in the license agreement and/or
+* nondisclosure agreement is expressly prohibited.
+*
+* The above copyright notice and this permission notice shall be included
+* in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+* OTHER DEALINGS IN THE SOFTWARE.
+*
+* Except as contained in this notice, the name of Maxim Integrated
+* Products, Inc. shall not be used except as stated in the Maxim Integrated
+* Products, Inc. Branding Policy.
+*
+* The mere transfer of this software does not imply any licenses
+* of trade secrets, proprietary technology, copyrights, patents,
+* trademarks, maskwork rights, or any other form of intellectual
+* property whatsoever. Maxim Integrated Products, Inc. retains all
+* ownership rights.
+*******************************************************************************
+*/
+
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Drawing;
+using System.Data;
+using System.Linq;
+using System.Text;
+using System.Windows.Forms;
+using MaximStyle;
+using MAX30205EVKit.View;
+
+namespace HealthSensorPlatform.CustomControls
+{
+    public partial class TemperatureView : UserControl, ITemperatureView, IDeviceView
+    {
+        List<MaximCheckBox> temperatureConfigRegister1;
+        List<MaximCheckBox> temperatureConfigRegister2;
+
+        bool unitsCelsius = true;
+        int refreshRate = 10;
+        double temperature1C = 25;
+        //int temperature1Hex;
+        double temperature2C = 25;
+
+        static string degreeCUnit = "°C";
+        static string degreeFUnit = "°F";
+        static string blankTemperature = "--.---";
+
+        public static bool I2CErrorShown;
+
+        bool internalUpdate = false;
+        
+
+        public event EventHandler<EventArgs> ReadAll;
+        public event EventHandler<EventArgs> UnitsChanged;
+        public event EventHandler<EventArgs> RequestReadTemperature;
+        public event EventHandler<WriteRegisterEventArgs> WriteRegister;
+        public event EventHandler<TemperatureEventArgs> OverTemperatureChanged;
+        public event EventHandler<TemperatureEventArgs> HystersisChanged;
+        public event EventHandler<DataFormatEventArgs> DataFormatChanged;
+
+        public TemperatureView()
+        {
+            InitializeComponent();
+
+            temperatureInitialize();
+            temperatureEventsInitialize();
+        }
+
+        public bool UnitsCelsius
+        {
+            get
+            {
+                return unitsCelsius;
+            }
+        }
+
+        public int RefreshRate
+        {
+            get
+            {
+                return refreshRate;
+            }
+            set
+            {
+                refreshRate = value;
+                cboRefreshRate.Text = refreshRate.ToString();
+                timer1.Interval = value * 1000;
+            }
+        }
+
+        public bool Connected { get; set; }
+
+        public void DisplayTemperature(int index, TemperatureValue tempValue)
+        {
+            double temperature;
+            int hex;
+
+            if (unitsCelsius)
+                temperature = tempValue.TemperatureC;
+            else
+                temperature = tempValue.TemperatureF;
+
+            hex = tempValue.TemperatureHex;
+
+            if (index == 0)
+            {
+                temperature1C = tempValue.TemperatureC;
+                lblTemperature1.Text = temperature.ToString("F3");
+                lblTemperatureHex1.Text = "(" + hex.ToString("X4") + "h)";
+            }
+            else if (index == 1)
+            {
+                temperature2C = tempValue.TemperatureC;
+                lblTemperature2.Text = temperature.ToString("F3");
+                lblTemperatureHex2.Text = "(" + hex.ToString("X4") + "h)";
+            }
+        }
+
+        public void DisplayHysteresis(int index, TemperatureValue tempValue)
+        {
+            double temperature;
+            int hex;
+
+            if (unitsCelsius)
+                temperature = tempValue.TemperatureC;
+            else
+                temperature = tempValue.TemperatureF;
+
+            hex = tempValue.TemperatureHex;
+
+            if (index == 0)
+            {
+                txtHysteresis1.Text = temperature.ToString("F2");
+                lblHysteresis1.Text = "(" + hex.ToString("X4") + "h)";
+            }
+            else if (index == 1)
+            {
+                txtHysteresis2.Text = temperature.ToString("F2");
+                lblHysteresis2.Text = "(" + hex.ToString("X4") + "h)";
+            }
+        }
+
+        public void DisplayOverTemperature(int index, TemperatureValue tempValue)
+        {
+            double temperature;
+            int hex;
+
+            if (unitsCelsius)
+                temperature = tempValue.TemperatureC;
+            else
+                temperature = tempValue.TemperatureF;
+
+            hex = tempValue.TemperatureHex;
+
+            if (index == 0)
+            {
+                txtOvertemperature1.Text = temperature.ToString("F2");
+                lblOvertemperature1.Text = "(" + hex.ToString("X4") + "h)";
+            }
+            else if (index == 1)
+            {
+                txtOvertemperature2.Text = temperature.ToString("F2");
+                lblOvertemperature2.Text = "(" + hex.ToString("X4") + "h)";
+            }
+        }
+
+        public void DisplayConfigurationRegister(int index, int hex)
+        {
+            if (index == 0)
+            {
+                byteToConfigurationCheckBoxes((byte)hex, temperatureConfigRegister1);
+            }
+            else if (index == 1)
+            {
+                byteToConfigurationCheckBoxes((byte)hex, temperatureConfigRegister2);
+
+            }
+        }
+
+        public void DisplayError(Control control, string message)
+        {
+            if (control!= null)
+                errorProvider1.SetError(control, message);
+        }
+
+        public void TimerState(bool state)
+        {
+            timer1.Enabled = state;
+        }
+
+
+        #region Temperature Tab UI
+        void temperatureInitialize()
+        {
+            temperatureConfigRegister1 = new List<MaximCheckBox>();
+            temperatureConfigRegister2 = new List<MaximCheckBox>();
+
+            temperatureConfigRegister1.Add(chkOneShot1);
+            temperatureConfigRegister1.Add(chkTimeout1);
+            temperatureConfigRegister1.Add(chkDataFormat1);
+            temperatureConfigRegister1.Add(chkFaultQueue11);
+            temperatureConfigRegister1.Add(chkFaultQueue01);
+            temperatureConfigRegister1.Add(chkOSPolarity1);
+            temperatureConfigRegister1.Add(chkComparatorInterrupt1);
+            temperatureConfigRegister1.Add(chkShutdown1);
+
+            temperatureConfigRegister2.Add(chkOneShot2);
+            temperatureConfigRegister2.Add(chkTimeout2);
+            temperatureConfigRegister2.Add(chkDataFormat2);
+            temperatureConfigRegister2.Add(chkFaultQueue12);
+            temperatureConfigRegister2.Add(chkFaultQueue02);
+            temperatureConfigRegister2.Add(chkOSPolarity2);
+            temperatureConfigRegister2.Add(chkComparatorInterrupt2);
+            temperatureConfigRegister2.Add(chkShutdown2);
+
+            cboRefreshRate.SelectedIndex = 0;
+        }
+
+        void temperatureEventsInitialize()
+        {
+            tglCelsiusFahrenheit.CheckedChanged += new System.EventHandler(tglCelsiusFahrenheit_CheckedChanged);
+            txtOvertemperature1.Leave += new System.EventHandler(temperatureRegisters_Leave);
+            txtOvertemperature2.Leave += new System.EventHandler(temperatureRegisters_Leave);
+            txtHysteresis1.Leave += new System.EventHandler(temperatureRegisters_Leave);
+            txtHysteresis2.Leave += new System.EventHandler(temperatureRegisters_Leave);
+            
+            foreach (MaximCheckBox cb in temperatureConfigRegister1)
+            {
+                cb.CheckedChanged += new System.EventHandler(configurationRegister_CheckedChanged);
+            }
+
+            foreach (MaximCheckBox cb in temperatureConfigRegister2)
+            {
+                cb.CheckedChanged += new System.EventHandler(configurationRegister_CheckedChanged);
+            }
+        }
+
+        void convertUnits(bool celsius)
+        {
+            if (celsius == true)
+            {
+                lblUnits1.Text = degreeCUnit;
+                lblUnits2.Text = degreeCUnit;
+                lblUnits3.Text = degreeCUnit;
+                lblUnits4.Text = degreeCUnit;
+                lblUnits5.Text = degreeCUnit;
+                lblUnits6.Text = degreeCUnit;
+
+                //lblTemperature1.Text = fahrenheitToCelsius(Convert.ToDouble(lblTemperature1.Text)).ToString("F2");
+                //lblTemperature2.Text = fahrenheitToCelsius(Convert.ToDouble(lblTemperature2.Text)).ToString("F2");
+                //lblTemperature1.Text = blankTemperature;
+                //lblTemperature2.Text = blankTemperature;
+
+                txtOvertemperature1.Text = fahrenheitToCelsius(Convert.ToDouble(txtOvertemperature1.Text)).ToString("F2");
+                txtOvertemperature2.Text = fahrenheitToCelsius(Convert.ToDouble(txtOvertemperature2.Text)).ToString("F2");
+
+                txtHysteresis1.Text = fahrenheitToCelsius(Convert.ToDouble(txtHysteresis1.Text)).ToString("F2");
+                txtHysteresis2.Text = fahrenheitToCelsius(Convert.ToDouble(txtHysteresis2.Text)).ToString("F2");
+            }
+            else
+            {
+                lblUnits1.Text = degreeFUnit;
+                lblUnits2.Text = degreeFUnit;
+                lblUnits3.Text = degreeFUnit;
+                lblUnits4.Text = degreeFUnit;
+                lblUnits5.Text = degreeFUnit;
+                lblUnits6.Text = degreeFUnit;
+
+                //lblTemperature1.Text = celsiusToFahrenheit(Convert.ToDouble(lblTemperature1.Text)).ToString("F2");
+                //lblTemperature2.Text = celsiusToFahrenheit(Convert.ToDouble(lblTemperature2.Text)).ToString("F2");
+                //lblTemperature1.Text = blankTemperature;
+                //lblTemperature2.Text = blankTemperature;
+
+                txtOvertemperature1.Text = celsiusToFahrenheit(Convert.ToDouble(txtOvertemperature1.Text)).ToString("F2");
+                txtOvertemperature2.Text = celsiusToFahrenheit(Convert.ToDouble(txtOvertemperature2.Text)).ToString("F2");
+
+                txtHysteresis1.Text = celsiusToFahrenheit(Convert.ToDouble(txtHysteresis1.Text)).ToString("F2");
+                txtHysteresis2.Text = celsiusToFahrenheit(Convert.ToDouble(txtHysteresis2.Text)).ToString("F2");
+            }
+        }
+
+        void configurationRegisterToByte()
+        {
+            int config1, config2;
+
+            config1 =
+                ((chkOneShot1.Checked == true ? 1 : 0) << 7) |
+                ((chkTimeout1.Checked == true ? 1 : 0) << 6) |
+                ((chkDataFormat1.Checked == true ? 1 : 0) << 5) |
+                ((chkFaultQueue11.Checked == true ? 1 : 0) << 4) |
+                ((chkFaultQueue01.Checked == true ? 1 : 0) << 3) |
+                ((chkOSPolarity1.Checked == true ? 1 : 0) << 2) |
+                ((chkComparatorInterrupt1.Checked == true ? 1 : 0) << 1) |
+                ((chkShutdown1.Checked == true ? 1 : 0) << 0);
+
+            config2 =
+                ((chkOneShot2.Checked == true ? 1 : 0) << 7) |
+                ((chkTimeout2.Checked == true ? 1 : 0) << 6) |
+                ((chkDataFormat2.Checked == true ? 1 : 0) << 5) |
+                ((chkFaultQueue12.Checked == true ? 1 : 0) << 4) |
+                ((chkFaultQueue02.Checked == true ? 1 : 0) << 3) |
+                ((chkOSPolarity2.Checked == true ? 1 : 0) << 2) |
+                ((chkComparatorInterrupt2.Checked == true ? 1 : 0) << 1) |
+                ((chkShutdown2.Checked == true ? 1 : 0) << 0);
+
+            lblConfigRegister1.Text = configurationByteToString((byte)config1);
+            lblConfigRegister2.Text = configurationByteToString((byte)config2);
+
+            if (WriteRegister != null && !internalUpdate)
+            {
+                WriteRegister(this, new WriteRegisterEventArgs() { Index = 0, Register = 0x01, Data = config1 });
+                WriteRegister(this, new WriteRegisterEventArgs() { Index = 1, Register = 0x01, Data = config2 });
+            }
+        }
+
+        string configurationByteToString(byte hex)
+        {
+            return "(" + hex.ToString("X2") + "h)";
+        }
+
+        void byteToConfigurationCheckBoxes(byte hex, List<MaximCheckBox> list)
+        {
+            internalUpdate = true;
+            for (int i = 0; i < 8; i++ )
+            {
+                list[i].Checked = (hex & (1 << (7 - i))) == (1 << (7 - i));
+            }
+            internalUpdate = false;
+        }
+
+        #endregion
+
+        #region Helper Functions
+        double celsiusToFahrenheit(double temperature)
+        {
+            return temperature * 9 / 5 + 32;
+        }
+
+        double fahrenheitToCelsius(double temperature)
+        {
+            return (temperature - 32) * 5 / 9;
+        }
+
+        short temperatureToHex(double temperature)
+        {
+            return (short)(temperature * Math.Pow(2, 8));
+        }
+
+        public double HexToTemperature(int hex, bool dataFormat)
+        {
+            return hexToTemperature(new byte[] { (byte)(hex >> 8), (byte)(hex & 0xFF) }, dataFormat);
+        }
+
+        double hexToTemperature(byte[] hex, bool dataFormat)
+        {
+            int rawCode;
+            int normalCode;
+
+            if (hex.Length != 2)
+                return 0;
+
+            rawCode = (hex[0] << 8) + hex[1];
+
+            if (rawCode > 0x7fff)
+                normalCode = rawCode - 0x10000;
+            else
+                normalCode = rawCode;
+
+            if (dataFormat == false)
+                return normalCode / Math.Pow(2, 8);
+            else
+                return normalCode / Math.Pow(2, 8) + 64;
+
+        }
+
+        #endregion
+
+
+        #region Temperature Tab Events
+        private void tglCelsiusFahrenheit_CheckedChanged(object sender, EventArgs e)
+        {
+            MaximStyle.MaximToggleButton tgl = (MaximStyle.MaximToggleButton)sender;
+
+            if (internalUpdate == true)
+                return;
+
+            unitsCelsius = !tgl.Checked;
+
+            convertUnits(unitsCelsius);
+
+            if (lblTemperature1.Text != blankTemperature)
+            {
+                if (unitsCelsius)
+                {
+                    lblTemperature1.Text = temperature1C.ToString("F3");
+                    lblTemperature2.Text = temperature2C.ToString("F3");
+                }
+                else
+                {
+                    lblTemperature1.Text = celsiusToFahrenheit(temperature1C).ToString("F3");
+                    lblTemperature2.Text = celsiusToFahrenheit(temperature2C).ToString("F3");
+                }
+            }
+        }
+
+        void temperatureRegisters_Leave(object sender, EventArgs e)
+        {
+            TextBox tb = (TextBox)sender;
+            byte[] tempData = new byte[2];
+            double temperature; // Temperature in C
+
+            if (Double.TryParse(tb.Text, out temperature))
+            {
+
+                //To clear just the textBox that raised this event, send SetError with empty string
+                errorProvider1.SetError(tb, "");
+
+                // Save Temperature value in C
+                if (unitsCelsius == true)
+                    temperature = Convert.ToDouble(tb.Text);
+                else
+                    temperature = fahrenheitToCelsius(Convert.ToDouble(tb.Text));
+
+                if (OverTemperatureChanged != null && HystersisChanged != null)
+                {
+                    if (ReferenceEquals(tb, txtOvertemperature1))
+                    {
+                        OverTemperatureChanged(this, new TemperatureEventArgs() { Index = 0, Temperature = temperature, Control = tb }); 
+                    }
+                    else if (ReferenceEquals(tb, txtOvertemperature2))
+                    {
+                        OverTemperatureChanged(this, new TemperatureEventArgs() { Index = 1, Temperature = temperature, Control = tb }); 
+                    }
+                    else if (ReferenceEquals(tb, txtHysteresis1))
+                    {
+                        HystersisChanged(this, new TemperatureEventArgs() { Index = 0, Temperature = temperature, Control = tb }); 
+                    }
+                    else if (ReferenceEquals(tb, txtHysteresis2))
+                    {
+                        HystersisChanged(this, new TemperatureEventArgs() { Index = 1, Temperature = temperature, Control = tb }); 
+                    }
+                }
+            }
+            else
+            {
+                errorProvider1.SetError(tb, "Invalid Temperature Format");
+            }
+        }
+
+        private void configurationRegister_CheckedChanged(object sender, EventArgs e)
+        {
+            try
+            {
+                configurationRegisterToByte();
+            }
+            catch (Exception)
+            {
+                ShowI2CErrorMessage();
+            }
+        }
+
+
+        #endregion
+
+        private void maximButton1_Click(object sender, EventArgs e)
+        {
+            if (ReadAll != null)
+            {
+                try
+                {
+                    ReadAll(this, e);
+                }
+                catch (Exception)
+                {
+                    ShowI2CErrorMessage();
+                }
+            }
+        }
+
+        private void timer1_Tick(object sender, EventArgs e)
+        {
+            if (RequestReadTemperature != null)
+            {
+                try
+                {
+                    RequestReadTemperature(this, e);
+                }
+                catch (Exception)
+                {
+                    ShowI2CErrorMessage();
+                }
+            }
+        }
+
+        private static void ShowI2CErrorMessage()
+        {
+            string message = "MAX30205 was not found. Please reconnect and try again or choose 'Cancel' to exit.";
+            string caption = "I2C Error";
+            MessageBoxButtons buttons = MessageBoxButtons.RetryCancel;
+            MessageBoxIcon icon = MessageBoxIcon.Warning;
+            DialogResult result;
+
+            // Displays the MessageBox if there isn't one displayed already.
+
+            if (!I2CErrorShown)
+            {
+                I2CErrorShown = true;
+                result = MessageBox.Show(message, caption, buttons, icon);
+
+                if (result == System.Windows.Forms.DialogResult.Cancel)
+                {
+                    Application.Exit();
+                }
+                else
+                {
+                    //Application.Restart();// Don't do this. Rerun address scan
+                    //InitBoard();
+                }
+
+                I2CErrorShown = false;
+
+            }
+        }
+
+        private void cboRefreshRate_SelectedIndexChanged(object sender, EventArgs e)
+        {
+            RefreshRate = Convert.ToInt32(cboRefreshRate.SelectedItem);
+        }
+
+        private void tglCelsiusFahrenheit_CheckedChanged_1(object sender, EventArgs e)
+        {
+
+        }
+
+        private void lblTemperature1_Click(object sender, EventArgs e)
+        {
+
+        }
+
+        private void chkDataFormat1_Click(object sender, EventArgs e)
+        {
+            MaximCheckBox chk = (MaximCheckBox)sender;
+
+            if (DataFormatChanged != null)
+            {
+                if (chk == chkDataFormat1)
+                    DataFormatChanged(this, new DataFormatEventArgs() { Index = 0, DataFormat = chkDataFormat1.Checked });
+                else if (chk == chkDataFormat2)
+                    DataFormatChanged(this, new DataFormatEventArgs() { Index = 1, DataFormat = chkDataFormat2.Checked });
+                else
+                    throw new NotImplementedException();
+            }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HspGuiSourceV301/HSPGui/CustomControls/TemperatureView.resx	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,129 @@
+<?xml version="1.0" encoding="utf-8"?>
+<root>
+  <!-- 
+    Microsoft ResX Schema 
+    
+    Version 2.0
+    
+    The primary goals of this format is to allow a simple XML format 
+    that is mostly human readable. The generation and parsing of the 
+    various data types are done through the TypeConverter classes 
+    associated with the data types.
+    
+    Example:
+    
+    ... ado.net/XML headers & schema ...
+    <resheader name="resmimetype">text/microsoft-resx</resheader>
+    <resheader name="version">2.0</resheader>
+    <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+    <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+    <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
+    <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+    <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+        <value>[base64 mime encoded serialized .NET Framework object]</value>
+    </data>
+    <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+        <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
+        <comment>This is a comment</comment>
+    </data>
+                
+    There are any number of "resheader" rows that contain simple 
+    name/value pairs.
+    
+    Each data row contains a name, and value. The row also contains a 
+    type or mimetype. Type corresponds to a .NET class that support 
+    text/value conversion through the TypeConverter architecture. 
+    Classes that don't support this are serialized and stored with the 
+    mimetype set.
+    
+    The mimetype is used for serialized objects, and tells the 
+    ResXResourceReader how to depersist the object. This is currently not 
+    extensible. For a given mimetype the value must be set accordingly:
+    
+    Note - application/x-microsoft.net.object.binary.base64 is the format 
+    that the ResXResourceWriter will generate, however the reader can 
+    read any of the formats listed below.
+    
+    mimetype: application/x-microsoft.net.object.binary.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
+            : and then encoded with base64 encoding.
+    
+    mimetype: application/x-microsoft.net.object.soap.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+            : and then encoded with base64 encoding.
+
+    mimetype: application/x-microsoft.net.object.bytearray.base64
+    value   : The object must be serialized into a byte array 
+            : using a System.ComponentModel.TypeConverter
+            : and then encoded with base64 encoding.
+    -->
+  <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+    <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
+    <xsd:element name="root" msdata:IsDataSet="true">
+      <xsd:complexType>
+        <xsd:choice maxOccurs="unbounded">
+          <xsd:element name="metadata">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" />
+              </xsd:sequence>
+              <xsd:attribute name="name" use="required" type="xsd:string" />
+              <xsd:attribute name="type" type="xsd:string" />
+              <xsd:attribute name="mimetype" type="xsd:string" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="assembly">
+            <xsd:complexType>
+              <xsd:attribute name="alias" type="xsd:string" />
+              <xsd:attribute name="name" type="xsd:string" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="data">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+                <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
+              <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+              <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="resheader">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" />
+            </xsd:complexType>
+          </xsd:element>
+        </xsd:choice>
+      </xsd:complexType>
+    </xsd:element>
+  </xsd:schema>
+  <resheader name="resmimetype">
+    <value>text/microsoft-resx</value>
+  </resheader>
+  <resheader name="version">
+    <value>2.0</value>
+  </resheader>
+  <resheader name="reader">
+    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <resheader name="writer">
+    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <metadata name="errorProvider1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
+    <value>17, 17</value>
+  </metadata>
+  <metadata name="$this.TrayHeight" type="System.Int32, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
+    <value>46</value>
+  </metadata>
+  <metadata name="timer1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
+    <value>135, 18</value>
+  </metadata>
+</root>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HspGuiSourceV301/HSPGui/DeviceDescriptions/AccelDevice.cs	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,587 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace Maxim.MAX30101GUI.DeviceDescriptions
+{
+    /// <summary>
+    /// This class holds the properties of the ADC selected
+    /// </summary>
+    public class AccelDevice
+    {
+        string name = "MAX11270";
+        //public string[] parts = {"MAX11270"};//, "MAX11271", "MAX11280"};
+        int resolution = 24;
+        bool bipolar = true;
+        bool twosComp = true;
+        double VREFExternal = 2.5;
+
+        public double gain; //calculated
+        public int offset;  //calculated
+        //public double CNVSTime = 1000;//us
+
+        //public double[] cont_SINC;// = { 1.9, 3.9, 7.8, 15.6, 31.2, 62.5, 125, 250, 500, 1000, 2000, 4000, 8000, 16000, 32000, 64000 };
+        //public double[] single_cont = { 50, 62.5, 100, 125, 200, 250, 400, 500, 800, 1000, 1600, 2000, 3200, 4000, 6400, 12800 };
+        //public double[] cont_FIR = { 125, 250, 500, 1000, 2000, 4000, 8000, 16000 };
+        public List<double> cont_SINC = new List<double>();
+        public List<double> single_cont = new List<double>();
+        public List<double> cont_FIR = new List<double>();
+
+        public bool FIRon = false;
+
+        //public string DeviceName;
+        public List<RegisterDescription> Registers;
+        public int RegisterCount;
+
+        //Registers
+        public RegisterDescription STAT;
+        public RegisterDescription CTRL1;
+        public RegisterDescription CTRL2;
+        public RegisterDescription CTRL3;
+        public RegisterDescription CTRL4;
+        public RegisterDescription CTRL5;
+        public RegisterDescription DATA;
+        public RegisterDescription SOC_SPI;
+        public RegisterDescription SGC_SPI;
+        public RegisterDescription SCOC_SPI;
+        public RegisterDescription SCGC_SPI;
+        public RegisterDescription HPF;
+        public RegisterDescription SOC_ADC;
+        public RegisterDescription SGC_ADC;
+        public RegisterDescription SCOC_ADC;
+        public RegisterDescription SCGC_ADC;
+
+        public List<BitInfo> CommandMODE0Bits = new List<BitInfo>();
+        public List<BitInfo> CommandMODE1Bits = new List<BitInfo>();
+
+        public AccelDevice()
+        {
+            GetDefault();
+        }
+
+        /// Get the default structure and values of the Register map
+        /// 
+        public void GetDefault()
+        {
+            if (name == "MAX11214")
+            {
+                cont_SINC.AddRange(new double[] { 0.95, 1.9, 3.9, 7.8, 15.6, 31.25, 62.5, 125, 250, 500, 1000, 2000, 4000, 8000, 16000, 32000 });
+                single_cont.AddRange(new double[] { 25, 31.25, 50, 62.5, 100, 125, 200, 250, 400, 500, 800, 1000, 1600, 2000, 3200, 6400 });
+                cont_FIR.AddRange(new double[] { 62.5, 125, 250, 500, 1000, 2000, 4000, 8000 });
+            }
+            else//MAX11216, MAX11270
+            {
+                cont_SINC.AddRange(new double[] { 1.9, 3.9, 7.8, 15.6, 31.2, 62.5, 125, 250, 500, 1000, 2000, 4000, 8000, 16000, 32000, 64000 });
+                single_cont.AddRange(new double[] { 50, 62.5, 100, 125, 200, 250, 400, 500, 800, 1000, 1600, 2000, 3200, 4000, 6400, 12800 });
+                cont_FIR.AddRange(new double[] { 125, 250, 500, 1000, 2000, 4000, 8000, 16000 });
+            }
+
+            //SetFullScaleAndOffset();
+
+            Registers = new List<RegisterDescription>();
+
+            List<BitInfo> R0bits = new List<BitInfo>();
+            List<BitInfo> R1bits = new List<BitInfo>();
+            List<BitInfo> R2bits = new List<BitInfo>();
+            List<BitInfo> R3bits = new List<BitInfo>();
+            List<BitInfo> R4bits = new List<BitInfo>();
+            List<BitInfo> R5bits = new List<BitInfo>();
+            List<BitInfo> R6bits = new List<BitInfo>();
+            List<BitInfo> R7bits = new List<BitInfo>();
+            List<BitInfo> R8bits = new List<BitInfo>();
+            List<BitInfo> R9bits = new List<BitInfo>();
+            List<BitInfo> R10bits = new List<BitInfo>();
+            List<BitInfo> R11bits = new List<BitInfo>();
+
+            //bit description for STAT
+            R0bits.Add(new BitInfo() { bitIndex = "B[0]", name = "RDY", Description = "Ready: 1 = new conversion result is ready" });
+            R0bits.Add(new BitInfo() { bitIndex = "B[1]", name = "MSTAT", Description = "Measurement Status: 1 = modulator is busy measuring" });
+            R0bits.Add(new BitInfo() { bitIndex = "B[2]", name = "DOR", Description = "Data Overrange: 1 = data out of range" });
+            R0bits.Add(new BitInfo() { bitIndex = "B[3]", name = "SYSGOR", Description = "System Gain Overrange: 1 = system gain out of range" });
+            R0bits.Add(new BitInfo() { bitIndex = "B[7:4]", name = "RATE[3:0]", Description = "Data Rate: Data rate of previous conversion" });
+            R0bits.Add(new BitInfo() { bitIndex = "B[8]", name = "AOR", Description = "Analog Overrange: input voltage > 1.3 x full scale" });
+            R0bits.Add(new BitInfo() { bitIndex = "B[9]", name = "RDERR", Description = "Data Read Error: 1 = data read while data written" });
+            R0bits.Add(new BitInfo() { bitIndex = "B[11:10]", name = "PSTAT[1:0]", Description = "Power Status\r\n00 = ADC is converting\r\n01 = powered down\r\n10 = standby" });
+            R0bits.Add(new BitInfo() { bitIndex = "B[13:12]", name = "Reserved", Description = "-" });
+            R0bits.Add(new BitInfo() { bitIndex = "B[14]", name = "ERROR", Description = "Error: 1 = CAL[1:0] set to invalid setting of 11" });
+            R0bits.Add(new BitInfo() { bitIndex = "B[15]", name = "INRESET", Description = "In Reset: 1 = part is in reset mode" });
+
+            //bit description for CTRL1
+            R1bits.Add(new BitInfo() { bitIndex = "B[0]", name = "CONTSC", Description = "Continuous Single Cycle: 1 = continuous conversion" });
+            R1bits.Add(new BitInfo() { bitIndex = "B[1]", name = "SCYCLE", Description = "Single Cycle: 1 = single cycle mode" });
+            R1bits.Add(new BitInfo() { bitIndex = "B[2]", name = "FORMAT", Description = "Format: 1 = offset binary, 0 = two's complement" });
+            R1bits.Add(new BitInfo() { bitIndex = "B[3]", name = "U/B", Description = "Input Range: 1 = unipolar, 0 = bipolar" });
+            R1bits.Add(new BitInfo() { bitIndex = "B[5:4]", name = "PD[1:0]", Description = "Power State\r\n00 = normal\r\n01 = power down\r\n10 = standby\r\n11 = reset registers" });
+            R1bits.Add(new BitInfo() { bitIndex = "B[6]", name = "SYNC", Description = "SYNC: 1 = continuous mode, 0 = pulse mode" });
+            R1bits.Add(new BitInfo() { bitIndex = "B[7]", name = "EXTCK", Description = "Clock: 1 = external, 0 = internal" });
+
+            //bit description for CTRL2
+            R2bits.Add(new BitInfo() { bitIndex = "B[2:0]", name = "PGA[2:0]", Description = "PGA Gain\r\n000 = x1    100 = x16\r\n001 = x2    101 = x32\r\n010 = x4    110 = x64\r\n011 = x8    111 = x128" });
+            R2bits.Add(new BitInfo() { bitIndex = "B[3]", name = "PGAEN", Description = "PGA Enable: 1 = enable" });
+            R2bits.Add(new BitInfo() { bitIndex = "B[4]", name = "LPMODE", Description = "PGA Low Power: 1 = low power" });
+            R2bits.Add(new BitInfo() { bitIndex = "B[5]", name = "BUFEN", Description = "Input Buffer Enable: 1 = enable" });
+            R2bits.Add(new BitInfo() { bitIndex = "B[7:6]", name = "DGAIN[1:0]", Description = "Modulator Digital Gain\r\n00 = x1\r\n01 = x2\r\n10 = x4\r\n11 = x8" });
+
+            //bit description for CTRL3
+            if (name == "MAX11270")
+            {
+                R3bits.Add(new BitInfo() { bitIndex = "B[1:0]", name = "Reserved", Description = "-" });
+                R3bits.Add(new BitInfo() { bitIndex = "B[2]", name = "Reserved", Description = "-" });
+            }
+            else
+            {
+                R3bits.Add(new BitInfo() { bitIndex = "B[1:0]", name = "FILT[1:0]", Description = "Filter Control\r\n0x = SINC\r\n10 = FIR\r\n11 = IIR" });
+                R3bits.Add(new BitInfo() { bitIndex = "B[2]", name = "PHASE", Description = "FIR Phase: 1 = minimum, 0 = linear" });
+            }
+
+            R3bits.Add(new BitInfo() { bitIndex = "B[3]", name = "DATA32", Description = "32-bit Data: 1 = 32-bit data, 0 = 24-bit data" });
+            R3bits.Add(new BitInfo() { bitIndex = "B[4]", name = "MODBITS", Description = "Modulator Output Mode Enable: 1 = enable" });
+            R3bits.Add(new BitInfo() { bitIndex = "B[5]", name = "ENMSYNC", Description = "Modulator SYNC Pulse Enable: 1 = enable" });
+            R3bits.Add(new BitInfo() { bitIndex = "B[7:6]", name = "Reserved", Description = "-" });
+
+
+            //bit description for CTRL4
+            R4bits.Add(new BitInfo() { bitIndex = "B[0]", name = "DIO1", Description = "GPIO1 Bit Value" });
+            R4bits.Add(new BitInfo() { bitIndex = "B[1]", name = "DIO2", Description = "GPIO2 Bit Value" });
+            R4bits.Add(new BitInfo() { bitIndex = "B[2]", name = "DIO3", Description = "GPIO3 Bit Value" });
+            R4bits.Add(new BitInfo() { bitIndex = "B[3]", name = "Reserved", Description = "-" });
+            R4bits.Add(new BitInfo() { bitIndex = "B[4]", name = "DIR1", Description = "GPIO1 Direction: 1 = output, 0 = input" });
+            R4bits.Add(new BitInfo() { bitIndex = "B[5]", name = "DIR2", Description = "GPIO2 Direction: 1 = output, 0 = input" });
+            R4bits.Add(new BitInfo() { bitIndex = "B[6]", name = "DIR3", Description = "GPIO3 Direction: 1 = output, 0 = input" });
+            R4bits.Add(new BitInfo() { bitIndex = "B[7]", name = "Reserved", Description = "-" });
+
+            //bit description for CTRL5
+            R5bits.Add(new BitInfo() { bitIndex = "B[0]", name = "NOSCO", Description = "Disable Self Calibration Offset" });
+            R5bits.Add(new BitInfo() { bitIndex = "B[1]", name = "NOSCG", Description = "Disable Self Calibration Gain" });
+            R5bits.Add(new BitInfo() { bitIndex = "B[2]", name = "NOSYSO", Description = "Disable System Calibration Offset" });
+            R5bits.Add(new BitInfo() { bitIndex = "B[3]", name = "NOSYSG", Description = "Disable System Calibration Gain" });
+            R5bits.Add(new BitInfo() { bitIndex = "B[5:4]", name = "Reserved", Description = "-" });
+            R5bits.Add(new BitInfo() { bitIndex = "B[7:6]", name = "CAL[1:0]", Description = "Calibration\r\n00 = Perform Self Calibration\r\n01 = Perform System Offset Calibration\r\n10 = Perform System Gain Calibration" });
+
+            //bit description for Data
+            R6bits.Add(new BitInfo() { bitIndex = "B[31:0]", name = "DATA", Description = "32-Bit Mode: MSB = bit31, LSB = bit0" });
+            R6bits.Add(new BitInfo() { bitIndex = "B[31:8]", name = "DATA", Description = "24-Bit Mode: MSB = bit31, LSB = bit8" });
+
+            //bit description for SOC
+            R7bits.Add(new BitInfo() { bitIndex = "B[23:0]", name = "SOC[23:0]", Description = "System Offset Calibration: two's complement format" });
+
+            //bit description for SGC
+            R8bits.Add(new BitInfo() { bitIndex = "B[23:0]", name = "SGC[23:0]", Description = "System Gain Calibration: two's complement format" });
+
+            //bit description for SCOC
+            R9bits.Add(new BitInfo() { bitIndex = "B[23:0]", name = "SCOC[23:0]", Description = "Self Offset Calibration: two's complement format" });
+
+            //bit description for SCGC
+            R10bits.Add(new BitInfo() { bitIndex = "B[23:0]", name = "SCGC[23:0]", Description = "Self Gain Calibration: two's complement format" });
+
+            //bit description for HPF
+            R11bits.Add(new BitInfo() { bitIndex = "B[16:0]", name = "HPF[16:0]", Description = "High Pass Filter: corner frequency" });
+
+            //add information to registers
+            STAT = new RegisterDescription() { Address = 0x00, Name = "STAT", Description = "Status", ReadOnly = true, numBytes = 2, Value = 0x0000, BitInfo = R0bits };
+            CTRL1 = new RegisterDescription() { Address = 0x01, Name = "CTRL1", Description = "Control 1", ReadOnly = false, numBytes = 1, Value = 0x02, BitInfo = R1bits };
+            CTRL2 = new RegisterDescription() { Address = 0x02, Name = "CTRL2", Description = "Control 2", ReadOnly = false, numBytes = 1, Value = 0x00, BitInfo = R2bits };
+            CTRL3 = new RegisterDescription() { Address = 0x03, Name = "CTRL3", Description = "Control 3", ReadOnly = false, numBytes = 1, Value = 0x61, BitInfo = R3bits };
+            CTRL4 = new RegisterDescription() { Address = 0x04, Name = "CTRL4", Description = "Control 4", ReadOnly = false, numBytes = 1, Value = 0x08, BitInfo = R4bits };
+            CTRL5 = new RegisterDescription() { Address = 0x05, Name = "CTRL5", Description = "Control 5", ReadOnly = false, numBytes = 1, Value = 0x0C, BitInfo = R5bits };
+            DATA = new RegisterDescription() { Address = 0x06, Name = "DATA", Description = "Data", ReadOnly = true, numBytes = 4, Value = 0x00000000, BitInfo = R6bits };
+            SOC_SPI = new RegisterDescription() { Address = 0x07, Name = "SOC_SPI", Description = "SPI System Offset Calibration", ReadOnly = false, numBytes = 3, Value = 0x000000, BitInfo = R7bits };
+            SGC_SPI = new RegisterDescription() { Address = 0x08, Name = "SGC_SPI", Description = "SPI System Gain Calibration", ReadOnly = false, numBytes = 3, Value = 0x7FFFFF, BitInfo = R8bits };
+            SCOC_SPI = new RegisterDescription() { Address = 0x09, Name = "SCOC_SPI", Description = "SPI Self Offset Calibration", ReadOnly = false, numBytes = 3, Value = 0x000000, BitInfo = R9bits };
+            SCGC_SPI = new RegisterDescription() { Address = 0x0A, Name = "SCGC_SPI", Description = "SPI Self Gain Calibration", ReadOnly = false, numBytes = 3, Value = 0xBF851B, BitInfo = R10bits };
+            HPF = new RegisterDescription() { Address = 0x0B, Name = "HPF", Description = "High Pass Filter", ReadOnly = false, numBytes = 2, Value = 0x0000, BitInfo = R11bits };
+            SOC_ADC = new RegisterDescription() { Address = 0x15, Name = "SOC_ADC", Description = "ADC System Offset Calibration", ReadOnly = true, numBytes = 3, Value = 0x000000, BitInfo = R7bits };
+            SGC_ADC = new RegisterDescription() { Address = 0x16, Name = "SGC_ADC", Description = "ADC System Gain Calibration", ReadOnly = true, numBytes = 3, Value = 0x000000, BitInfo = R8bits };
+            SCOC_ADC = new RegisterDescription() { Address = 0x17, Name = "SCOC_ADC", Description = "ADC Self Offset Calibration", ReadOnly = true, numBytes = 3, Value = 0x000000, BitInfo = R9bits };
+            SCGC_ADC = new RegisterDescription() { Address = 0x18, Name = "SCGC_ADC", Description = "ADC Self Gain Calibration", ReadOnly = true, numBytes = 3, Value = 0x000000, BitInfo = R10bits };
+
+            //add registers to map
+            /*
+            Registers.Add(STAT);
+            Registers.Add(CTRL1);
+            Registers.Add(CTRL2);
+            Registers.Add(CTRL3);
+            Registers.Add(CTRL4);
+            Registers.Add(CTRL5);
+            Registers.Add(DATA);
+            Registers.Add(SOC_SPI);
+            Registers.Add(SGC_SPI);
+            Registers.Add(SCOC_SPI);
+            Registers.Add(SCGC_SPI);
+
+            if (name != "MAX11270")
+                Registers.Add(HPF);
+
+            Registers.Add(SOC_ADC);
+            Registers.Add(SGC_ADC);
+            Registers.Add(SCOC_ADC);
+            Registers.Add(SCGC_ADC);
+            */
+            //STATUS_REG_AUX
+            for (int reg = 0; reg <= 0x3F; reg++)
+            {
+                Registers.Add(new RegisterDescription() { Address = (byte)reg, Name = RegisterNames[reg], Description = "ADC Self Gain Calibration", ReadOnly = true, numBytes = 1, Value = 0x000000, BitInfo = R10bits });
+            }
+            RegisterCount = Registers.Count;
+
+
+            //bit description for command MODE 0 bits
+            CommandMODE0Bits.Add(new BitInfo() { bitIndex = "B[3:0]", name = "RATE[3:0]", Description = "Data Rate for conversion" });
+            CommandMODE0Bits.Add(new BitInfo() { bitIndex = "B[4]", name = "IMPD", Description = "1 = sleep mode\r\n0 = normal" });
+            CommandMODE0Bits.Add(new BitInfo() { bitIndex = "B[5]", name = "CAL", Description = "1 = perform calibration\r\n0 = no calibration" });
+            CommandMODE0Bits.Add(new BitInfo() { bitIndex = "B[6]", name = "MODE", Description = "MODE = 0 to start conversion, power down or calibrate" });
+            CommandMODE0Bits.Add(new BitInfo() { bitIndex = "B[7]", name = "START", Description = "START = 1" });
+
+            //bit description for command MODE 1 bits
+            CommandMODE1Bits.Add(new BitInfo() { bitIndex = "B[0]", name = "R/W", Description = "Read/Write bit:\r\n1 = read, 0 = write" });
+            CommandMODE1Bits.Add(new BitInfo() { bitIndex = "B[5:1]", name = "RS[4:0]", Description = "Register address" });
+            CommandMODE1Bits.Add(new BitInfo() { bitIndex = "B[6]", name = "MODE", Description = "MODE = 1 for register access mode" });
+            CommandMODE1Bits.Add(new BitInfo() { bitIndex = "B[7]", name = "START", Description = "START = 1" });
+        }
+
+        public void ResetReigsters()
+        {
+            CTRL1.Value = 0x02;
+            CTRL2.Value = 0x00;
+            CTRL3.Value = 0x61;
+            CTRL4.Value = 0x08;
+            CTRL5.Value = 0x0C;
+
+            HPF.Value = 0;
+
+            SOC_SPI.Value = 0;
+            SGC_SPI.Value = 0x7FFFFF;
+            SCOC_SPI.Value = 0;
+            SCGC_SPI.Value = 0xBF851B;
+
+        }
+
+        String[] RegisterNames = {
+        "Reserved",
+"Reserved",
+"Reserved",
+"Reserved",
+"Reserved",
+"Reserved",
+"Reserved",
+"STATUS_REG_AUX",
+"Reserved",
+"Reserved",
+"Reserved",
+"Reserved",
+"OUT_TEMP_L",
+"OUT_TEMP_H",
+"INT_COUNTER_REG",
+"WHO_AM_I",
+"Reserved",
+"Reserved",
+"Reserved",
+"Reserved",
+"Reserved",
+"Reserved",
+"Reserved",
+"Reserved",
+"Reserved",
+"Reserved",
+"Reserved",
+"Reserved",
+"Reserved",
+"Reserved",
+"Reserved",
+"TEMP_CFG_REG",
+"CTRL_REG1",
+"CTRL_REG2",
+"CTRL_REG3",
+"CTRL_REG4",
+"CTRL_REG5",
+"CTRL_REG6",
+"REFERENCE",
+"STATUS_REG2",
+"OUT_X_L",
+"OUT_X_H",
+"OUT_Y_L",
+"OUT_Y_H",
+"OUT_Z_L",
+"OUT_Z_H",
+"FIFO_CTRL_REG",
+"FIFO_SRC_REG",
+"INT1_CFG",
+"INT1_SOURCE",
+"INT1_THS",
+"INT1_DURATION",
+"INT2_CFG",
+"INT2_SOURCE",
+"INT2_THS",
+"INT2_DURATION",
+"CLICK_CFG",
+"CLICK_SRC",
+"CLICK_THS",
+"TIME_LIMIT",
+"TIME_LATENCY",
+"TIME_WINDOW",
+"Act_THS",
+"Act_DUR"
+    };
+
+
+        /// When the name property changes the other properties will change based on the name
+        public string Name
+        {
+            get
+            {
+                return name;
+            }
+            set
+            {
+                if (value != name)
+                {
+                    name = value;
+
+                    //change register map and sampling rates for other devices
+                    ChangeADCSetting();
+                }
+
+            }
+        }
+
+        public void ChangeADCSetting()
+        {
+            switch (name)
+            {
+                case "MAX11214":
+
+                    if (cont_SINC[0] != 0.95)
+                    {
+                        cont_SINC.Clear();
+                        single_cont.Clear();
+                        cont_FIR.Clear();
+                        cont_SINC.AddRange(new double[] { 0.95, 1.9, 3.9, 7.8, 15.6, 31.25, 62.5, 125, 250, 500, 1000, 2000, 4000, 8000, 16000, 32000 });
+                        single_cont.AddRange(new double[] { 25, 31.25, 50, 62.5, 100, 125, 200, 250, 400, 500, 800, 1000, 1600, 2000, 3200, 6400 });
+                        cont_FIR.AddRange(new double[] { 62.5, 125, 250, 500, 1000, 2000, 4000, 8000 });
+                    }
+
+                    if (!Registers.Contains(HPF))
+                    {
+                        Registers.Insert(11, HPF);
+                        RegisterCount = Registers.Count;
+
+
+                        CTRL3.BitInfo[0].name = "FILT[1:0]";
+                        CTRL3.BitInfo[0].Description = "Filter Control\r\n0x = SINC\r\n10 = FIR\r\n11 = IIR";
+                        CTRL3.BitInfo[1].name = "PHASE";
+                        CTRL3.BitInfo[1].Description = "FIR Phase: 1 = minimum, 0 = linear";
+                    }
+
+                    break;
+                case "MAX11216":
+
+                    if (cont_SINC[0] != 1.9)
+                    {
+                        cont_SINC.Clear();
+                        single_cont.Clear();
+                        cont_FIR.Clear();
+
+                        cont_SINC.AddRange(new double[] { 1.9, 3.9, 7.8, 15.6, 31.2, 62.5, 125, 250, 500, 1000, 2000, 4000, 8000, 16000, 32000, 64000 });
+                        single_cont.AddRange(new double[] { 50, 62.5, 100, 125, 200, 250, 400, 500, 800, 1000, 1600, 2000, 3200, 4000, 6400, 12800 });
+                        cont_FIR.AddRange(new double[] { 125, 250, 500, 1000, 2000, 4000, 8000, 16000 });
+                    }
+
+                    if (!Registers.Contains(HPF))
+                    {
+                        Registers.Insert(11, HPF);
+                        RegisterCount = Registers.Count;
+
+
+                        CTRL3.BitInfo[0].name = "FILT[1:0]";
+                        CTRL3.BitInfo[0].Description = "Filter Control\r\n0x = SINC\r\n10 = FIR\r\n11 = IIR";
+                        CTRL3.BitInfo[1].name = "PHASE";
+                        CTRL3.BitInfo[1].Description = "FIR Phase: 1 = minimum, 0 = linear";
+                    }
+
+                    break;
+                case "MAX11270":
+
+                    if (cont_SINC[0] != 1.9)
+                    {
+                        cont_SINC.Clear();
+                        single_cont.Clear();
+                        cont_FIR.Clear();
+
+                        cont_SINC.AddRange(new double[] { 1.9, 3.9, 7.8, 15.6, 31.2, 62.5, 125, 250, 500, 1000, 2000, 4000, 8000, 16000, 32000, 64000 });
+                        single_cont.AddRange(new double[] { 50, 62.5, 100, 125, 200, 250, 400, 500, 800, 1000, 1600, 2000, 3200, 4000, 6400, 12800 });
+                        cont_FIR.AddRange(new double[] { 125, 250, 500, 1000, 2000, 4000, 8000, 16000 });
+                    }
+
+                    if (Registers.Contains(HPF))
+                    {
+                        Registers.Remove(HPF);
+                        RegisterCount = Registers.Count;
+
+
+                        CTRL3.BitInfo[0].name = "Reserved";
+                        CTRL3.BitInfo[0].Description = "-";
+                        CTRL3.BitInfo[1].name = "Reserved";
+                        CTRL3.BitInfo[1].Description = "-";
+                    }
+
+                    break;
+                case "MAX11271":
+
+                    if (cont_SINC[0] != 1.9)
+                    {
+                        cont_SINC.Clear();
+                        single_cont.Clear();
+                        cont_FIR.Clear();
+
+                        cont_SINC.AddRange(new double[] { 1.9, 3.9, 7.8, 15.6, 31.2, 62.5, 125, 250, 500, 1000, 2000, 4000, 8000, 16000, 32000, 64000 });
+                        single_cont.AddRange(new double[] { 50, 62.5, 100, 125, 200, 250, 400, 500, 800, 1000, 1600, 2000, 3200, 4000, 6400, 12800 });
+                        cont_FIR.AddRange(new double[] { 125, 250, 500, 1000, 2000, 4000, 8000, 16000 });
+                    }
+
+                    if (Registers.Contains(HPF))
+                    {
+                        Registers.Remove(HPF);
+                        RegisterCount = Registers.Count;
+
+
+                        CTRL3.BitInfo[0].name = "Reserved";
+                        CTRL3.BitInfo[0].Description = "-";
+                        CTRL3.BitInfo[1].name = "Reserved";
+                        CTRL3.BitInfo[1].Description = "-";
+                    }
+                    break;
+                case "MAX11280":
+                    break;
+                case "MAX11281":
+                    break;
+                case "MAX11282":
+                    break;
+            }
+
+        }
+
+        public int Resolution
+        {
+            get
+            {
+                return resolution;
+
+            }
+            set
+            {
+                if (value != resolution)
+                {
+                    resolution = value;
+
+                    //SetFullScaleAndOffset();
+                }
+            }
+        }
+
+        public double VREF
+        {
+            get
+            {
+                return VREFExternal;
+
+            }
+            set
+            {
+                if (value != VREFExternal)
+                {
+                    VREFExternal = value;
+
+                    //SetFullScaleAndOffset();
+                }
+            }
+        }
+
+        public bool IsBipolar
+        {
+            get
+            {
+                return bipolar;
+
+            }
+            set
+            {
+                if (value != bipolar)
+                {
+                    bipolar = value;
+
+                    //SetFullScaleAndOffset();
+                }
+            }
+        }
+
+        public bool IsTwosComp
+        {
+            get
+            {
+                return twosComp;
+
+            }
+            set
+            {
+                if (value != twosComp)
+                {
+                    twosComp = value;
+
+                    //SetFullScaleAndOffset();
+                }
+            }
+        }
+
+        /// Calculates the Full scale value and offset of the ADC
+        public void SetGainAndOffset(int res)
+        {
+            double FullScale;
+
+            if (bipolar)
+            {
+                FullScale = 2 * VREFExternal;
+
+                if (twosComp) //2's compliment
+                    offset = 0;
+                else          //offset binary
+                    offset = 1 << (res - 1); //2^(resolution-1)
+            }
+            else //unipolar
+            {
+                FullScale = VREFExternal;
+                offset = 0;
+            }
+
+            long digitalFullscale = ((long)1 << res) - 1;
+
+            gain = FullScale / digitalFullscale;
+        }
+    }
+
+    /// <summary>
+    /// This class sets up a structure to hold register information
+    /// </summary>
+    /// @see RegisterMap
+    public class RegisterDescription
+    {
+        public byte Address;
+        public string Name;
+        public bool ReadOnly;
+        public int numBytes;
+        public string Description;
+        public int Value;
+        public List<BitInfo> BitInfo;
+    }
+
+    ///<summary>
+    /// This class sets up the structure to hold bit information of registers
+    /// </summary>
+    ///@see RegisterDescription
+    public class BitInfo
+    {
+        public string name;
+        public string bitIndex;
+        public string Description;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HspGuiSourceV301/HSPGui/DeviceDescriptions/Device.cs	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,64 @@
+/*******************************************************************************
+* Copyright (C) 2016 Maxim Integrated Products, Inc., All rights Reserved.
+* 
+* This software is protected by copyright laws of the United States and
+* of foreign countries. This material may also be protected by patent laws
+* and technology transfer regulations of the United States and of foreign
+* countries. This software is furnished under a license agreement and/or a
+* nondisclosure agreement and may only be used or reproduced in accordance
+* with the terms of those agreements. Dissemination of this information to
+* any party or parties not specified in the license agreement and/or
+* nondisclosure agreement is expressly prohibited.
+*
+* The above copyright notice and this permission notice shall be included
+* in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+* OTHER DEALINGS IN THE SOFTWARE.
+*
+* Except as contained in this notice, the name of Maxim Integrated
+* Products, Inc. shall not be used except as stated in the Maxim Integrated
+* Products, Inc. Branding Policy.
+*
+* The mere transfer of this software does not imply any licenses
+* of trade secrets, proprietary technology, copyrights, patents,
+* trademarks, maskwork rights, or any other form of intellectual
+* property whatsoever. Maxim Integrated Products, Inc. retains all
+* ownership rights.
+*******************************************************************************
+*/
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using Maxim.CustomControls;
+using RPCSupport.DeviceSupport;
+
+namespace HealthSensorPlatform.DeviceDescriptions
+{
+    public class Device
+    {
+        public Device()
+        {
+        }
+        public RegisterInfo[] Info;
+        public DeviceDetails deviceDetails;
+
+        public RegisterBitDescriptions Descriptions(int address)
+        {
+            RegisterBitDescriptions descriptions = null;
+            foreach (RegisterInfo info in Info)
+            {
+                if (info.address == address) return info.description;
+            }
+            return descriptions;
+        }
+
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HspGuiSourceV301/HSPGui/DeviceDescriptions/DeviceController.cs	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,141 @@
+/*******************************************************************************
+* Copyright (C) 2016 Maxim Integrated Products, Inc., All rights Reserved.
+* 
+* This software is protected by copyright laws of the United States and
+* of foreign countries. This material may also be protected by patent laws
+* and technology transfer regulations of the United States and of foreign
+* countries. This software is furnished under a license agreement and/or a
+* nondisclosure agreement and may only be used or reproduced in accordance
+* with the terms of those agreements. Dissemination of this information to
+* any party or parties not specified in the license agreement and/or
+* nondisclosure agreement is expressly prohibited.
+*
+* The above copyright notice and this permission notice shall be included
+* in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+* OTHER DEALINGS IN THE SOFTWARE.
+*
+* Except as contained in this notice, the name of Maxim Integrated
+* Products, Inc. shall not be used except as stated in the Maxim Integrated
+* Products, Inc. Branding Policy.
+*
+* The mere transfer of this software does not imply any licenses
+* of trade secrets, proprietary technology, copyrights, patents,
+* trademarks, maskwork rights, or any other form of intellectual
+* property whatsoever. Maxim Integrated Products, Inc. retains all
+* ownership rights.
+*******************************************************************************
+*/
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using HealthSensorPlatform.DeviceDescriptions;
+using RPCSupport.DeviceSupport;
+
+namespace Maxim.CustomControls
+{
+    public class DeviceController
+    {
+        //Hid_BaseClass myHID;
+        RegisterInfo[] infoArray;
+        Byte deviceAddress;
+        Device device;
+        RPCSupport.RPCClient rpcClient;
+
+        public Device Device
+        {
+            get
+            {
+                return device;
+            }
+        }
+
+        public event EventHandler<RegisterEventArgs> RegisterRead;
+        public event EventHandler<RegisterEventArgs> RegisterWrite;
+
+        public class RegisterEventArgs : EventArgs
+        {
+            public RegisterInfo reg { get; set; }
+        }
+
+        protected virtual void OnRegisterRead(RegisterEventArgs e)
+        {
+            EventHandler<RegisterEventArgs> handler = RegisterRead;
+            if (handler != null)
+            {
+                handler(this, e);
+            }
+        }
+        protected virtual void OnRegisterWrite(RegisterEventArgs e)
+        {
+            EventHandler<RegisterEventArgs> handler = RegisterWrite;
+            if (handler != null)
+            {
+                handler(this, e);
+            }
+        }
+
+        public void SetRegisterInfo(Device device)
+        {
+            this.device = device;
+            this.infoArray = device.Info;
+        }
+        //public void SetHid(Hid_BaseClass hid) {
+        //    myHID = hid;
+        //}
+        public void SetDeviceAddress(Byte address)
+        {
+            deviceAddress = address;
+        }
+        public RegisterInfo[] InfoArray
+        {
+            get
+            {
+                return infoArray;
+            }
+        }
+
+        public void ReadAll()
+        {
+            foreach (RegisterInfo reg in infoArray)
+            {
+                ReadRegister(reg);
+            }
+        }
+
+        public void WriteAll()
+        {
+            foreach (RegisterInfo reg in infoArray)
+            {
+                WriteRegister(reg);
+            }
+        }
+
+        public void ReadRegister(RegisterInfo reg)
+        {
+            rpcClient.ReadRegister(device.deviceDetails, reg);
+            //RegisterEventArgs registerEventArgs = new RegisterEventArgs() { reg = reg };
+            //OnRegisterRead(registerEventArgs);
+        }
+
+        public void WriteRegister(RegisterInfo reg)
+        {
+            rpcClient.WriteRegister(device.deviceDetails, reg);
+            //RegisterEventArgs registerEventArgs = new RegisterEventArgs() { reg = reg };
+            //OnRegisterWrite(registerEventArgs);
+        }
+
+        internal void SetInterface(RPCSupport.RPCClient rpcClient)
+        {
+            this.rpcClient = rpcClient;
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HspGuiSourceV301/HSPGui/DeviceDescriptions/DeviceDetails.cs	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,30 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace HealthSensorPlatform.DeviceDescriptions
+{
+    public class DeviceDetails
+    {
+        public enum eType
+        {
+            eSpi,
+            eI2c
+        }
+        public eType type;
+        public int i2cInstance;
+        public int i2cSlaveAddress;
+
+        public int spiCs;
+        public void InitSpi(int spiCs) {
+            type = eType.eSpi;
+            this.spiCs = spiCs;
+        }
+        public void InitI2c(int i2cInstance, int i2cSlaveAddress) {
+            type = eType.eI2c;
+            this.i2cInstance = i2cInstance;
+            this.i2cSlaveAddress = i2cSlaveAddress;
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HspGuiSourceV301/HSPGui/DeviceDescriptions/LIS2DHInfo.cs	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,103 @@
+/*******************************************************************************
+* Copyright (C) 2016 Maxim Integrated Products, Inc., All rights Reserved.
+* 
+* This software is protected by copyright laws of the United States and
+* of foreign countries. This material may also be protected by patent laws
+* and technology transfer regulations of the United States and of foreign
+* countries. This software is furnished under a license agreement and/or a
+* nondisclosure agreement and may only be used or reproduced in accordance
+* with the terms of those agreements. Dissemination of this information to
+* any party or parties not specified in the license agreement and/or
+* nondisclosure agreement is expressly prohibited.
+*
+* The above copyright notice and this permission notice shall be included
+* in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+* OTHER DEALINGS IN THE SOFTWARE.
+*
+* Except as contained in this notice, the name of Maxim Integrated
+* Products, Inc. shall not be used except as stated in the Maxim Integrated
+* Products, Inc. Branding Policy.
+*
+* The mere transfer of this software does not imply any licenses
+* of trade secrets, proprietary technology, copyrights, patents,
+* trademarks, maskwork rights, or any other form of intellectual
+* property whatsoever. Maxim Integrated Products, Inc. retains all
+* ownership rights.
+*******************************************************************************
+*/
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using HealthSensorPlatform.DeviceDescriptions;
+using RPCSupport.DeviceSupport;
+
+namespace Maxim.CustomControls
+{
+    public class LIS2DHInfo : Device
+    {
+
+        public LIS2DHInfo()
+        {
+            deviceDetails = new DeviceDetails();
+            deviceDetails.InitI2c(2,0x32);
+
+            Info = new RegisterInfo[] {
+                new RegisterInfo("STATUS_REG_AUX",0x07),
+                new RegisterInfo("OUT_TEMP_L",0x0C),
+                new RegisterInfo("OUT_TEMP_H",0x0D),
+                new RegisterInfo("INT_COUNTER_REG",0x0E),
+                new RegisterInfo("WHO_AM_I",0x0F),
+                new RegisterInfo("TEMP_CFG_REG",0x1F),
+                new RegisterInfo("CTRL_REG1",0x20),
+                new RegisterInfo("CTRL_REG2",0x21),
+                new RegisterInfo("CTRL_REG3",0x22),
+                new RegisterInfo("CTRL_REG4",0x23),
+                new RegisterInfo("CTRL_REG5",0x24),
+                new RegisterInfo("CTRL_REG6",0x25),
+                new RegisterInfo("REFERENCE",0x26),
+                new RegisterInfo("STATUS_REG2",0x27),
+                new RegisterInfo("OUT_X_L",0x28),
+                new RegisterInfo("OUT_X_H",0x29),
+                new RegisterInfo("OUT_Y_L",0x2A),
+                new RegisterInfo("OUT_Y_H",0x2B),
+                new RegisterInfo("OUT_Z_L",0x2C),
+                new RegisterInfo("OUT_Z_H",0x2D),
+                new RegisterInfo("FIFO_CTRL_REG",0x2E),
+                new RegisterInfo("FIFO_SRC_REG",0x2F),
+                new RegisterInfo("INT1_CFG",0x30),
+                new RegisterInfo("INT1_SOURCE",0x31),
+                new RegisterInfo("INT1_THS",0x32),
+                new RegisterInfo("INT1_DURATION",0x33),
+                new RegisterInfo("INT2_CFG",0x34),
+                new RegisterInfo("INT2_SOURCE",0x35),
+                new RegisterInfo("INT2_THS",0x36),
+                new RegisterInfo("INT2_DURATION",0x37),
+                new RegisterInfo("CLICK_CFG",0x38),
+                new RegisterInfo("CLICK_SRC",0x39),
+                new RegisterInfo("CLICK_THS",0x3A),
+                new RegisterInfo("TIME_LIMIT",0x3B),
+                new RegisterInfo("TIME_LATENCY",0x3C),
+                new RegisterInfo("TIME_WINDOW",0x3D),
+                new RegisterInfo("Act_THS",0x3E),
+                new RegisterInfo("Act_DUR",0x3F)
+           };
+
+            // register 0x00
+            Descriptions(0x07).Add("Bit 0", "PWR_RDY", "Power Ready Flag");
+            Descriptions(0x07).Add("Bit 4", "PROX_INT", "Proximity Threshold Triggered");
+            // register 0x01
+            Descriptions(0x0C).Add("Bit 1", "DIE_TEMP_RDY", "Internal Temperature Ready Flag");
+            // register 0x02
+            Descriptions(0x0D).Add("Bit 4", "PROX_INT_EN", "Proximity Threshold Enable");
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HspGuiSourceV301/HSPGui/DeviceDescriptions/MAX14720Info.cs	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,396 @@
+/*******************************************************************************
+* Copyright (C) 2016 Maxim Integrated Products, Inc., All rights Reserved.
+* 
+* This software is protected by copyright laws of the United States and
+* of foreign countries. This material may also be protected by patent laws
+* and technology transfer regulations of the United States and of foreign
+* countries. This software is furnished under a license agreement and/or a
+* nondisclosure agreement and may only be used or reproduced in accordance
+* with the terms of those agreements. Dissemination of this information to
+* any party or parties not specified in the license agreement and/or
+* nondisclosure agreement is expressly prohibited.
+*
+* The above copyright notice and this permission notice shall be included
+* in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+* OTHER DEALINGS IN THE SOFTWARE.
+*
+* Except as contained in this notice, the name of Maxim Integrated
+* Products, Inc. shall not be used except as stated in the Maxim Integrated
+* Products, Inc. Branding Policy.
+*
+* The mere transfer of this software does not imply any licenses
+* of trade secrets, proprietary technology, copyrights, patents,
+* trademarks, maskwork rights, or any other form of intellectual
+* property whatsoever. Maxim Integrated Products, Inc. retains all
+* ownership rights.
+*******************************************************************************
+*/
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using HealthSensorPlatform.DeviceDescriptions;
+using RPCSupport.DeviceSupport;
+
+namespace Maxim.CustomControls
+{
+    /// <summary>
+    /// PMIC Register Information
+    /// </summary>
+    public class MAX14720Info : Device
+    {
+
+        public MAX14720Info()
+        {
+            deviceDetails = new DeviceDetails();
+            deviceDetails.InitI2c(2, 0x54);
+
+            initalizeDescription();
+
+        }
+
+        void initalizeDescription()
+        {
+            Info = new RegisterInfo[] {
+                new RegisterInfo("ChipId",0x00),
+                new RegisterInfo("ChipRev",0x01),
+                new RegisterInfo("BoostCDiv",0x03),
+                new RegisterInfo("BoostISet",0x04),
+                new RegisterInfo("BoostVSet",0x05),
+                new RegisterInfo("BoostCfg",0x06),
+                new RegisterInfo("BuckVSet",0x07),
+                new RegisterInfo("BuckCfg",0x08),
+                new RegisterInfo("BuckISet",0x09),
+                new RegisterInfo("LDOVSet",0x0A),
+                new RegisterInfo("LDOCfg",0x0B),
+                new RegisterInfo("SwitchCfg",0x0C),
+                new RegisterInfo("BatTime",0x0D),
+                new RegisterInfo("BatCfg",0x0E),
+                new RegisterInfo("BatBCV",0x0F),
+                new RegisterInfo("BatOCV",0x10),
+                new RegisterInfo("BattLCV",0x11),
+                new RegisterInfo("MONCfg",0x19),
+                new RegisterInfo("BoostCfg",0x1A),
+                new RegisterInfo("PinStat",0x1B),
+                new RegisterInfo("BBBExtra",0x1C),
+                new RegisterInfo("HandShk",0x1D),
+                new RegisterInfo("UVLOCfg",0x1E),
+                new RegisterInfo("PWROFF",0x1F)
+           };
+
+            // register 0x00
+            Descriptions(0x00).Add("Bit [7:0]", "ChipId", "Version information");
+            // register 0x01
+            Descriptions(0x01).Add("Bit [7:0]", "ChipRev", "Revison Information");
+            // register 0x03
+            Descriptions(0x03).Add("Bit 7", "ClkDivEn", @"Boost Current-Limited Output Mode Enable
+This allows the boost regulator to be operated in a current limited output mode.
+0: Normal Operation, Full Output Current Capability
+1: Divided Clock Current Limited Mode
+When the clock divider is enabled, the boost is operated with a fixed peak current limit and programmable
+frequency. The peak current is set by BoostISet[2:0] and the switching frequency is determined by
+ClkDivSet[6:0]. The regulator will stop switching when the voltage is above the set point and will only run when
+the voltage is below the output setting. This mode can only be enabled once the output voltage is set higher
+than the input voltage.");
+            // register 0x03
+            Descriptions(0x03).Add("Bit [6:0]", "ClkDivSet", @"Current-Limited Boost Clock Divider Setting
+When the current limited mode is enabled, the frequency of the boost regulator in current limited mode will be
+the frequency of the oscillator divided by the value of (10 + ClkDivSet[6:0]). The range is fOSC/10 to fOSC/137.");
+            // register 0x04
+            Descriptions(0x04).Add("Bit [2:0]", "BoostISet", @"Buck-Boost Peak Current-Limit Setting
+000: 0 (Minimum On-Time)
+001: 50mA
+010: 100mA
+011: 150mA
+100: 200mA
+101: 250mA
+110: 300mA
+111: 350mA");
+            // register 0x05
+            Descriptions(0x05).Add("Bit [4:0]", "BoostVSet[4:0]", @"Boost Output Voltage Setting. This setting is internally latched and can change only when boost is disabled.
+2.5V to 5.0V, linear scale, 100mV increments
+000000 = 2.5V
+000001 = 2.6V
+…
+011001 = 5.0V
+> 011001 = 5.0V");
+            // register 0x06
+            Descriptions(0x06).Add("Bit [7:5]", "BoostSeq[2:0]", @"Boost Enable Configuration (Read-Only)
+000 = Disabled
+001 = Reserved
+010 = Enabled at 0% of Boot/POR Process Delay Control
+011 = Enabled at 25% of Boot/POR Process Delay Control
+100 = Enabled at 50% of Boot/POR Process Delay Control
+101 = Reserved
+110 = Controlled by HVEN (MAX14750)
+111 = Controlled by BoostEn [1:0] after 100% of Boot/POR Process Delay Control (MAX14720)");
+            Descriptions(0x06).Add("Bit [4:3]", "BoostEn[1:0]", @"Boost Enable Configuration (effective only when BoostSeq[2:0] == 111)
+00 = Disabled. Active discharge behavior depends on BoostActDsc.
+01 = Enabled
+10 = Enabled when MPC is high
+11 = Reserved");
+            Descriptions(0x07).Add("Bit 1", "BoostEMI", @"Boost EMI reduction. Dampens ringing of the inductor when in discontinuous mode
+0 = EMI damping active (improve EMI)
+1 = EMI damping disabled (improve Efficiency)");
+            Descriptions(0x08).Add("Bit 0", "BoostInd", @"Boost Inductance Select
+1 = Inductance is 3.3µH
+0 = Inductance is 4.7µH");
+            // register 0x07
+            Descriptions(0x07).Add("Bit [5:0]", "BuckVSet[5:0]", @"Buck Output Voltage Setting This setting is internally latched and can change only when buck is disabled.
+1.0V to 2.0V, linear scale, 25mV increments
+000000 = 1.000V
+000001 = 1.025V
+…
+101000 = 2.0V
+> 101000 = 2.0V");
+            // register 0x08
+            Descriptions(0x08).Add("Bit [7:6]", "BuckSeq[2:0]", @"Buck Enable Configuration (Read-Only)
+000 = Disabled
+001 = Reserved
+010 = Enabled at 0% of Boot/POR Process Delay Control
+011 = Enabled at 25% of Boot/POR Process Delay Control
+100 = Enabled at 50% of Boot/POR Process Delay Control
+101 = Reserved
+110 = Controlled by BEN (MAX14750)
+111 = Controlled by BuckEn [1:0] after 100% of Boot/POR Process Delay Control");
+            Descriptions(0x08).Add("Bit [4:3]", "BuckEn[1:0]", @"Buck Enable Configuration (effective only when BuckSeq[2:0] == 111)
+00 = Disabled. Active discharge behavior depends on BuckActDsc.
+01 = Enabled
+10 = Enabled when MPC is high
+11 = Reserved");
+            Descriptions(0x08).Add("Bit [2:1]", "BuckMd[1:0]", @"Buck Mode Select
+00 = Burst mode
+01 = Forced PWM mode
+10 = Forced PWM mode when MPC is high
+11 = Reserved");
+            Descriptions(0x08).Add("Bit 0", "BuckFst", @"Buck Fast Start
+0 = Normal startup current limit
+1 = Double the startup current to reduce the startup time by half");
+            // register 0x09
+            Descriptions(0x09).Add("Bit [7:5]", "BuckISet[2:0]", @"Buck Peak Current Limit Setting
+000: 50mA
+001: 100mA
+010: 150mA
+011: 200mA
+100: 250mA
+101: 300mA
+110: 350mA
+111: 400mA");
+            Descriptions(0x09).Add("Bit 4", "BuckCfg", @"Buck Configuration
+0 = set to 0 for burst mode
+1 = set to 1 for FPWM mode");
+            Descriptions(0x09).Add("Bit 3", "BuckInd", @"Buck Inductance Select
+0 = Inductance is 2.2µH
+1 = Inductance is 4.7µH");
+            Descriptions(0x09).Add("Bit 2", "BuckHysOff", @"Buck Hysteresis Off
+0 = Enable comparator hysteresis
+1 = Disable comparator hysteresis (recommended to reduce voltage ripple)");
+            Descriptions(0x09).Add("Bit 1", "BuckMinOT", @"Buck Minimum On-Time
+0 = Enable deglitch delay on comparator for better efficiency
+1 = Disable deglitch delay on comparator to minimize voltage ripple");
+            Descriptions(0x09).Add("Bit 0", "BuckInteg", @"Buck Integrate
+0 = Helps stabilize the buck regulator for high currents with small output capacitor
+1 = Better load regulation at high current (recommended for output capacitance > 6µF)");
+            // register 0x0a
+            Descriptions(0x0A).Add("Bit [4:0]", "LDOVSet[4:0]", @"LDO Output Voltage Setting
+0.9V to 4V, linear scale, 100mV increments
+00000 = 0.9V
+00001 = 1.0V
+…
+10000 = 2.5V
+…
+11111 = 4.0V");
+            // register 0x0b
+            Descriptions(0x0B).Add("Bit [7:5]", "LDOSeq[2:0]", @"LDO Enable Configuration (Read-Only)
+000 = Disabled
+001 = Enabled always when BAT/SYS is present
+010 = Enabled at 0% of Boot/POR Process Delay Control
+011 = Enabled at 25% of Boot/POR Process Delay Control
+100 = Enabled at 50% of Boot/POR Process Delay Control
+101 = Disabled
+110 = Controlled by LEN (MAX14750)
+111 = Controlled by LDOEn[1:0] after 100% of Boot/POR Process Delay Control");
+            Descriptions(0x0B).Add("Bit 4", "LDOActDsc", @"LDO Active Discharge Control
+0: LDO output will be discharged only entering off and hard-reset modes.
+1: LDO output will be discharged only entering off and hard-reset modes and when the enable is low.");
+            Descriptions(0x0B).Add("Bit 3", "LDOActDsc", @"LDO Active Discharge Control
+0: LDO output will be actively discharged only entering off and hard-reset modes.
+1: LDO output will be actively discharged only entering off and hard-reset modes and when the enable is low.");
+            Descriptions(0x0B).Add("Bit [2:1]", "LDOEn[1:0]", @"LDO Enable Configuration (effective only when LDOSeq[2:0] == 111)
+00 = Disabled
+01 = Enabled
+10 = Enabled when MPC is high
+11 = Reserved");
+            Descriptions(0x0B).Add("Bit 0", "LDOMode", @"LDO Mode Control
+0 = Normal LDO operating mode
+1 = Load switch mode. FET is either fully on or off depending on the state of LDOEn. When FET is on, the
+output is unregulated and is not affected by UVLO’s control block. This setting is internally latched and can
+change only when the LDO is disabled.");
+            // register 0x0c
+            Descriptions(0x0C).Add("Bit [7:5]", "SWSeq[2:0]", @"SW Enable Configuration (Read-Only)
+000 = Disabled
+001 = Enabled always when BAT/SYS is present
+010 = Enabled at 0% of Boot/POR Process Delay Control
+011 = Enabled at 25% of Boot/POR Process Delay Control
+100 = Enabled at 50% of Boot/POR Process Delay Control
+101 = Disabled
+110 = Controlled by SWEN (MAX14750)
+111 = Controlled by SWEn[1:0] after 100% of Boot/POR Process Delay Control");
+            Descriptions(0x0C).Add("Bit [2:1]", "SWSoftStart", @"SW Enable Configuration (effective only when SWSeq[2:0] == 111)
+00 = Disabled
+01 = Enabled
+10 = Enabled when MPC is high
+11 = Reserved");
+            // register 0x0d
+            Descriptions(0x0d).Add("Bit [5:4]", "BCVTm[1:0]", @"Battery Cell Voltage Timing
+00: Skip battery measurement
+01: Take battery measurement after 10ms delay
+10: Take battery measurement after 100ms delay
+11: Take battery measurement after 1000ms delay");
+            Descriptions(0x0d).Add("Bit [3:2]", "OCVTm[1:0]", @"Battery Open Cell Voltage Timing
+If this step is skipped, LCV measurement will be taken with switch closed
+00: Skip OCV measurement
+01: Take OCV measurement after 10ms delay
+10: Take OCV measurement after 100ms delay
+11: Take OCV measurement after 1000ms delay");
+            Descriptions(0x0d).Add("Bit [1:0]", "LCVTm[1:0]", @"Battery Loaded Cell Voltage Timing
+00: Skip LCV measurement
+01: Take LCV measurement after 10ms delay
+10: Take LCV measurement after 100ms delay
+11: Take LCV measurement after 1000ms delay");
+            // register 0x0e
+            Descriptions(0x0e).Add("Bit 7", "BIA", @"Battery Impedance Active
+Write 1 to start battery impedance measurement. If the measurement is already running, the write is ignored.
+Bit will remain high until the measurement is completed.
+0: Battery impedance measurement is not ongoing
+1: Battery impedance measurement is ongoing");
+            Descriptions(0x0e).Add("Bit 6", "BIMAbort", @"Battery Impedance Measurement Skip
+Write 1 to immediately abort the battery impedance measurement
+0: Battery impedance measurement is aborted
+1: Battery impedance measurement is not aborted yet");
+            Descriptions(0x0e).Add("Bit 3", "LcvDly2Skip", @"Write 1 to skip the second delay time (equal again to LCVTm) after LCV Measurement is taken. This second
+delay time allows VCC to recover its unloaded value before closing the power switch again.
+0: Wait second delay time
+1: Skip second delay time");
+            Descriptions(0x0e).Add("Bit [2:0]", "BatimpCur[2:0]", @"Battery Impedance Current
+000: 0
+001: 250µA
+010: 500µA
+011: 1mA
+100: 2mA
+101: 4mA
+110: 8mA
+111: Reserved");
+            // register 0x0f
+            Descriptions(0x0f).Add("Bit [7:0]", "BatV[7:0]", @"Battery Voltage Measurement Result
+8-bit battery voltage measurement: VCC = [ 2.6 * (BCV[7:0]/255) + 1.1 ] V
+If BCVTm[2:0] = 00, BCV[7:0] = 0000 0000.
+If error occurs or the measurement is aborted, BCV[7:0] =1111 1111.");
+            // register 0x10
+            Descriptions(0x10).Add("Bit [7:0]", "BatOCV[7:0]", @"Battery Voltage Measurement Result
+8-bit battery voltage measurement: VCC = [2.6 x (OCV[7:0]/255) + 1.1] V
+If OCVTm[2:0] = 00, OCV[7:0] =0000 0000.
+If error occurs or the measurement is aborted, OCV[7:0] =1111 1111.");
+            // register 0x11
+            Descriptions(0x11).Add("Bit [7:0]", "LCV[7:0]", @"Battery Voltage Measurement Result
+8 bit battery voltage measurement: VCC = [2.6 x ( LCV[7:0]/255) + 1.1] V
+If LCVTm[2:0] = 00, BCV[7:0] = 0000 0000.
+If error occurs or the measurement is aborted, LCV[7:0] =1111 1111.");
+            // register 0x19
+            Descriptions(0x19).Add("Bit 7", "MonEn", @"Monitor Enable
+0 = Monitor function disabled
+1 = Monitor function enabled");
+            Descriptions(0x19).Add("Bit 3", "MONtHiZ", @"MON OFF MODE Condition
+0 = Pulled Low by a 100k Pulldown Resistor
+1 = Hi-Z");
+            Descriptions(0x19).Add("Bit [2:0]", "MONCtr[2:0]", @"MON Pin Source Selection
+000 = MON connected to SWIN
+001 = MON connected to SWOUT
+010 = MON connected to BIN
+011 = MON connected to BOUT
+100 = MON connected to HVIN
+101 = MON connected to HVOUT
+110 = MON connected to LIN
+111 = MON connected to LOUT");
+            // register 0x1a
+            Descriptions(0x1a).Add("Bit [7:4]", "PwrRstCfg[4:0]", @"0000: Pin Controlled (MAX14750)
+0110: Push-Button Monitor (MAX14720)");
+            Descriptions(0x1a).Add("Bit 3", "SftRstCfg", @"Soft Reset Register Default
+0 = Registers do not reset to default values on soft reset
+1 = Registers reset to default values on soft reset");
+            Descriptions(0x1a).Add("Bit 2", "PFNPUDCfg", @"KIN Pullup/Pulldown Configuration
+0 = Pullups and pulldowns on control lines disabled
+1 = Selective pullups and pulldowns enabled on KIN pin");
+            Descriptions(0x1a).Add("Bit [1:0]", "BootDly[1:0]", @"Boot/POR Process tRESET Delay Control
+00 = 80ms
+01 = 120ms
+10 = 220ms
+11 = 420ms");
+            // register 0x1b
+            Descriptions(0x1a).Add("Bit 3", "/KIN", @"Input State
+0 = Pin low
+1 = Pin high");
+            Descriptions(0x1a).Add("Bit 2", "/KOUT", @"Input State
+0 = Pin low
+1 = Pin high");
+            Descriptions(0x1a).Add("Bit 1", "MPC", @"Input State
+0 = Pin low
+1 = Pin high");
+            Descriptions(0x1a).Add("Bit 0", "/RST", @"Input State
+0 = Pin low
+1 = Pin high");
+            // register 0x1c
+            Descriptions(0x1c).Add("Bit 7", "BoostHysOff", @"Boost Hysteresis Off
+0 = Enable comparator hysteresis
+1 = Disable comparator hysteresis (recommended to reduce voltage ripple)");
+            Descriptions(0x1c).Add("Bit 6", "BoostPacDsc", @"Boost Passive Discharge Control
+0: Boost output will be discharged only when entering off and hard-reset modes.
+1: Boost output will be discharged only when entering off and hard-reset modes and when BoostEn is set to 00.");
+            Descriptions(0x1c).Add("Bit 5", "BoostActDsc", @"Boost Active Discharge Control
+0: Boost output will be discharged only when entering off and hard-reset modes.
+1: Boost output will be discharged only when entering off and hard-reset modes and when BoostEn is set to 00.");
+            Descriptions(0x1c).Add("Bit 2", "BuckActDsc", @"Buck Passive Discharge Control
+0: Buck output will be discharged only when entering off and hard-reset modes.
+1: Buck output will be discharged only when entering off and hard-reset modes and when BuckEn is set to 00.");
+            Descriptions(0x1c).Add("Bit 1", "BuckActDsc", @"Buck Active Discharge Control
+0: Buck output will be discharged only when entering off and hard-reset modes.
+1: Buck output will be discharged only when entering off and hard-reset modes and when BuckEn is set to 00.");
+            Descriptions(0x1c).Add("Bit 0", "BuckFScl", @"Buck Force FET scaling (it reduces IQ by lowering the nMOS power to 20% of the nominal value)
+0: FET Scaling only enabled during the buck turn-on sequence
+1: FET Scaling enabled during the buck turn-on sequence and also in the buck active state.");
+            // register 0x1d
+            Descriptions(0x1d).Add("Bit 7", "StartOff", @"Start In Off
+1: The device will start in the off mode.
+0: The device begins the power-on sequence after a VCC power on reset.");
+            Descriptions(0x1d).Add("Bit 6", "GlbPasDsc", @"Global Passive Discharge
+0: Passive discharge loads are disabled in off mode.
+1: Passive discharge loads are enabled in off mode.");
+            Descriptions(0x1d).Add("Bit 0", "StayOn", @"Processor Handshake
+This bit is used to ensure that the processor booted correctly. This bit must be set within 5s of power-on to
+prevent the part from shutting down and returning to the power-off condition. This bit has no effect after being
+set.
+0 = Shutdown 5s after power-on
+1 = Stay on");
+            // register 0x1e
+            Descriptions(0x1e).Add("Bit 1", "BBBUVLOSel", @"Buck/Buck-Boost UVLO Select
+0: Buck and buck-boost are turned off/on according to LIN_UVLO thresholds
+1: Buck and buck-boost are turned off/on according to BIN_UVLO thresholds");
+            Descriptions(0x1e).Add("Bit 0", "LDOUVLOsel", @"LDO UVLO Select
+0: LDO is turned off/on according to LIN_UVLO thresholds
+1: LDO is turned off/on according to BIN_UVLO thresholds");
+            // register 0x1f
+            Descriptions(0x1f).Add("Bit [7:0]", "PWROFFCMD[7:0]", @"Power-Off Command
+Writing 0xB2 to this register will place the part in the off state/seal mode. Waking up the device from this mode
+requires a low pulse on /KIN.
+All other codes = Do nothing");
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HspGuiSourceV301/HSPGui/DeviceDescriptions/MAX30001Info.cs	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,320 @@
+/*******************************************************************************
+* Copyright (C) 2016 Maxim Integrated Products, Inc., All rights Reserved.
+* 
+* This software is protected by copyright laws of the United States and
+* of foreign countries. This material may also be protected by patent laws
+* and technology transfer regulations of the United States and of foreign
+* countries. This software is furnished under a license agreement and/or a
+* nondisclosure agreement and may only be used or reproduced in accordance
+* with the terms of those agreements. Dissemination of this information to
+* any party or parties not specified in the license agreement and/or
+* nondisclosure agreement is expressly prohibited.
+*
+* The above copyright notice and this permission notice shall be included
+* in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+* OTHER DEALINGS IN THE SOFTWARE.
+*
+* Except as contained in this notice, the name of Maxim Integrated
+* Products, Inc. shall not be used except as stated in the Maxim Integrated
+* Products, Inc. Branding Policy.
+*
+* The mere transfer of this software does not imply any licenses
+* of trade secrets, proprietary technology, copyrights, patents,
+* trademarks, maskwork rights, or any other form of intellectual
+* property whatsoever. Maxim Integrated Products, Inc. retains all
+* ownership rights.
+*******************************************************************************
+*/
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using HealthSensorPlatform.DeviceDescriptions;
+using RPCSupport.DeviceSupport;
+
+namespace Maxim.CustomControls
+{
+    class MAX30001Info : Device
+    {
+
+        public MAX30001Info()
+        {
+            deviceDetails = new DeviceDetails();
+            deviceDetails.type = DeviceDetails.eType.eMAX30001;
+
+            initalizeDescription();
+
+        }
+
+        void initalizeDescription()
+        {
+            Info = new RegisterInfo[] {
+                new RegisterInfo("STATUS",	    0x01,	3, RegisterInfo.RegisterType.ReadOnly),
+                new RegisterInfo("EN_INT",	    0x02,	3),
+                new RegisterInfo("EN_INT2",	    0x03,	3),
+                new RegisterInfo("MNGR_INT",	0x04,	3),
+                new RegisterInfo("MNGR_DYN",	0x05,	3),
+                new RegisterInfo("SW_RST",	    0x08,	3, RegisterInfo.RegisterType.WriteOnly),
+                new RegisterInfo("SYNCH",	    0x09,	3, RegisterInfo.RegisterType.WriteOnly),
+                new RegisterInfo("FIFO_RST",	0x0A,	3, RegisterInfo.RegisterType.WriteOnly),
+                new RegisterInfo("INFO",	    0x0F,	3, RegisterInfo.RegisterType.ReadOnly),
+                new RegisterInfo("CNFG_GEN",	0x10,	3),
+                new RegisterInfo("CNFG_CAL",	0x12,	3),
+                new RegisterInfo("CNFG_EMUX",	0x14,	3),
+                new RegisterInfo("CNFG_ECG",	0x15,	3),
+                new RegisterInfo("CNFG_BMUX",	0x17,	3),
+                new RegisterInfo("CNFG_BIOZ",	0x18,	3),
+                new RegisterInfo("CNFG_PACE",   0x1A,	3),
+                new RegisterInfo("CNFG_RTOR1",	0x1D,	3),
+                new RegisterInfo("CNFG_RTOR2",	0x1E,	3)
+           };
+
+             
+//bit description for STATUS
+Descriptions(0x01).Add("Bit [23]", "EINT", "ECG FIFO Interrupt: indicates ECG records meeting/exceeding the ECG FIFO Interrupt Threshold (EFIT) are available for read back.  Remains active until ECG FIFO is read back to the extent required to clear the EFIT condition.");
+Descriptions(0x01).Add("Bit [22]", "EOVF", "ECG FIFO Overflow: indicates the ECG FIFO has overflowed and the data record has been corrupted.  ");
+Descriptions(0x01).Add("Bit [21]", "FSTINT", "ECG Fast Recovery Mode: Issued when the ECG Fast Recovery Mode is engaged (either manually or automatically).");
+Descriptions(0x01).Add("Bit [20]", "DCLOFFINT", "DC Lead Off Detection Interrupt:  indicates the part has determined it is in an ECG/BIOZ Leads Off condition (as selected in CNFG_GEN) for more than 90ms. Remains active as long as the Leads Off condition persists even after a STATUS register read, then held until cleared by STATUS register read (30th SCLK) if condition has ceased.  Note: Exact time depends on BIOZ modulation frequency (the clock used for counting) and can range from 90ms to 140ms.");
+Descriptions(0x01).Add("Bit [19]", "BINT", "BIOZ FIFO Interrupt: indicates BIOZ records meeting/exceeding the BIOZ FIFO Interrupt Threshold (BFIT) are available for read back.  Remains active until BIOZ FIFO is read back to the extent required to clear the BFIT condition.");
+Descriptions(0x01).Add("Bit [18]", "BOVF", "BIOZ FIFO Overflow: indicates the BIOZ FIFO has overflowed and the data record has been corrupted.  ");
+Descriptions(0x01).Add("Bit [17]", "BOVER", "BIOZ Over Range: indicates the BIOZ output magnitude has exceeded the BIOZ High Threshold (BLOFF_HI_IT) for at least 100ms, recommended for use in 2 and 4 electrode BIOZ Lead Off detection.");
+Descriptions(0x01).Add("Bit [16]", "BUNDR", "BIOZ Under Range: indicates the BIOZ output magnitude has been bounded by the BIOZ Low Threshold (BLOFF_LO_IT) for at least 1.7 seconds, recommended for use in 4 electrode BIOZ Lead Off detection.");
+Descriptions(0x01).Add("Bit [15]", "BCGMON", "BIOZ Current Generator Monitor:  indicates the DRVP and/or DRVN current generator has been in a Lead Off condition for at least 128ms, recommended for use in 4 electrode BIOZ Lead Off detection.");
+Descriptions(0x01).Add("Bit [14]", "PINT", "PACE FIFO Interrupt: indicates PACE records are available for read back (should be used in conjunction with EINT).  ");
+Descriptions(0x01).Add("Bit [13]", "POVF", "PACE FIFO Overflow: indicates the PACE FIFO has overflowed and the data record has been corrupted.  ");
+Descriptions(0x01).Add("Bit [12]", "PEDGE", "PACE Edge Detection Interrupt: real time PACE edge indicator showing when the MAX30001 has determined a PACE edge occurred (note this is different than the PINT interrupt, which indicates when the detected edges are logged into the PACE FIFO).  Clear behavior is defined by CLR_PEDGE[1:0], see MNGR_INT for details.");
+Descriptions(0x01).Add("Bit [11]", "LONINT", "Ultra Low Power Lead On Detection Interrupt: indicates the part has determined it is in a Leads On condition (as selected in CNFG_GEN).  Remains active while the Leads On condition persists, then held until cleared by STATUS read back (32nd SCLK).");
+Descriptions(0x01).Add("Bit [10]", "RRINT", "ECG R to R Detector R Event Interrupt: Issued when the R to R detector has identified a new R event.");
+Descriptions(0x01).Add("Bit [9]", "SAMP", "Sample Synchronization Pulse:  issued on the ECG/BIOZ base-rate sampling instant, for use in assisting µC monitoring and synchronizing other peripheral operations and data, generally recommended for use as a dedicated interrupt.  ECG is the default, BIOZ is used only when ECG is not in use.  Frequency is selected by SAMP_IT[1:0], see MNGR_INT for details.  Clear behavior is defined by CLR_SAMP, see MNGR_INT for details.");
+Descriptions(0x01).Add("Bit [8]", "PLLINT", "PLL Unlocked Interrupt:  indicates the PLL has not yet achieved or has lost its phase lock.  PLLINT will only be asserted when the PLL is powered up and active (ECG and/or BIOZ Channel enabled).  Remains asserted while the PLL unlocked condition persists, then held until cleared by STATUS read back (32nd SCLK).  Note:  Writes to CNFG_GEN which either enable the PLL or alter the FMSTR setting will result in an issuance of PLLINT while the PLL re-achieves lock – users should allow this behavior to settle out before considering the data valid.");
+Descriptions(0x01).Add("Bit [5]", "BCGMP", "BIOZ Current Generator Monitor individual outputs:  indicates the DRVP or DRVN current generator has been in a Lead Off condition for at least 128ms.  These are not strictly interrupt terms, but are detailed status bits, covered by the BCGMON interrupt term.");
+Descriptions(0x01).Add("Bit [4]", "BCGMN", "BIOZ Current Generator Monitor individual outputs:  indicates the DRVP or DRVN current generator has been in a Lead Off condition for at least 128ms.  These are not strictly interrupt terms, but are detailed status bits, covered by the BCGMON interrupt term.");
+Descriptions(0x01).Add("Bit [3]", "LDOFF_PH", "DC Lead Off Detection Detailed Status:  indicates the part has determined (as selected by CNFG_GEN):  ");
+Descriptions(0x01).Add("Bit [2]", "LDOFF_PL", "ECGP/BIP is above the high threshold (VTHH), ECGP/BIP is below the low threshold (VTHL),");
+Descriptions(0x01).Add("Bit [1]", "LDOFF_NH", "ECGN/BIN is above the high threshold (VTHH), ECGN/BIN is below the low threshold (VTHL), respectively.");
+Descriptions(0x01).Add("Bit [0]", "LDOFF_NL", "Remain active as long as the Lead Off Detection is active and the Leads Off condition persists, then held until cleared by STATUS read back (32nd SCLK). These are not strictly interrupt terms, but are detailed status bits, covered by the DCLOFFINT bit.");
+ 
+//bit description for EN_INT
+Descriptions(0x02).Add("Bit [23]", "EN_EINT", @"Interrupt enable for INTB pin.  
+0 = Individual Interrupt bit is not included in (or masked from) the Interrupt logical OR Term 
+1 = Individual Interrupt bit is included in (or unmasked from) the Interrupt logical OR Term");
+Descriptions(0x02).Add("Bit [22]", "EN_EOVF", @"Interrupt enable for INTB pin.  
+0 = Individual Interrupt bit is not included in (or masked from) the Interrupt logical OR Term 
+1 = Individual Interrupt bit is included in (or unmasked from) the Interrupt logical OR Term");
+Descriptions(0x02).Add("Bit [21]", "EN_FSTINT", @"Interrupt enable for INTB pin.  
+0 = Individual Interrupt bit is not included in (or masked from) the Interrupt logical OR Term 
+1 = Individual Interrupt bit is included in (or unmasked from) the Interrupt logical OR Term");
+Descriptions(0x02).Add("Bit [20]", "EN_DCLOFFINT", @"Interrupt enable for INTB pin.  
+0 = Individual Interrupt bit is not included in (or masked from) the Interrupt logical OR Term 
+1 = Individual Interrupt bit is included in (or unmasked from) the Interrupt logical OR Term");
+Descriptions(0x02).Add("Bit [19]", "EN_BINT", @"Interrupt enable for INTB pin.  
+0 = Individual Interrupt bit is not included in (or masked from) the Interrupt logical OR Term 
+1 = Individual Interrupt bit is included in (or unmasked from) the Interrupt logical OR Term");
+Descriptions(0x02).Add("Bit [18]", "EN_BOVF", @"Interrupt enable for INTB pin.  
+0 = Individual Interrupt bit is not included in (or masked from) the Interrupt logical OR Term 
+1 = Individual Interrupt bit is included in (or unmasked from) the Interrupt logical OR Term");
+Descriptions(0x02).Add("Bit [17]", "EN_BOVER", @"Interrupt enable for INTB pin.  
+0 = Individual Interrupt bit is not included in (or masked from) the Interrupt logical OR Term 
+1 = Individual Interrupt bit is included in (or unmasked from) the Interrupt logical OR Term");
+Descriptions(0x02).Add("Bit [16]", "EN_BUNDR", @"Interrupt enable for INTB pin.  
+0 = Individual Interrupt bit is not included in (or masked from) the Interrupt logical OR Term 
+1 = Individual Interrupt bit is included in (or unmasked from) the Interrupt logical OR Term");
+Descriptions(0x02).Add("Bit [15]", "EN_BCGMON", @"Interrupt enable for INTB pin.  
+0 = Individual Interrupt bit is not included in (or masked from) the Interrupt logical OR Term 
+1 = Individual Interrupt bit is included in (or unmasked from) the Interrupt logical OR Term");
+Descriptions(0x02).Add("Bit [14]", "EN_PINT", @"Interrupt enable for INTB pin.  
+0 = Individual Interrupt bit is not included in (or masked from) the Interrupt logical OR Term 
+1 = Individual Interrupt bit is included in (or unmasked from) the Interrupt logical OR Term");
+Descriptions(0x02).Add("Bit [13]", "EN_POVF", @"Interrupt enable for INTB pin.  
+0 = Individual Interrupt bit is not included in (or masked from) the Interrupt logical OR Term 
+1 = Individual Interrupt bit is included in (or unmasked from) the Interrupt logical OR Term");
+Descriptions(0x02).Add("Bit [12]", "EN_PEDGE", @"Interrupt enable for INTB pin.  
+0 = Individual Interrupt bit is not included in (or masked from) the Interrupt logical OR Term 
+1 = Individual Interrupt bit is included in (or unmasked from) the Interrupt logical OR Term");
+Descriptions(0x02).Add("Bit [11]", "EN_LONINT", @"Interrupt enable for INTB pin.  
+0 = Individual Interrupt bit is not included in (or masked from) the Interrupt logical OR Term 
+1 = Individual Interrupt bit is included in (or unmasked from) the Interrupt logical OR Term");
+Descriptions(0x02).Add("Bit [10]", "EN_RRINT", @"Interrupt enable for INTB pin.  
+0 = Individual Interrupt bit is not included in (or masked from) the Interrupt logical OR Term 
+1 = Individual Interrupt bit is included in (or unmasked from) the Interrupt logical OR Term");
+Descriptions(0x02).Add("Bit [9]", "EN_SAMP", @"Interrupt enable for INTB pin.  
+0 = Individual Interrupt bit is not included in (or masked from) the Interrupt logical OR Term 
+1 = Individual Interrupt bit is included in (or unmasked from) the Interrupt logical OR Term");
+Descriptions(0x02).Add("Bit [8]", "EN_PLLINT", @"Interrupt enable for INTB pin.  
+0 = Individual Interrupt bit is not included in (or masked from) the Interrupt logical OR Term 
+1 = Individual Interrupt bit is included in (or unmasked from) the Interrupt logical OR Term");
+Descriptions(0x02).Add("Bit [1:0]", "INTB_TYPE[1:0]", "INTB Port Type (EN_INT Selections)");
+ 
+//bit description for EN_INT2
+Descriptions(0x03).Add("Bit [23]", "EN_EINT2", @"Interrupt enable for INT2B pin.  
+0 = Individual Interrupt bit is not included in (or masked from) the Interrupt logical OR Term 
+1 = Individual Interrupt bit is included in (or unmasked from) the Interrupt logical OR Term");
+Descriptions(0x03).Add("Bit [22]", "EN_EOVF2", @"Interrupt enable for INT2B pin.  
+0 = Individual Interrupt bit is not included in (or masked from) the Interrupt logical OR Term 
+1 = Individual Interrupt bit is included in (or unmasked from) the Interrupt logical OR Term");
+Descriptions(0x03).Add("Bit [21]", "EN_FSTINT2", @"Interrupt enable for INT2B pin.  
+0 = Individual Interrupt bit is not included in (or masked from) the Interrupt logical OR Term 
+1 = Individual Interrupt bit is included in (or unmasked from) the Interrupt logical OR Term");
+Descriptions(0x03).Add("Bit [20]", "EN_DCLOFFINT2", @"Interrupt enable for INT2B pin.  
+0 = Individual Interrupt bit is not included in (or masked from) the Interrupt logical OR Term 
+1 = Individual Interrupt bit is included in (or unmasked from) the Interrupt logical OR Term");
+Descriptions(0x03).Add("Bit [19]", "EN_BINT2", @"Interrupt enable for INT2B pin.  
+0 = Individual Interrupt bit is not included in (or masked from) the Interrupt logical OR Term 
+1 = Individual Interrupt bit is included in (or unmasked from) the Interrupt logical OR Term");
+Descriptions(0x03).Add("Bit [18]", "EN_BOVF2", @"Interrupt enable for INT2B pin.  
+0 = Individual Interrupt bit is not included in (or masked from) the Interrupt logical OR Term 
+1 = Individual Interrupt bit is included in (or unmasked from) the Interrupt logical OR Term");
+Descriptions(0x03).Add("Bit [17]", "EN_BOVER2", @"Interrupt enable for INT2B pin.  
+0 = Individual Interrupt bit is not included in (or masked from) the Interrupt logical OR Term 
+1 = Individual Interrupt bit is included in (or unmasked from) the Interrupt logical OR Term");
+Descriptions(0x03).Add("Bit [16]", "EN_BUNDR2", @"Interrupt enable for INT2B pin.  
+0 = Individual Interrupt bit is not included in (or masked from) the Interrupt logical OR Term 
+1 = Individual Interrupt bit is included in (or unmasked from) the Interrupt logical OR Term");
+Descriptions(0x03).Add("Bit [15]", "EN_BCGMON2", @"Interrupt enable for INT2B pin.  
+0 = Individual Interrupt bit is not included in (or masked from) the Interrupt logical OR Term 
+1 = Individual Interrupt bit is included in (or unmasked from) the Interrupt logical OR Term");
+Descriptions(0x03).Add("Bit [14]", "EN_PINT2", @"Interrupt enable for INT2B pin.  
+0 = Individual Interrupt bit is not included in (or masked from) the Interrupt logical OR Term 
+1 = Individual Interrupt bit is included in (or unmasked from) the Interrupt logical OR Term");
+Descriptions(0x03).Add("Bit [13]", "EN_POVF2", @"Interrupt enable for INT2B pin.  
+0 = Individual Interrupt bit is not included in (or masked from) the Interrupt logical OR Term 
+1 = Individual Interrupt bit is included in (or unmasked from) the Interrupt logical OR Term");
+Descriptions(0x03).Add("Bit [12]", "EN_PEDGE2", @"Interrupt enable for INT2B pin.  
+0 = Individual Interrupt bit is not included in (or masked from) the Interrupt logical OR Term 
+1 = Individual Interrupt bit is included in (or unmasked from) the Interrupt logical OR Term");
+Descriptions(0x03).Add("Bit [11]", "EN_LONINT2", @"Interrupt enable for INT2B pin.  
+0 = Individual Interrupt bit is not included in (or masked from) the Interrupt logical OR Term 
+1 = Individual Interrupt bit is included in (or unmasked from) the Interrupt logical OR Term");
+Descriptions(0x03).Add("Bit [10]", "EN_RRINT2", @"Interrupt enable for INT2B pin.  
+0 = Individual Interrupt bit is not included in (or masked from) the Interrupt logical OR Term 
+1 = Individual Interrupt bit is included in (or unmasked from) the Interrupt logical OR Term");
+Descriptions(0x03).Add("Bit [9]", "EN_SAMP2", @"Interrupt enable for INT2B pin.  
+0 = Individual Interrupt bit is not included in (or masked from) the Interrupt logical OR Term 
+1 = Individual Interrupt bit is included in (or unmasked from) the Interrupt logical OR Term");
+Descriptions(0x03).Add("Bit [8]", "EN_PLLINT2", @"Interrupt enable for INT2B pin.  
+0 = Individual Interrupt bit is not included in (or masked from) the Interrupt logical OR Term 
+1 = Individual Interrupt bit is included in (or unmasked from) the Interrupt logical OR Term");
+Descriptions(0x03).Add("Bit [1:0]", "INTB2_TYPE[1:0]", "INT2B Port Type (EN_INT Selections)");
+ 
+//bit description for MNGR_INT
+Descriptions(0x04).Add("Bit [23:19]", "EFIT[4:0]", "ECG FIFO Interrupt Threshold (issues EINT based on number of unread FIFO records)");
+Descriptions(0x04).Add("Bit [18:16]", "BFIT[2:0]", "BIOZ FIFO Interrupt Threshold (issues BINT based on number of unread FIFO records)");
+Descriptions(0x04).Add("Bit [6]", "CLR_FAST", "FAST MODE Interrupt Clear Behavior ");
+Descriptions(0x04).Add("Bit [5:4]", "CLR_RRINT[1:0]", "RTOR R Detect Interrupt (RRINT) Clear Behavior ");
+Descriptions(0x04).Add("Bit [3]", "CLR_PEDGE", "PACE Edge Detect Interrupt (PEDGE) Clear Behavior ");
+Descriptions(0x04).Add("Bit [2]", "CLR_SAMP", "Sample Synchronization Pulse (SAMP) Clear Behavior ");
+Descriptions(0x04).Add("Bit [1:0]", "SAMP_IT[1:0]", "Sample Synchronization Pulse (SAMP) Frequency ");
+ 
+//bit description for MNGR_DYN
+Descriptions(0x05).Add("Bit [23:22]", "FAST[1:0]", "ECG Channel Fast Recovery Mode Selection (aka ECG High Pass Filter Bypass)");
+Descriptions(0x05).Add("Bit [21:16]", "FAST_TH[5:0]", "Automatic Fast Recovery Threshold  ");
+Descriptions(0x05).Add("Bit [15:8]", "BLOFF_HI_IT[7:0]", "BIOZ AC Lead Off Over-Range Threshold ");
+Descriptions(0x05).Add("Bit [7:0]", "BLOFF_LO_IT[7:0]", "BIOZ AC Lead Off Under-Range Threshold ");
+ 
+//bit description for SW_RST
+Descriptions(0x08).Add("Bit [23:0]", "RESET", "Data Required for Execution  = 00_00_00");
+ 
+//bit description for SYNCH
+Descriptions(0x09).Add("Bit [23:0]", "SYNCH", "Data Required for Execution  = 00_00_00");
+ 
+//bit description for FIFO_RST
+Descriptions(0x0A).Add("Bit [23:0]", "FIFO_RST", "Data Required for Execution  = 00_00_00");
+ 
+//bit description for INFO
+Descriptions(0x0F).Add("Bit [19:16]", "REV_ID[3:0]", "Revision ID");
+//Descriptions(0x0F).Add("Bit [14]", "SAMPLE", "Sample - Experimental Functionality Enable\n0 - Production functionality only\n1 - Experimental functionality");
+//Descriptions(0x0F).Add("Bit [13:12]", "PART_ID[1:0]", "Part ID\n00 - MAX30004\n01 - MAX30001\n10 - MAX30002\n11 - MAX30003");
+//Descriptions(0x0F).Add("Bit [11:0]", "SERIAL[11:0]", "Serial Number");
+ 
+//bit description for CNFG_GEN
+Descriptions(0x10).Add("Bit [23:22]", "EN_ULP_LON[1:0]", "Ultra Low Power Lead On Detection Enable");
+Descriptions(0x10).Add("Bit [21:20]", "FMSTR[1:0]", "Master Clock Frequency");
+Descriptions(0x10).Add("Bit [19]", "EN_ECG", "ECG Channel Enable");
+Descriptions(0x10).Add("Bit [18]", "EN_BIOZ", "BIOZ Channel Enable");
+Descriptions(0x10).Add("Bit [17]", "EN_PACE", "PACE Channel Enable");
+Descriptions(0x10).Add("Bit [15:14]", "EN_BLOFF[1:0]", "BIOZ Digital Lead Off Detection Enable ");
+Descriptions(0x10).Add("Bit [13:12]", "EN_DCLOFF", "DC Lead Off Detection Enable");
+Descriptions(0x10).Add("Bit [11]", "DCLOFF_IPOL", "DC Lead Off Current Polarity (if current sources are enabled/connected)");
+Descriptions(0x10).Add("Bit [10:8]", "DCLOFF_IMAG[2:0]", "DC Lead Off Current Magnitude Selection");
+Descriptions(0x10).Add("Bit [7:6]", "DCLOFF_VTH[1:0]", "DC Lead Off Voltage Threshold Selection ");
+Descriptions(0x10).Add("Bit [5:4]", "EN_RBIAS[1:0]", "Enable and Select Resistive Lead Bias Mode ");
+Descriptions(0x10).Add("Bit [3:2]", "RBIASV[1:0]", "Resistive Bias Mode Value Selection ");
+Descriptions(0x10).Add("Bit [1]", "RBIASP", "Enables Resistive Bias on Positive Input");
+Descriptions(0x10).Add("Bit [0]", "RBIASN", "Enables Resistive Bias on Negative Input");
+ 
+//bit description for CNFG_CAL
+Descriptions(0x12).Add("Bit [22]", "CAL_EN_VCAL", "Calibration Source (VCALP and VCALN) Enable ");
+Descriptions(0x12).Add("Bit [21]", "CAL_VMODE", "Calibration Source Mode Selection ");
+Descriptions(0x12).Add("Bit [20]", "CAL_VMAG", "Calibration Source Magnitude Selection (VMAG)");
+Descriptions(0x12).Add("Bit [14:12]", "CAL_FCAL[2:0]", "Calibration Source Frequency Selection (FCAL)");
+Descriptions(0x12).Add("Bit [11]", "CAL_FIFTY", "Calibration Source Duty Cycle Mode Selection");
+Descriptions(0x12).Add("Bit [10:0]", "CAL_THIGH[10:0]", "Calibration Source Time High Selection  ");
+ 
+//bit description for CNFG_EMUX
+Descriptions(0x14).Add("Bit [23]", "EMUX_POL", "ECG Input Polarity Selection");
+Descriptions(0x14).Add("Bit [21]", "EMUX_OPENP", "Open the ECGP Input Switch (most often used for testing and calibration studies)");
+Descriptions(0x14).Add("Bit [20]", "EMUX_OPENN", "Open the ECGN Input Switch (most often used for testing and calibration studies)");
+Descriptions(0x14).Add("Bit [19:18]", "EMUX_CALP_SEL[1:0]", "ECGP Calibration Selection");
+Descriptions(0x14).Add("Bit [17:16]", "EMUX_CALN_SEL[1:0]", "ECGN Calibration Selection");
+ 
+//bit description for CNFG_ECG
+Descriptions(0x15).Add("Bit [23:22]", "ECG_RATE[1:0]", "ECG Data Rate (also dependent on FMSTR selection, see CNFG_GEN and table below):");
+Descriptions(0x15).Add("Bit [17:16]", "ECG_GAIN[1:0]", "ECG Channel Gain Setting ");
+Descriptions(0x15).Add("Bit [14]", "ECG_DHPF", "ECG Channel Digital High Pass Filter Cutoff Frequency");
+Descriptions(0x15).Add("Bit [13:12]", "ECG_DLPF[1:0]", "ECG Channel Digital Low Pass Filter Cutoff Frequency");
+ 
+//bit description for CNFG_BMUX
+Descriptions(0x17).Add("Bit [21]", "BMUX_OPENP", "Open the BIP Input Switch (most often used for testing and calibration studies)");
+Descriptions(0x17).Add("Bit [20]", "BMUX_OPENN", "Open the BIN Input Switch (most often used for testing and calibration studies)");
+Descriptions(0x17).Add("Bit [19:18]", "BMUX_CALP_SEL[1:0]", "BIP Calibration Selection (VCAL application to BIP/N inputs intended for use in PACE testing only.)");
+Descriptions(0x17).Add("Bit [17:16]", "BMUX_CALN_SEL[1:0]", "BIN Calibration Selection (VCAL application to BIP/N inputs intended for use in PACE testing only.)");
+Descriptions(0x17).Add("Bit [13:12]", "BMUX_CG_MODE[1:0]", "BIOZ Current Generator Mode Selection");
+Descriptions(0x17).Add("Bit [11]", "BMUX_EN_BIST", "BIOZ Modulated Resistance Built-In-Self-Test (RMOD BIST) Mode Enable");
+Descriptions(0x17).Add("Bit [10:8]", "BMUX_RNOM[2:0]", "BIOZ RMOD BIST Nominal Resistance Selection");
+Descriptions(0x17).Add("Bit [6:4]", "BMUX_RMOD[2:0]", "BIOZ RMOD BIST Modulated Resistance Selection (See RMOD BIST Settings Table for details.)");
+Descriptions(0x17).Add("Bit [1:0]", "BMUX_FBIST[1:0]", "BIOZ RMOD BIST Frequency Selection");
+ 
+//bit description for CNFG_BIOZ
+Descriptions(0x18).Add("Bit [23]", "BIOZ_RATE", "BIOZ Data Rate (also dependent on FMSTR selection, see CNFG_GEN):");
+Descriptions(0x18).Add("Bit [22:20]", "BIOZ_AHPF[2:0]", "BIOZ/PACE Channel Analog High Pass Filter Cutoff Frequency and Bypass");
+Descriptions(0x18).Add("Bit [19]", "EXT_RBIAS", "External Resistor Bias Enable");
+Descriptions(0x18).Add("Bit [17:16]", "BIOZ_GAIN[1:0]", "BIOZ Channel Gain Setting ");
+Descriptions(0x18).Add("Bit [15:14]", "BIOZ_DHPF[1:0]", "BIOZ Channel Digital High Pass Filter Cutoff Frequency");
+Descriptions(0x18).Add("Bit [13:12]", "BIOZ_DLPF[1:0]", "BIOZ Channel Digital Low Pass Filter Cutoff Frequency");
+Descriptions(0x18).Add("Bit [11:8]", "BIOZ_FCGEN[3:0]", "BIOZ Current Generator Modulation Frequency");
+Descriptions(0x18).Add("Bit [7]", "BIOZ_CGMON", "BIOZ Current Generator Monitor");
+Descriptions(0x18).Add("Bit [6:4]", "BIOZ_CGMAG[2:0]", "BIOZ Current Generator Magnitude");
+Descriptions(0x18).Add("Bit [3:0]", "BIOZ_PHOFF[3:0]", "BIOZ Current Generator Modulation Phase Offset ");
+ 
+//bit description for CNFG_PACE
+Descriptions(0x1A).Add("Bit [23]", "PACE_POL", "PACE Input Polarity Selection");
+Descriptions(0x1A).Add("Bit [19]", "PACE_GN_DIFF_OFF", "PACE Differentiator (Derivative) Mode");
+Descriptions(0x1A).Add("Bit [18:16]", "PACE_GAIN[2:0]", "PACE Channel Gain Selection");
+Descriptions(0x1A).Add("Bit [14]", "PACE_AOUT_LBW", "PACE Analog Output Buffer Bandwidth Mode ");
+Descriptions(0x1A).Add("Bit [13:12]", "PACE_AOUT[1:0]", "PACE Single Ended Analog Output Buffer Signal Monitoring Selection");
+Descriptions(0x1A).Add("Bit [7:4]", "PACE_DACP[3:0]", "PACE Detector Positive Comparator Threshold");
+Descriptions(0x1A).Add("Bit [3:0]", "PACE_DACN[3:0]", "PACE Detector Negative Comparator Threshold");
+ 
+//bit description for CNFG_RTOR1
+Descriptions(0x1D).Add("Bit [23:20]", "RTOR_WNDW[3:0]", "R to R Window Averaging (Window Width = RTOR_WNDW[3:0]*8ms)");
+Descriptions(0x1D).Add("Bit [19:16]", "RTOR_GAIN[3:0]", "R to R Gain (where Gain = 2^RTOR_GAIN[3:0], plus an auto-scale option)");
+Descriptions(0x1D).Add("Bit [15]", "EN_RTOR", "ECG RTOR Detection Enable  ");
+Descriptions(0x1D).Add("Bit [13:12]", "RTOR_PAVG[1:0]", "R to R Peak Averaging Weight Factor");
+Descriptions(0x1D).Add("Bit [11:8]", "RTOR_PTSF[3:0]", "R to R Peak Threshold Scaling Factor");
+ 
+//bit description for CNFG_RTOR2
+Descriptions(0x1E).Add("Bit [21:16]", "RTOR_HOFF[5:0]", "R to R Minimum Hold Off ");
+Descriptions(0x1E).Add("Bit [13:12]", "RTOR_RAVG[1:0]", "R to R Interval Averaging Weight Factor");
+Descriptions(0x1E).Add("Bit [10:8]", "RTOR_RHSF[2:0]", "R to R Interval Hold Off Scaling Factor");
+
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HspGuiSourceV301/HSPGui/DeviceDescriptions/MAX30003Info.cs	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,330 @@
+/*******************************************************************************
+* Copyright (C) 2016 Maxim Integrated Products, Inc., All rights Reserved.
+* 
+* This software is protected by copyright laws of the United States and
+* of foreign countries. This material may also be protected by patent laws
+* and technology transfer regulations of the United States and of foreign
+* countries. This software is furnished under a license agreement and/or a
+* nondisclosure agreement and may only be used or reproduced in accordance
+* with the terms of those agreements. Dissemination of this information to
+* any party or parties not specified in the license agreement and/or
+* nondisclosure agreement is expressly prohibited.
+*
+* The above copyright notice and this permission notice shall be included
+* in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+* OTHER DEALINGS IN THE SOFTWARE.
+*
+* Except as contained in this notice, the name of Maxim Integrated
+* Products, Inc. shall not be used except as stated in the Maxim Integrated
+* Products, Inc. Branding Policy.
+*
+* The mere transfer of this software does not imply any licenses
+* of trade secrets, proprietary technology, copyrights, patents,
+* trademarks, maskwork rights, or any other form of intellectual
+* property whatsoever. Maxim Integrated Products, Inc. retains all
+* ownership rights.
+*******************************************************************************
+*/
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using HealthSensorPlatform.DeviceDescriptions;
+using RPCSupport.DeviceSupport;
+
+namespace Maxim.CustomControls
+{
+    class MAX30003Info : Device
+    {
+
+        public MAX30003Info()
+        {
+            deviceDetails = new DeviceDetails();
+            deviceDetails.type = DeviceDetails.eType.eMAX30001;
+
+            initalizeDescription();
+
+        }
+
+        void initalizeDescription()
+        {
+            Info = new RegisterInfo[] {
+                new RegisterInfo("STATUS",	    0x01,	3, RegisterInfo.RegisterType.ReadOnly),
+                new RegisterInfo("EN_INT",	    0x02,	3),
+                new RegisterInfo("EN_INT2",	    0x03,	3),
+                new RegisterInfo("MNGR_INT",	0x04,	3),
+                new RegisterInfo("MNGR_DYN",	0x05,	3),
+                new RegisterInfo("SW_RST",	    0x08,	3, RegisterInfo.RegisterType.WriteOnly),
+                new RegisterInfo("SYNCH",	    0x09,	3, RegisterInfo.RegisterType.WriteOnly),
+                new RegisterInfo("FIFO_RST",	0x0A,	3, RegisterInfo.RegisterType.WriteOnly),
+                new RegisterInfo("INFO",	    0x0F,	3, RegisterInfo.RegisterType.ReadOnly),
+                new RegisterInfo("CNFG_GEN",	0x10,	3),
+                new RegisterInfo("CNFG_CAL",	0x12,	3),
+                new RegisterInfo("CNFG_EMUX",	0x14,	3),
+                new RegisterInfo("CNFG_ECG",	0x15,	3),
+                //new RegisterInfo("CNFG_BMUX",	0x17,	3),
+                //new RegisterInfo("CNFG_BIOZ",	0x18,	3),
+                //new RegisterInfo("CNFG_PACE",   0x1A,	3),
+                new RegisterInfo("CNFG_RTOR1",	0x1D,	3),
+                new RegisterInfo("CNFG_RTOR2",	0x1E,	3)
+           };
+
+
+            //bit description for STATUS
+            Descriptions(0x01).Add("Bit [23]", "EINT", "ECG FIFO Interrupt: indicates ECG records meeting/exceeding the ECG FIFO Interrupt Threshold (EFIT) are available for read back.  Remains active until ECG FIFO is read back to the extent required to clear the EFIT condition.");
+            Descriptions(0x01).Add("Bit [22]", "EOVF", "ECG FIFO Overflow: indicates the ECG FIFO has overflowed and the data record has been corrupted.  ");
+            Descriptions(0x01).Add("Bit [21]", "FSTINT", "ECG Fast Recovery Mode: Issued when the ECG Fast Recovery Mode is engaged (either manually or automatically).");
+            Descriptions(0x01).Add("Bit [20]", "DCLOFFINT", "DC Lead Off Detection Interrupt:  indicates the part has determined it is in an ECG/BIOZ Leads Off condition (as selected in CNFG_GEN) for more than 90ms. Remains active as long as the Leads Off condition persists even after a STATUS register read, then held until cleared by STATUS register read (30th SCLK) if condition has ceased.  Note: Exact time depends on BIOZ modulation frequency (the clock used for counting) and can range from 90ms to 140ms.");
+            /*
+            Descriptions(0x01).Add("Bit [19]", "BINT", "BIOZ FIFO Interrupt: indicates BIOZ records meeting/exceeding the BIOZ FIFO Interrupt Threshold (BFIT) are available for read back.  Remains active until BIOZ FIFO is read back to the extent required to clear the BFIT condition.");
+            Descriptions(0x01).Add("Bit [18]", "BOVF", "BIOZ FIFO Overflow: indicates the BIOZ FIFO has overflowed and the data record has been corrupted.  ");
+            Descriptions(0x01).Add("Bit [17]", "BOVER", "BIOZ Over Range: indicates the BIOZ output magnitude has exceeded the BIOZ High Threshold (BLOFF_HI_IT) for at least 100ms, recommended for use in 2 and 4 electrode BIOZ Lead Off detection.");
+            Descriptions(0x01).Add("Bit [16]", "BUNDR", "BIOZ Under Range: indicates the BIOZ output magnitude has been bounded by the BIOZ Low Threshold (BLOFF_LO_IT) for at least 1.7 seconds, recommended for use in 4 electrode BIOZ Lead Off detection.");
+            Descriptions(0x01).Add("Bit [15]", "BCGMON", "BIOZ Current Generator Monitor:  indicates the DRVP and/or DRVN current generator has been in a Lead Off condition for at least 128ms, recommended for use in 4 electrode BIOZ Lead Off detection.");
+            Descriptions(0x01).Add("Bit [14]", "PINT", "PACE FIFO Interrupt: indicates PACE records are available for read back (should be used in conjunction with EINT).  ");
+            Descriptions(0x01).Add("Bit [13]", "POVF", "PACE FIFO Overflow: indicates the PACE FIFO has overflowed and the data record has been corrupted.  ");
+            Descriptions(0x01).Add("Bit [12]", "PEDGE", "PACE Edge Detection Interrupt: real time PACE edge indicator showing when the MAX30001 has determined a PACE edge occurred (note this is different than the PINT interrupt, which indicates when the detected edges are logged into the PACE FIFO).  Clear behavior is defined by CLR_PEDGE[1:0], see MNGR_INT for details.");
+            */
+            Descriptions(0x01).Add("Bit [11]", "LONINT", "Ultra Low Power Lead On Detection Interrupt: indicates the part has determined it is in a Leads On condition (as selected in CNFG_GEN).  Remains active while the Leads On condition persists, then held until cleared by STATUS read back (32nd SCLK).");
+            Descriptions(0x01).Add("Bit [10]", "RRINT", "ECG R to R Detector R Event Interrupt: Issued when the R to R detector has identified a new R event.");
+            Descriptions(0x01).Add("Bit [9]", "SAMP", "Sample Synchronization Pulse:  issued on the ECG/BIOZ base-rate sampling instant, for use in assisting µC monitoring and synchronizing other peripheral operations and data, generally recommended for use as a dedicated interrupt.  ECG is the default, BIOZ is used only when ECG is not in use.  Frequency is selected by SAMP_IT[1:0], see MNGR_INT for details.  Clear behavior is defined by CLR_SAMP, see MNGR_INT for details.");
+            Descriptions(0x01).Add("Bit [8]", "PLLINT", "PLL Unlocked Interrupt:  indicates the PLL has not yet achieved or has lost its phase lock.  PLLINT will only be asserted when the PLL is powered up and active (ECG and/or BIOZ Channel enabled).  Remains asserted while the PLL unlocked condition persists, then held until cleared by STATUS read back (32nd SCLK).  Note:  Writes to CNFG_GEN which either enable the PLL or alter the FMSTR setting will result in an issuance of PLLINT while the PLL re-achieves lock – users should allow this behavior to settle out before considering the data valid.");
+            /*
+            Descriptions(0x01).Add("Bit [5]", "BCGMP", "BIOZ Current Generator Monitor individual outputs:  indicates the DRVP or DRVN current generator has been in a Lead Off condition for at least 128ms.  These are not strictly interrupt terms, but are detailed status bits, covered by the BCGMON interrupt term.");
+            Descriptions(0x01).Add("Bit [4]", "BCGMN", "BIOZ Current Generator Monitor individual outputs:  indicates the DRVP or DRVN current generator has been in a Lead Off condition for at least 128ms.  These are not strictly interrupt terms, but are detailed status bits, covered by the BCGMON interrupt term.");
+            */
+            Descriptions(0x01).Add("Bit [3]", "LDOFF_PH", "DC Lead Off Detection Detailed Status:  indicates the part has determined (as selected by CNFG_GEN):  ");
+            Descriptions(0x01).Add("Bit [2]", "LDOFF_PL", "ECGP/BIP is above the high threshold (VTHH), ECGP/BIP is below the low threshold (VTHL),");
+            Descriptions(0x01).Add("Bit [1]", "LDOFF_NH", "ECGN/BIN is above the high threshold (VTHH), ECGN/BIN is below the low threshold (VTHL), respectively.");
+            Descriptions(0x01).Add("Bit [0]", "LDOFF_NL", "Remain active as long as the Lead Off Detection is active and the Leads Off condition persists, then held until cleared by STATUS read back (32nd SCLK). These are not strictly interrupt terms, but are detailed status bits, covered by the DCLOFFINT bit.");
+
+            //bit description for EN_INT
+            Descriptions(0x02).Add("Bit [23]", "EN_EINT", @"Interrupt enable for INTB pin.  
+0 = Individual Interrupt bit is not included in (or masked from) the Interrupt logical OR Term 
+1 = Individual Interrupt bit is included in (or unmasked from) the Interrupt logical OR Term");
+            Descriptions(0x02).Add("Bit [22]", "EN_EOVF", @"Interrupt enable for INTB pin.  
+0 = Individual Interrupt bit is not included in (or masked from) the Interrupt logical OR Term 
+1 = Individual Interrupt bit is included in (or unmasked from) the Interrupt logical OR Term");
+            Descriptions(0x02).Add("Bit [21]", "EN_FSTINT", @"Interrupt enable for INTB pin.  
+0 = Individual Interrupt bit is not included in (or masked from) the Interrupt logical OR Term 
+1 = Individual Interrupt bit is included in (or unmasked from) the Interrupt logical OR Term");
+            Descriptions(0x02).Add("Bit [20]", "EN_DCLOFFINT", @"Interrupt enable for INTB pin.  
+0 = Individual Interrupt bit is not included in (or masked from) the Interrupt logical OR Term 
+1 = Individual Interrupt bit is included in (or unmasked from) the Interrupt logical OR Term");
+            /*
+            Descriptions(0x02).Add("Bit [19]", "EN_BINT", @"Interrupt enable for INTB pin.  
+0 = Individual Interrupt bit is not included in (or masked from) the Interrupt logical OR Term 
+1 = Individual Interrupt bit is included in (or unmasked from) the Interrupt logical OR Term");
+            Descriptions(0x02).Add("Bit [18]", "EN_BOVF", @"Interrupt enable for INTB pin.  
+0 = Individual Interrupt bit is not included in (or masked from) the Interrupt logical OR Term 
+1 = Individual Interrupt bit is included in (or unmasked from) the Interrupt logical OR Term");
+            Descriptions(0x02).Add("Bit [17]", "EN_BOVER", @"Interrupt enable for INTB pin.  
+0 = Individual Interrupt bit is not included in (or masked from) the Interrupt logical OR Term 
+1 = Individual Interrupt bit is included in (or unmasked from) the Interrupt logical OR Term");
+            Descriptions(0x02).Add("Bit [16]", "EN_BUNDR", @"Interrupt enable for INTB pin.  
+0 = Individual Interrupt bit is not included in (or masked from) the Interrupt logical OR Term 
+1 = Individual Interrupt bit is included in (or unmasked from) the Interrupt logical OR Term");
+            Descriptions(0x02).Add("Bit [15]", "EN_BCGMON", @"Interrupt enable for INTB pin.  
+0 = Individual Interrupt bit is not included in (or masked from) the Interrupt logical OR Term 
+1 = Individual Interrupt bit is included in (or unmasked from) the Interrupt logical OR Term");
+            Descriptions(0x02).Add("Bit [14]", "EN_PINT", @"Interrupt enable for INTB pin.  
+0 = Individual Interrupt bit is not included in (or masked from) the Interrupt logical OR Term 
+1 = Individual Interrupt bit is included in (or unmasked from) the Interrupt logical OR Term");
+            Descriptions(0x02).Add("Bit [13]", "EN_POVF", @"Interrupt enable for INTB pin.  
+0 = Individual Interrupt bit is not included in (or masked from) the Interrupt logical OR Term 
+1 = Individual Interrupt bit is included in (or unmasked from) the Interrupt logical OR Term");
+            Descriptions(0x02).Add("Bit [12]", "EN_PEDGE", @"Interrupt enable for INTB pin.  
+0 = Individual Interrupt bit is not included in (or masked from) the Interrupt logical OR Term 
+1 = Individual Interrupt bit is included in (or unmasked from) the Interrupt logical OR Term");
+            */
+            Descriptions(0x02).Add("Bit [11]", "EN_LONINT", @"Interrupt enable for INTB pin.  
+0 = Individual Interrupt bit is not included in (or masked from) the Interrupt logical OR Term 
+1 = Individual Interrupt bit is included in (or unmasked from) the Interrupt logical OR Term");
+            Descriptions(0x02).Add("Bit [10]", "EN_RRINT", @"Interrupt enable for INTB pin.  
+0 = Individual Interrupt bit is not included in (or masked from) the Interrupt logical OR Term 
+1 = Individual Interrupt bit is included in (or unmasked from) the Interrupt logical OR Term");
+            Descriptions(0x02).Add("Bit [9]", "EN_SAMP", @"Interrupt enable for INTB pin.  
+0 = Individual Interrupt bit is not included in (or masked from) the Interrupt logical OR Term 
+1 = Individual Interrupt bit is included in (or unmasked from) the Interrupt logical OR Term");
+            Descriptions(0x02).Add("Bit [8]", "EN_PLLINT", @"Interrupt enable for INTB pin.  
+0 = Individual Interrupt bit is not included in (or masked from) the Interrupt logical OR Term 
+1 = Individual Interrupt bit is included in (or unmasked from) the Interrupt logical OR Term");
+            Descriptions(0x02).Add("Bit [1:0]", "INTB_TYPE[1:0]", "INTB Port Type (EN_INT Selections)");
+
+            //bit description for EN_INT2
+            Descriptions(0x03).Add("Bit [23]", "EN_EINT2", @"Interrupt enable for INT2B pin.  
+0 = Individual Interrupt bit is not included in (or masked from) the Interrupt logical OR Term 
+1 = Individual Interrupt bit is included in (or unmasked from) the Interrupt logical OR Term");
+            Descriptions(0x03).Add("Bit [22]", "EN_EOVF2", @"Interrupt enable for INT2B pin.  
+0 = Individual Interrupt bit is not included in (or masked from) the Interrupt logical OR Term 
+1 = Individual Interrupt bit is included in (or unmasked from) the Interrupt logical OR Term");
+            Descriptions(0x03).Add("Bit [21]", "EN_FSTINT2", @"Interrupt enable for INT2B pin.  
+0 = Individual Interrupt bit is not included in (or masked from) the Interrupt logical OR Term 
+1 = Individual Interrupt bit is included in (or unmasked from) the Interrupt logical OR Term");
+            Descriptions(0x03).Add("Bit [20]", "EN_DCLOFFINT2", @"Interrupt enable for INT2B pin.  
+0 = Individual Interrupt bit is not included in (or masked from) the Interrupt logical OR Term 
+1 = Individual Interrupt bit is included in (or unmasked from) the Interrupt logical OR Term");
+            /*
+            Descriptions(0x03).Add("Bit [19]", "EN_BINT2", @"Interrupt enable for INT2B pin.  
+0 = Individual Interrupt bit is not included in (or masked from) the Interrupt logical OR Term 
+1 = Individual Interrupt bit is included in (or unmasked from) the Interrupt logical OR Term");
+            Descriptions(0x03).Add("Bit [18]", "EN_BOVF2", @"Interrupt enable for INT2B pin.  
+0 = Individual Interrupt bit is not included in (or masked from) the Interrupt logical OR Term 
+1 = Individual Interrupt bit is included in (or unmasked from) the Interrupt logical OR Term");
+            Descriptions(0x03).Add("Bit [17]", "EN_BOVER2", @"Interrupt enable for INT2B pin.  
+0 = Individual Interrupt bit is not included in (or masked from) the Interrupt logical OR Term 
+1 = Individual Interrupt bit is included in (or unmasked from) the Interrupt logical OR Term");
+            Descriptions(0x03).Add("Bit [16]", "EN_BUNDR2", @"Interrupt enable for INT2B pin.  
+0 = Individual Interrupt bit is not included in (or masked from) the Interrupt logical OR Term 
+1 = Individual Interrupt bit is included in (or unmasked from) the Interrupt logical OR Term");
+            Descriptions(0x03).Add("Bit [15]", "EN_BCGMON2", @"Interrupt enable for INT2B pin.  
+0 = Individual Interrupt bit is not included in (or masked from) the Interrupt logical OR Term 
+1 = Individual Interrupt bit is included in (or unmasked from) the Interrupt logical OR Term");
+            Descriptions(0x03).Add("Bit [14]", "EN_PINT2", @"Interrupt enable for INT2B pin.  
+0 = Individual Interrupt bit is not included in (or masked from) the Interrupt logical OR Term 
+1 = Individual Interrupt bit is included in (or unmasked from) the Interrupt logical OR Term");
+            Descriptions(0x03).Add("Bit [13]", "EN_POVF2", @"Interrupt enable for INT2B pin.  
+0 = Individual Interrupt bit is not included in (or masked from) the Interrupt logical OR Term 
+1 = Individual Interrupt bit is included in (or unmasked from) the Interrupt logical OR Term");
+            Descriptions(0x03).Add("Bit [12]", "EN_PEDGE2", @"Interrupt enable for INT2B pin.  
+0 = Individual Interrupt bit is not included in (or masked from) the Interrupt logical OR Term 
+1 = Individual Interrupt bit is included in (or unmasked from) the Interrupt logical OR Term");
+            */
+            Descriptions(0x03).Add("Bit [11]", "EN_LONINT2", @"Interrupt enable for INT2B pin.  
+0 = Individual Interrupt bit is not included in (or masked from) the Interrupt logical OR Term 
+1 = Individual Interrupt bit is included in (or unmasked from) the Interrupt logical OR Term");
+            Descriptions(0x03).Add("Bit [10]", "EN_RRINT2", @"Interrupt enable for INT2B pin.  
+0 = Individual Interrupt bit is not included in (or masked from) the Interrupt logical OR Term 
+1 = Individual Interrupt bit is included in (or unmasked from) the Interrupt logical OR Term");
+            Descriptions(0x03).Add("Bit [9]", "EN_SAMP2", @"Interrupt enable for INT2B pin.  
+0 = Individual Interrupt bit is not included in (or masked from) the Interrupt logical OR Term 
+1 = Individual Interrupt bit is included in (or unmasked from) the Interrupt logical OR Term");
+            Descriptions(0x03).Add("Bit [8]", "EN_PLLINT2", @"Interrupt enable for INT2B pin.  
+0 = Individual Interrupt bit is not included in (or masked from) the Interrupt logical OR Term 
+1 = Individual Interrupt bit is included in (or unmasked from) the Interrupt logical OR Term");
+            Descriptions(0x03).Add("Bit [1:0]", "INTB2_TYPE[1:0]", "INT2B Port Type (EN_INT Selections)");
+
+            //bit description for MNGR_INT
+            Descriptions(0x04).Add("Bit [23:19]", "EFIT[4:0]", "ECG FIFO Interrupt Threshold (issues EINT based on number of unread FIFO records)");
+            //Descriptions(0x04).Add("Bit [18:16]", "BFIT[2:0]", "BIOZ FIFO Interrupt Threshold (issues BINT based on number of unread FIFO records)");
+            Descriptions(0x04).Add("Bit [6]", "CLR_FAST", "FAST MODE Interrupt Clear Behavior ");
+            Descriptions(0x04).Add("Bit [5:4]", "CLR_RRINT[1:0]", "RTOR R Detect Interrupt (RRINT) Clear Behavior ");
+            //Descriptions(0x04).Add("Bit [3]", "CLR_PEDGE", "PACE Edge Detect Interrupt (PEDGE) Clear Behavior ");
+            Descriptions(0x04).Add("Bit [2]", "CLR_SAMP", "Sample Synchronization Pulse (SAMP) Clear Behavior ");
+            Descriptions(0x04).Add("Bit [1:0]", "SAMP_IT[1:0]", "Sample Synchronization Pulse (SAMP) Frequency ");
+
+            //bit description for MNGR_DYN
+            Descriptions(0x05).Add("Bit [23:22]", "FAST[1:0]", "ECG Channel Fast Recovery Mode Selection (aka ECG High Pass Filter Bypass)");
+            Descriptions(0x05).Add("Bit [21:16]", "FAST_TH[5:0]", "Automatic Fast Recovery Threshold  ");
+            //Descriptions(0x05).Add("Bit [15:8]", "BLOFF_HI_IT[7:0]", "BIOZ AC Lead Off Over-Range Threshold ");
+            //Descriptions(0x05).Add("Bit [7:0]", "BLOFF_LO_IT[7:0]", "BIOZ AC Lead Off Under-Range Threshold ");
+
+            //bit description for SW_RST
+            Descriptions(0x08).Add("Bit [23:0]", "RESET", "Data Required for Execution  = 00_00_00");
+
+            //bit description for SYNCH
+            Descriptions(0x09).Add("Bit [23:0]", "SYNCH", "Data Required for Execution  = 00_00_00");
+
+            //bit description for FIFO_RST
+            Descriptions(0x0A).Add("Bit [23:0]", "FIFO_RST", "Data Required for Execution  = 00_00_00");
+
+            //bit description for INFO
+            Descriptions(0x0F).Add("Bit [19:16]", "REV_ID[3:0]", "Revision ID");
+            //Descriptions(0x0F).Add("Bit [14]", "SAMPLE", "Sample - Experimental Functionality Enable\n0 - Production functionality only\n1 - Experimental functionality");
+            //Descriptions(0x0F).Add("Bit [13:12]", "PART_ID[1:0]", "Part ID\n00 - MAX30004\n01 - MAX30001\n10 - MAX30002\n11 - MAX30003");
+            //Descriptions(0x0F).Add("Bit [11:0]", "SERIAL[11:0]", "Serial Number");
+
+            //bit description for CNFG_GEN
+            Descriptions(0x10).Add("Bit [23:22]", "EN_ULP_LON[1:0]", "Ultra Low Power Lead On Detection Enable");
+            Descriptions(0x10).Add("Bit [21:20]", "FMSTR[1:0]", "Master Clock Frequency");
+            Descriptions(0x10).Add("Bit [19]", "EN_ECG", "ECG Channel Enable");
+            //Descriptions(0x10).Add("Bit [18]", "EN_BIOZ", "BIOZ Channel Enable");
+            //Descriptions(0x10).Add("Bit [17]", "EN_PACE", "PACE Channel Enable");
+            //Descriptions(0x10).Add("Bit [15:14]", "EN_BLOFF[1:0]", "BIOZ Digital Lead Off Detection Enable ");
+            Descriptions(0x10).Add("Bit [13:12]", "EN_DCLOFF", "DC Lead Off Detection Enable");
+            Descriptions(0x10).Add("Bit [11]", "DCLOFF_IPOL", "DC Lead Off Current Polarity (if current sources are enabled/connected)");
+            Descriptions(0x10).Add("Bit [10:8]", "DCLOFF_IMAG[2:0]", "DC Lead Off Current Magnitude Selection");
+            Descriptions(0x10).Add("Bit [7:6]", "DCLOFF_VTH[1:0]", "DC Lead Off Voltage Threshold Selection ");
+            Descriptions(0x10).Add("Bit [5:4]", "EN_RBIAS[1:0]", "Enable and Select Resistive Lead Bias Mode ");
+            Descriptions(0x10).Add("Bit [3:2]", "RBIASV[1:0]", "Resistive Bias Mode Value Selection ");
+            Descriptions(0x10).Add("Bit [1]", "RBIASP", "Enables Resistive Bias on Positive Input");
+            Descriptions(0x10).Add("Bit [0]", "RBIASN", "Enables Resistive Bias on Negative Input");
+
+            //bit description for CNFG_CAL
+            Descriptions(0x12).Add("Bit [22]", "CAL_EN_VCAL", "Calibration Source (VCALP and VCALN) Enable ");
+            Descriptions(0x12).Add("Bit [21]", "CAL_VMODE", "Calibration Source Mode Selection ");
+            Descriptions(0x12).Add("Bit [20]", "CAL_VMAG", "Calibration Source Magnitude Selection (VMAG)");
+            Descriptions(0x12).Add("Bit [14:12]", "CAL_FCAL[2:0]", "Calibration Source Frequency Selection (FCAL)");
+            Descriptions(0x12).Add("Bit [11]", "CAL_FIFTY", "Calibration Source Duty Cycle Mode Selection");
+            Descriptions(0x12).Add("Bit [10:0]", "CAL_THIGH[10:0]", "Calibration Source Time High Selection  ");
+
+            //bit description for CNFG_EMUX
+            Descriptions(0x14).Add("Bit [23]", "EMUX_POL", "ECG Input Polarity Selection");
+            Descriptions(0x14).Add("Bit [21]", "EMUX_OPENP", "Open the ECGP Input Switch (most often used for testing and calibration studies)");
+            Descriptions(0x14).Add("Bit [20]", "EMUX_OPENN", "Open the ECGN Input Switch (most often used for testing and calibration studies)");
+            Descriptions(0x14).Add("Bit [19:18]", "EMUX_CALP_SEL[1:0]", "ECGP Calibration Selection");
+            Descriptions(0x14).Add("Bit [17:16]", "EMUX_CALN_SEL[1:0]", "ECGN Calibration Selection");
+
+            //bit description for CNFG_ECG
+            Descriptions(0x15).Add("Bit [23:22]", "ECG_RATE[1:0]", "ECG Data Rate (also dependent on FMSTR selection, see CNFG_GEN and table below):");
+            Descriptions(0x15).Add("Bit [17:16]", "ECG_GAIN[1:0]", "ECG Channel Gain Setting ");
+            Descriptions(0x15).Add("Bit [14]", "ECG_DHPF", "ECG Channel Digital High Pass Filter Cutoff Frequency");
+            Descriptions(0x15).Add("Bit [13:12]", "ECG_DLPF[1:0]", "ECG Channel Digital Low Pass Filter Cutoff Frequency");
+
+            /*
+            //bit description for CNFG_BMUX
+            Descriptions(0x17).Add("Bit [21]", "BMUX_OPENP", "Open the BIP Input Switch (most often used for testing and calibration studies)");
+            Descriptions(0x17).Add("Bit [20]", "BMUX_OPENN", "Open the BIN Input Switch (most often used for testing and calibration studies)");
+            Descriptions(0x17).Add("Bit [19:18]", "BMUX_CALP_SEL[1:0]", "BIP Calibration Selection (VCAL application to BIP/N inputs intended for use in PACE testing only.)");
+            Descriptions(0x17).Add("Bit [17:16]", "BMUX_CALN_SEL[1:0]", "BIN Calibration Selection (VCAL application to BIP/N inputs intended for use in PACE testing only.)");
+            Descriptions(0x17).Add("Bit [13:12]", "BMUX_CG_MODE[1:0]", "BIOZ Current Generator Mode Selection");
+            Descriptions(0x17).Add("Bit [11]", "BMUX_EN_BIST", "BIOZ Modulated Resistance Built-In-Self-Test (RMOD BIST) Mode Enable");
+            Descriptions(0x17).Add("Bit [10:8]", "BMUX_RNOM[2:0]", "BIOZ RMOD BIST Nominal Resistance Selection");
+            Descriptions(0x17).Add("Bit [6:4]", "BMUX_RMOD[2:0]", "BIOZ RMOD BIST Modulated Resistance Selection (See RMOD BIST Settings Table for details.)");
+            Descriptions(0x17).Add("Bit [1:0]", "BMUX_FBIST[1:0]", "BIOZ RMOD BIST Frequency Selection");
+
+            //bit description for CNFG_BIOZ
+            Descriptions(0x18).Add("Bit [23]", "BIOZ_RATE", "BIOZ Data Rate (also dependent on FMSTR selection, see CNFG_GEN):");
+            Descriptions(0x18).Add("Bit [22:20]", "BIOZ_AHPF[2:0]", "BIOZ/PACE Channel Analog High Pass Filter Cutoff Frequency and Bypass");
+            Descriptions(0x18).Add("Bit [19]", "EXT_RBIAS", "External Resistor Bias Enable");
+            Descriptions(0x18).Add("Bit [17:16]", "BIOZ_GAIN[1:0]", "BIOZ Channel Gain Setting ");
+            Descriptions(0x18).Add("Bit [15:14]", "BIOZ_DHPF[1:0]", "BIOZ Channel Digital High Pass Filter Cutoff Frequency");
+            Descriptions(0x18).Add("Bit [13:12]", "BIOZ_DLPF[1:0]", "BIOZ Channel Digital Low Pass Filter Cutoff Frequency");
+            Descriptions(0x18).Add("Bit [11:8]", "BIOZ_FCGEN[3:0]", "BIOZ Current Generator Modulation Frequency");
+            Descriptions(0x18).Add("Bit [7]", "BIOZ_CGMON", "BIOZ Current Generator Monitor");
+            Descriptions(0x18).Add("Bit [6:4]", "BIOZ_CGMAG[2:0]", "BIOZ Current Generator Magnitude");
+            Descriptions(0x18).Add("Bit [3:0]", "BIOZ_PHOFF[3:0]", "BIOZ Current Generator Modulation Phase Offset ");
+
+            //bit description for CNFG_PACE
+            Descriptions(0x1A).Add("Bit [23]", "PACE_POL", "PACE Input Polarity Selection");
+            Descriptions(0x1A).Add("Bit [19]", "PACE_GN_DIFF_OFF", "PACE Differentiator (Derivative) Mode");
+            Descriptions(0x1A).Add("Bit [18:16]", "PACE_GAIN[2:0]", "PACE Channel Gain Selection");
+            Descriptions(0x1A).Add("Bit [14]", "PACE_AOUT_LBW", "PACE Analog Output Buffer Bandwidth Mode ");
+            Descriptions(0x1A).Add("Bit [13:12]", "PACE_AOUT[1:0]", "PACE Single Ended Analog Output Buffer Signal Monitoring Selection");
+            Descriptions(0x1A).Add("Bit [7:4]", "PACE_DACP[3:0]", "PACE Detector Positive Comparator Threshold");
+            Descriptions(0x1A).Add("Bit [3:0]", "PACE_DACN[3:0]", "PACE Detector Negative Comparator Threshold");
+            */
+
+            //bit description for CNFG_RTOR1
+            Descriptions(0x1D).Add("Bit [23:20]", "RTOR_WNDW[3:0]", "R to R Window Averaging (Window Width = RTOR_WNDW[3:0]*8ms)");
+            Descriptions(0x1D).Add("Bit [19:16]", "RTOR_GAIN[3:0]", "R to R Gain (where Gain = 2^RTOR_GAIN[3:0], plus an auto-scale option)");
+            Descriptions(0x1D).Add("Bit [15]", "EN_RTOR", "ECG RTOR Detection Enable  ");
+            Descriptions(0x1D).Add("Bit [13:12]", "RTOR_PAVG[1:0]", "R to R Peak Averaging Weight Factor");
+            Descriptions(0x1D).Add("Bit [11:8]", "RTOR_PTSF[3:0]", "R to R Peak Threshold Scaling Factor");
+
+            //bit description for CNFG_RTOR2
+            Descriptions(0x1E).Add("Bit [21:16]", "RTOR_HOFF[5:0]", "R to R Minimum Hold Off ");
+            Descriptions(0x1E).Add("Bit [13:12]", "RTOR_RAVG[1:0]", "R to R Interval Averaging Weight Factor");
+            Descriptions(0x1E).Add("Bit [10:8]", "RTOR_RHSF[2:0]", "R to R Interval Hold Off Scaling Factor");
+
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HspGuiSourceV301/HSPGui/DeviceDescriptions/MAX30101Info.cs	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,143 @@
+/*******************************************************************************
+* Copyright (C) 2016 Maxim Integrated Products, Inc., All rights Reserved.
+* 
+* This software is protected by copyright laws of the United States and
+* of foreign countries. This material may also be protected by patent laws
+* and technology transfer regulations of the United States and of foreign
+* countries. This software is furnished under a license agreement and/or a
+* nondisclosure agreement and may only be used or reproduced in accordance
+* with the terms of those agreements. Dissemination of this information to
+* any party or parties not specified in the license agreement and/or
+* nondisclosure agreement is expressly prohibited.
+*
+* The above copyright notice and this permission notice shall be included
+* in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+* OTHER DEALINGS IN THE SOFTWARE.
+*
+* Except as contained in this notice, the name of Maxim Integrated
+* Products, Inc. shall not be used except as stated in the Maxim Integrated
+* Products, Inc. Branding Policy.
+*
+* The mere transfer of this software does not imply any licenses
+* of trade secrets, proprietary technology, copyrights, patents,
+* trademarks, maskwork rights, or any other form of intellectual
+* property whatsoever. Maxim Integrated Products, Inc. retains all
+* ownership rights.
+*******************************************************************************
+*/
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using Maxim.CustomControls;
+using HealthSensorPlatform.DeviceDescriptions;
+using RPCSupport.DeviceSupport;
+
+namespace Maxim.CustomControls
+{
+    public class MAX30101Info : Device
+    {  
+
+        public MAX30101Info() 
+        {
+            deviceDetails = new DeviceDetails();
+            deviceDetails.InitI2c(2, 0xAE);
+
+            Info = new RegisterInfo[] {
+                            new RegisterInfo("Interrupt Status 1",0x00),
+                            new RegisterInfo("Interrupt Status 2",0x01),
+                            new RegisterInfo("Interrupt Enable 1",0x02),
+                            new RegisterInfo("Interrupt Enable 2",0x03),
+                            new RegisterInfo("FIFO Write Pointer",0x04),
+                            new RegisterInfo("Over Flow Counter",0x05),
+                            new RegisterInfo("FIFO Read Pointer",0x06),
+                            new RegisterInfo("FIFO Data Register",0x07), 
+                            new RegisterInfo("FIFO Configuration",0x08),
+                            new RegisterInfo("Mode Configuration",0x09),
+                            new RegisterInfo("SPO2 Configuration",0x0A),
+                            new RegisterInfo("LED1 Pulse Amplitude (Red)",0x0C),
+                            new RegisterInfo("LED2 Pulse Amplitude (IR)",0x0D),
+                            new RegisterInfo("LED3 Pulse Amplitude (Green)",0x0E), 
+                            new RegisterInfo("LED4 Pulse Amplitude (Green)",0x0F),
+                            new RegisterInfo("Proximity Mode LED Pulse Amplitude",0x10), 
+                            new RegisterInfo("Multi-LED Mode Control Register timeslot 1 and 2",0x11),
+                            new RegisterInfo("Multi-LED Mode Control Register timeslot 3 and 4",0x12),
+                            new RegisterInfo("Die Temperature integer",0x1F),
+                            new RegisterInfo("Die Temperature fraction",0x20), 
+                            new RegisterInfo("Die Temperature Config",0x21),
+                            new RegisterInfo("Proximity Interrupt Threshold",0x30), 
+                            new RegisterInfo("Revision ID",0xFE),
+                            new RegisterInfo("Part ID",0xFF)
+                        };
+
+            // register 0x00
+            Descriptions(0x00).Add("Bit 7", "A_FULL", "FIFO Almost Full Flag");
+            Descriptions(0x00).Add("Bit 6", "PPG_RDY", "New FIFO Data Ready");
+            Descriptions(0x00).Add("Bit 5", "ALC_OVF", "Ambient Light Cancellation Overflow");
+            Descriptions(0x00).Add("Bit 4", "PROX_INT", "Proximity Threshold Triggered");
+            Descriptions(0x00).Add("Bit 0", "PWR_RDY", "Power Ready Flag");
+            // register 0x01
+            Descriptions(0x01).Add("Bit 1", "DIE_TEMP_RDY", "Internal Temperature Ready Flag");
+            // register 0x02
+            Descriptions(0x02).Add("Bit 7", "A_FULL_EN", "FIFO Almost Full Flag Enable");
+            Descriptions(0x02).Add("Bit 6", "PPG_RDY_EN", "New FIFO Data Ready Enable");
+            Descriptions(0x02).Add("Bit 5", "ALC_OVF_EN", "Ambient Light Cancellation Overflow Enable");
+            Descriptions(0x02).Add("Bit 4", "PROX_INT_EN", "Proximity Threshold Enable");
+            // register 0x03
+            Descriptions(0x03).Add("Bit 1", "DIE_TEMP_RDY_EN", "Internal Temperature Ready Flag Enable");
+            // register 0x04
+            Descriptions(0x04).Add("Bit [4:0]", "FIFO_WR_PTR[4:0]", "FIFO Write Pointer");
+            // register 0x05
+            Descriptions(0x05).Add("Bit [4:0]", "OVF_COUNTER[4:0]", "FIFO Overflow Counter");
+            // register 0x06
+            Descriptions(0x06).Add("Bit [4:0]", "FIFO_RD_PTR[4:0]", "FIFO Read Pointer");
+            // register 0x07
+            Descriptions(0x07).Add("Bit [7:0]", "FIFO_DATA[7:0]", "FIFO Data Register");
+            // register 0x08
+            Descriptions(0x08).Add("Bit [7:5]", "SMP_AVE[2:0]", "Sample Averaging");
+            Descriptions(0x08).Add("Bit 4", "FIFO_ROLLOVER_EN", "FIFO Rolls on Full");
+            Descriptions(0x08).Add("Bit [3:0]", "FIFO_A_FULL[3:0]", "FIFO Almost Full Value");
+            // register 0x09
+            Descriptions(0x09).Add("Bit 7", "SHDN", "Shutdown Control");
+            Descriptions(0x09).Add("Bit 6", "RESET", "Reset Control");
+            Descriptions(0x09).Add("Bit [2:0]", "MODE[2:0]", "Mode Control");
+            // register 0x0a
+            Descriptions(0x0a).Add("Bit [6:5]", "SPO2_ADC_RGE[1:0]", "SP02 ADC Range Control");
+            Descriptions(0x0a).Add("Bit [4:2]", "SPO2_SR[2:0]", "SP02 Sample Rate Control");
+            Descriptions(0x0a).Add("Bit [1:0]", "LED_PW[1:0]", "LED Pulse Width Control and ADC Resolution");
+            // register 0x0c
+            Descriptions(0x0c).Add("Bit [7:0]", "LED1_PA[7:0]", "LED1 Pulse Amplitude (RED)");
+            Descriptions(0x0d).Add("Bit [7:0]", "LED2_PA[7:0]", "LED2 Pulse Amplitude (IR)");
+            // register 0x0f
+            Descriptions(0x0f).Add("Bit [7:0]", "LED4_PA[7:0]", "LED4 Pulse Amplitude (Green)");
+            // register 0x10
+            Descriptions(0x10).Add("Bit [7:0]", "PILOT_PA[7:0]", "Proximity Mode LED Pulse Amplitude");
+            // register 0x11
+            Descriptions(0x11).Add("Bit [6:4]", "SLOT2[2:0]", "Time slot 2");
+            Descriptions(0x11).Add("Bit [2:0]", "SLOT1[2:0]", "Time slot 1");
+            // register 0x12
+            Descriptions(0x12).Add("Bit [6:4]", "SLOT4[2:0]", "Time slot 4");
+            Descriptions(0x12).Add("Bit [2:0]", "SLOT3[2:0]", "Time slot 3");
+            // register 0x1f
+            Descriptions(0x1f).Add("Bit [7:0]", "TINT[7:0]", "Temperature Integer");
+            // register 0x20
+            Descriptions(0x20).Add("Bit [7:0]", "TFRAC[3:0]", "Temperature Fraction");
+            // register 0x21
+            Descriptions(0x21).Add("Bit 0", "TEMP_EN", "Temperature Enable");
+            // register 0x30
+            Descriptions(0x30).Add("Bit [7:0]", "PROX_INT_THRESH[7:0]", "Proximity Mode Interrupt Threshold");
+            // register 0xfe
+            Descriptions(0xfe).Add("Bit [7:0]", "REV_ID[7:0]", "Revision ID");
+            // register 0xff
+            Descriptions(0xff).Add("Bit [7:0]", "PART_ID[7:0]", "Part ID");
+        }
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HspGuiSourceV301/HSPGui/DeviceDescriptions/MAX30205Info.cs	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,91 @@
+/*******************************************************************************
+* Copyright (C) 2016 Maxim Integrated Products, Inc., All rights Reserved.
+* 
+* This software is protected by copyright laws of the United States and
+* of foreign countries. This material may also be protected by patent laws
+* and technology transfer regulations of the United States and of foreign
+* countries. This software is furnished under a license agreement and/or a
+* nondisclosure agreement and may only be used or reproduced in accordance
+* with the terms of those agreements. Dissemination of this information to
+* any party or parties not specified in the license agreement and/or
+* nondisclosure agreement is expressly prohibited.
+*
+* The above copyright notice and this permission notice shall be included
+* in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+* OTHER DEALINGS IN THE SOFTWARE.
+*
+* Except as contained in this notice, the name of Maxim Integrated
+* Products, Inc. shall not be used except as stated in the Maxim Integrated
+* Products, Inc. Branding Policy.
+*
+* The mere transfer of this software does not imply any licenses
+* of trade secrets, proprietary technology, copyrights, patents,
+* trademarks, maskwork rights, or any other form of intellectual
+* property whatsoever. Maxim Integrated Products, Inc. retains all
+* ownership rights.
+*******************************************************************************
+*/
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using HealthSensorPlatform.DeviceDescriptions;
+using RPCSupport.DeviceSupport;
+
+namespace Maxim.CustomControls
+{
+    public class MAX30205Info : Device
+    {
+
+        public MAX30205Info()
+        {
+            deviceDetails = new DeviceDetails();
+            deviceDetails.InitI2c(1, 0x90);
+
+            initalizeDescription();
+
+        }
+
+        public MAX30205Info(byte i2cAddress)
+        {
+            deviceDetails = new DeviceDetails();
+            deviceDetails.InitI2c(1, i2cAddress);
+
+            initalizeDescription();
+        }
+
+        void initalizeDescription()
+        {
+            Info = new RegisterInfo[] {
+                new RegisterInfo("TEMPERATURE",0x00,2),
+                new RegisterInfo("CONFIGURATION",0x01),
+                new RegisterInfo("T_HYST",0x02,2),
+                new RegisterInfo("T_OS",0x03,2)
+           };
+
+            // register 0x00
+            Descriptions(0x00).Add("Bit [15:0]", "TEMP", "Temperature Data");
+            // register 0x01
+            Descriptions(0x01).Add("Bit 7", "ONE-SHOT", "One-Shot");
+            Descriptions(0x01).Add("Bit 6", "/TIMEOUT", "Timeout");
+            Descriptions(0x01).Add("Bit 5", "DATA_FORMAT", "Data Format");
+            Descriptions(0x01).Add("Bit 4", "FAULT_QUEUE[1]", "Fault Queue");
+            Descriptions(0x01).Add("Bit 3", "FAULT_QUEUE[0]", "Fault Queue");
+            Descriptions(0x01).Add("Bit 2", "OS_POLARITY", "OS Polarity");
+            Descriptions(0x01).Add("Bit 1", "CMPRTR/INTRRPT", "Comparator and Interrupt");
+            Descriptions(0x01).Add("Bit 0", "SHUTDOWN", "Shutdown");
+            // register 0x02
+            Descriptions(0x02).Add("Bit [15:0]", "T_HYST", "Hysteresis Set Point");
+            // register 0x03
+            Descriptions(0x03).Add("Bit [15:0]", "T_OS", "Overtemperature Shutdown Set Point");
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HspGuiSourceV301/HSPGui/DeviceDescriptions/RegisterBitDescriptions.cs	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,22 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace HealthSensorPlatform.DeviceDescriptions
+{
+    public class RegisterBitDescriptions
+    {
+        public List<RegisterBitDescription> list = new List<RegisterBitDescription>();
+        public class RegisterBitDescription
+        {
+            public string bit { get; set; }
+            public string name { get; set; }
+            public string description { get; set; }
+        }
+        public void Add(string _bit, string _name, string _description)
+        {
+            list.Add(new RegisterBitDescription() { bit = _bit, name = _name, description = _description });
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HspGuiSourceV301/HSPGui/DeviceDescriptions/RegisterInfo.cs	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,30 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using HealthSensorPlatform.DeviceDescriptions;
+
+namespace Maxim.CustomControls
+{
+    public class RegisterInfo
+    {
+        public String name;
+        public int address;
+        public int value = 0;
+        public int numberOf;
+        public RegisterBitDescriptions description;
+        public RegisterInfo(String name, int address)
+        {
+            this.name = name;
+            this.address = address;
+            description = new RegisterBitDescriptions();
+        }
+        public RegisterInfo(String name, int address, int numberOf)
+        {
+            this.name = name;
+            this.address = address;
+            this.numberOf = numberOf;
+            description = new RegisterBitDescriptions();
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HspGuiSourceV301/HSPGui/ECGChannel.cs	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,607 @@
+/*******************************************************************************
+* Copyright (C) 2016 Maxim Integrated Products, Inc., All rights Reserved.
+* 
+* This software is protected by copyright laws of the United States and
+* of foreign countries. This material may also be protected by patent laws
+* and technology transfer regulations of the United States and of foreign
+* countries. This software is furnished under a license agreement and/or a
+* nondisclosure agreement and may only be used or reproduced in accordance
+* with the terms of those agreements. Dissemination of this information to
+* any party or parties not specified in the license agreement and/or
+* nondisclosure agreement is expressly prohibited.
+*
+* The above copyright notice and this permission notice shall be included
+* in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+* OTHER DEALINGS IN THE SOFTWARE.
+*
+* Except as contained in this notice, the name of Maxim Integrated
+* Products, Inc. shall not be used except as stated in the Maxim Integrated
+* Products, Inc. Branding Policy.
+*
+* The mere transfer of this software does not imply any licenses
+* of trade secrets, proprietary technology, copyrights, patents,
+* trademarks, maskwork rights, or any other form of intellectual
+* property whatsoever. Maxim Integrated Products, Inc. retains all
+* ownership rights.
+*******************************************************************************
+*/
+
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Data;
+using System.Drawing;
+using System.Linq;
+using System.Text;
+using System.Windows.Forms;
+
+namespace HealthSensorPlatform
+{
+     // Code for ECG Configuration Tab
+    public partial class HspForm 
+    {
+        List<RegisterField> ecgChannelField = new List<RegisterField>(); 
+        List<RegisterField> ecgGlobalField = new List<RegisterField>();
+        List<RegisterField> rToRField = new List<RegisterField>();
+
+        List<RegisterField> channelEnableField = new List<RegisterField>();
+
+        // Needed for dynamic changing of options
+        RegisterField ecgSampleRateField; 
+        RegisterField ecgDlpfField;
+
+        string[][] ecgSampleRateOptions = new string[][] 
+            { 
+                new string[] { "512 sps", "256 sps", "128 sps*" }, 
+                new string[] { "500 sps", "250 sps", "125 sps*" }, 
+                new string[] { "N/A", "N/A", "200 sps*" }, 
+                new string[] { "N/A", "N/A", "199.8 sps*" } 
+            };
+
+        double[][] ecgSampleRates = new double[][]
+            {
+                new double[] {512, 256, 128, 128},
+                new double[] {500, 250, 125, 125},
+                new double[] {200, 200, 200, 200},
+                new double[] {199.8, 199.8, 199.8, 199.8} // using 200, the error is 0.1%
+            };
+
+        string[][][] ecgDlpfOptions;
+
+
+        void initalizeECGConfigFields()
+        {
+			ecgDlpfOptions = new string[4][][];
+			
+			for	(int i = 0; i < 4; i++)
+			{
+				ecgDlpfOptions[i] = new string[4][];
+			}
+			
+			// 32768 Hz
+			ecgDlpfOptions[0][0] = new string[] {"Bypass (00)", "40.96 Hz (01)*", "102.4 Hz (10)", "153.6 Hz (11)"};
+			ecgDlpfOptions[0][1] = new string[] {"Bypass (00)", "40.96 Hz (01)*", "102.4 Hz (10)"};//, "40.96 Hz (11)"};
+			ecgDlpfOptions[0][2] = new string[] {"Bypass (00)", "40.96 Hz (01)*"}; //, "40.96 Hz (10)", "40.96 Hz (11)"};
+			ecgDlpfOptions[0][3] = new string[] {"Bypass (00)", "40.96 Hz (01)*"}; //, "40.96 Hz (10)", "40.96 Hz (11)"};
+			// 32000 Hz
+            ecgDlpfOptions[1][0] = new string[] { "Bypass (00)", "40.00 Hz (01)*", "100.0 Hz (10)", "150.0 Hz (11)"};
+			ecgDlpfOptions[1][1] = new string[] {"Bypass (00)", "40.00 Hz (01)*", "100.0 Hz (10)"}; //, "40.00 Hz (11)"};
+			ecgDlpfOptions[1][2] = new string[] {"Bypass (00)", "40.00 Hz (01)*"}; //, "40.00 Hz (10)", "40.00 Hz (11)"};
+			ecgDlpfOptions[1][3] = new string[] {"Bypass (00)", "40.00 Hz (01)*"}; //, "40.00 Hz (10)", "40.00 Hz (11)"};
+			//32000 Hz
+            ecgDlpfOptions[2][0] = new string[] { "Bypass", "40.00 Hz"}; //, "40.00 Hz", "40.00 Hz" };
+            ecgDlpfOptions[2][1] = new string[] { "Bypass", "40.00 Hz"}; //, "40.00 Hz", "40.00 Hz" };
+            ecgDlpfOptions[2][2] = new string[] { "Bypass", "40.00 Hz"}; //, "40.00 Hz", "40.00 Hz" };
+            ecgDlpfOptions[2][3] = new string[] { "Bypass", "40.00 Hz"}; //, "40.00 Hz", "40.00 Hz" };
+			// 31968 Hz
+            ecgDlpfOptions[3][0] = new string[] { "Bypass (00)", "39.96 Hz (01)" }; //, "39.96 Hz (10)", "39.96 Hz (11)" };
+            ecgDlpfOptions[3][1] = new string[] { "Bypass", "39.96 Hz"}; //, "39.96 Hz", "39.96 Hz" };
+            ecgDlpfOptions[3][2] = new string[] { "Bypass", "39.96 Hz"};//, "39.96 Hz", "39.96 Hz" };
+            ecgDlpfOptions[3][3] = new string[] { "Bypass", "39.96 Hz"};//, "39.96 Hz", "39.96 Hz" };
+			
+            string[] fastOptions = { "Normal*", "Manual Fast Recovery", "Automatic Fast Recovery" };
+            string[] fastThOptions = new string[64];
+            for (int i = 0; i < 64; i++)
+            {
+                fastThOptions[i] = i.ToString() + " * 2048 LSB";
+            }
+            fastThOptions[0x3F] += "*"; // Default option
+
+            string[] channelGainOptions = { "20 V/V*", "40 V/V", "80 V/V", "160 V/V" };
+
+            //string[] sampleRateOptions = { "512 sps", "256 sps", "128 sps*"}; // Assume FMSTR = 32768 Hz
+
+            string[] dlpfOptions = { "Bypass", "40.96 Hz*", "102.4 Hz", "153.6 Hz" };
+            string[] dhpfOptions = { "Bypass", "0.50 Hz*" };
+
+            RegisterField fastField = new RegisterField { Name = "FAST", Register = 5, Index = 22, Width = 2, Descriptions = fastOptions, Label = lblFast, Control = cboFast, Device = max30001};
+            RegisterField fastThField = new RegisterField { Name = "FAST_TH", Register = 5, Index = 16, Width = 6, Descriptions = fastThOptions, Label = lblFastTh, Control = cboFastTh, Device = max30001};
+            ecgChannelField.Add(fastField);
+            ecgChannelField.Add(fastThField);
+
+            RegisterField channelGainField = new RegisterField { Name = "ECG_GAIN", Register = 0x15, Index = 16, Width = 2, Descriptions = channelGainOptions, Label = lblChannelGain, Control = cboChannelGain, Device = max30001};
+            ecgChannelField.Add(channelGainField);
+
+            ecgSampleRateField = new RegisterField { Name = "ECG_RATE", Register = 0x15, Index = 22, Width = 2, Descriptions = ecgSampleRateOptions[0], Label = lblSampleRate, Control = cboSampleRate, Device = max30001};
+            ecgChannelField.Add(ecgSampleRateField);
+
+            ecgDlpfField = new RegisterField { Name = "ECG_DLPF", Register = 0x15, Index = 12, Width = 2, Descriptions = dlpfOptions, Label = lblDlpf,  Control = cboDlpf, Device = max30001};
+            RegisterField dhpfField = new RegisterField { Name = "ECG_DHPF", Register = 0x15, Index = 14, Width = 1, Descriptions = dhpfOptions, Label = lblDhpf, Control = cboDhpf, Device = max30001};
+            ecgChannelField.Add(ecgDlpfField);
+            ecgChannelField.Add(dhpfField);
+        }
+
+        void initalizeECGGlobalControls()
+        {
+            string[] fmstrDescription = { "32768 Hz (00)*", "32000 Hz (01)", "32000 Hz (10)", "31968 Hz (11)" };
+            string[] enECGDescription = { "Disabled*", "Enabled" };
+
+            RegisterField fmstrField = new RegisterField { Name = "FMSTR", Register = 0x10, Index = 20, Width = 2, Descriptions = fmstrDescription, Control = cboMasterClock, Device = max30001};
+            ecgGlobalField.Add(fmstrField);
+
+            //RegisterField enECGField = new RegisterField { Name = "EN_ECG", Register = 0x10, Index = 19, Width = 1, Descriptions = enECGDescription, Label = lblECGChannelEnable };
+            //enECGField.Control = cboECGChannelEnable;
+            //ecgGlobalField.Add(enECGField);
+            RegisterField enECGField = new RegisterField { Name = "EN_ECG", Register = 0x10, Index = 19, Width = 1, Control = chkEnECG, Device = max30001};
+            RegisterField enBioZField = new RegisterField { Name = "EN_BIOZ", Register = 0x10, Index = 18, Width = 1, Control = chkEnBioZ, Device = max30001};
+            RegisterField enPaceField = new RegisterField { Name = "EN_PACE", Register = 0x10, Index = 17, Width = 1, Control = chkEnPace, Device = max30001};
+            RegisterField enRtorField = new RegisterField { Name = "EN_RTOR", Register = 0x1d, Index = 15, Width = 1, Control = chkEnRtor, Device = max30001};
+            channelEnableField.Add(enECGField);
+            channelEnableField.Add(enBioZField);
+            channelEnableField.Add(enPaceField);
+            channelEnableField.Add(enRtorField);
+        }
+
+        void initalizeRToRFields()
+        {
+            string[] wndwOptions = {"6 * 8ms", "8 * 8ms", "10 * 8ms", "12 * 8ms*", "14 * 8ms", "16 * 8ms", "18 * 8ms", "20 * 8ms", 
+                                   "22 * 8ms", "24 * 8ms", "26 * 8ms", "28 * 8ms"};
+            string[] gainOptions = { "1", "2", "4", "8", "16", "32", "64", "128", "256", "512", "1024", "2048", "4096", "8192", "16384", "Auto-Scale*" };
+            string[] enableOptions = { "Disable*", "Enable" };
+            string[] pavgOptions = { "2", "4", "8*", "16" };
+            string[] ptsfOptions = { "1/16", "2/16", "3/16", "4/16*", "5/16", "6/16", "7/16", "8/16",
+                                   "9/16", "10/16", "11/16", "12/16", "13/16", "14/16", "15/16", "16/16"};
+            string[] hoffOptions = new string[64];
+            for(int i = 0; i < 64; i ++)
+            {
+                hoffOptions[i] = i.ToString();
+                if (i == 32)
+                    hoffOptions[i] += "*";
+            }
+            string[] ravgOptions = { "2", "4", "8*", "16" };
+            string[] rhsfOptions = { "0/8", "1/8", "2/8", "3/8", "4/8*", "5/8", "6/8", "7/8" };
+
+            RegisterField wndwField = new RegisterField { Name = "RTOR_WNDW", Register = 0x1d, Index = 20, Width = 4, Descriptions = wndwOptions, Control = cboRRWndw, Label = lblRRWndw, Device = max30001 };
+            RegisterField gainField = new RegisterField { Name = "RTOR_GAIN", Register = 0x1d, Index = 16, Width = 4, Descriptions = gainOptions, Control = cboRRGain, Label = lblRRGain, Device = max30001 };
+            RegisterField enableField = new RegisterField { Name = "EN_RTOR", Register = 0x1d, Index = 15, Width = 1, Descriptions = enableOptions, Control = cboEnRToR, Label = lblEnRToR, Device = max30001 };
+            RegisterField pavgField = new RegisterField { Name = "RTOR_PAVG", Register = 0x1d, Index = 12, Width = 2, Descriptions = pavgOptions, Control = cboRRPavg, Label = lblRRPavg, Device = max30001 };
+            RegisterField ptsfField = new RegisterField { Name = "RTOR_PTSF", Register = 0x1d, Index = 8, Width = 4, Descriptions = ptsfOptions, Control = cboRRPtsf, Label = lblRRPtsf, Device = max30001};
+            RegisterField hoffField = new RegisterField { Name = "RTOR_HOFF", Register = 0x1e, Index = 16, Width = 6, Descriptions = hoffOptions, Control = cboRRHoff, Label = lblRRHoff, Device = max30001 };
+            RegisterField ravgField = new RegisterField { Name = "RTOR_RAVG", Register = 0x1e, Index = 12, Width = 2, Descriptions = ravgOptions, Control = cboRRRavg, Label = lblRRRavg, Device = max30001 };
+            RegisterField rhsfField = new RegisterField { Name = "RTOR_RHSF", Register = 0x1e, Index = 8, Width = 3, Descriptions = rhsfOptions, Control = cboRRRhsf, Label = lblRRRhsf, Device = max30001 };
+
+            rToRField.Add(wndwField);
+            rToRField.Add(gainField);
+            rToRField.Add(enableField);
+            rToRField.Add(pavgField);
+            rToRField.Add(ptsfField);
+            rToRField.Add(hoffField);
+            rToRField.Add(ravgField);
+            rToRField.Add(rhsfField);
+        }
+
+        /// <summary>
+        /// Read register values and update GUI accordingly
+        /// </summary>
+        void ECGChannelUpdateRegisters()
+        {
+            internalUpdate = true;
+            ReadComboBoxesRegisters(ecgChannelField);
+            ReadComboBoxesRegisters(rToRField);
+            internalUpdate = false;
+        }
+
+        /// <summary>
+        /// Read and update all the MAX30001 global GUI settings (enable bits and clock)
+        /// </summary>
+        void ECGGlobalUpdateRegisters()
+        {
+            internalUpdate = true;
+            ReadComboBoxesRegisters(ecgGlobalField);
+            ReadCheckBoxRegisters(channelEnableField);
+            channelEnableMask(chkEnECG);
+            internalUpdate = false;
+            
+            // Update EcgView to maintain consistent state
+            ecgView1.EnableBioZ = chkEnBioZ.Checked;
+            ecgView1.EnableECG = chkEnECG.Checked;
+            ecgView1.EnablePace = chkEnPace.Checked;
+            ecgView1.EnableRToR = chkEnRtor.Checked;
+        }
+
+        /// <summary>
+        /// Mask enable bits for features which depend on EN_ECG = 1 and EN_BIOZ = 1
+        /// </summary>
+        /// <param name="enEcg">Checkbox representing EN_ECG bit</param>
+        void channelEnableMask(MaximStyle.MaximCheckBox enEcg)
+        {
+            if (enEcg.Checked == false)
+            {
+                chkEnRtor.Enabled = false;
+                chkEnPace.Enabled = false;
+            }
+            else
+            {
+                chkEnRtor.Enabled = true;
+                if (max30001Model.PartID == Model.MAX30001Model.Part.MAX30001)
+                    chkEnPace.Enabled = true;
+            }
+
+            /*if (chkEnBioZ.Checked == false)
+            { 
+                chkEnPace.Enabled = false;
+            }
+            else
+            {
+                chkEnPace.Enabled = true;
+            }*/
+
+        }
+
+        void ReadComboBoxesRegisters(List<RegisterField> fields)
+        {
+            int bitValue;
+            MaximStyle.MaximComboBox cbox;
+
+            foreach (RegisterField rf in fields)
+            {
+                cbox = (MaximStyle.MaximComboBox)rf.Control;
+
+                if (rf.AutoUpdate == true)
+                {
+                    //for (int i = 0; i < 3; i++)
+                    //{
+                    //    try
+                    //    {
+                           bitValue = rf.ReadField();
+
+
+                           if (bitValue < cbox.Items.Count && cbox.Items.Count != 0) // Bit setting matches combobox setting
+                           {
+                               cbox.SelectedItem = rf.Descriptions[bitValue];
+                           }
+                           else // Bit setting value outside of combobox item range
+                           {
+                               cbox.Text = "0b" + Convert.ToString(bitValue, 2);
+                           }
+
+                    //    }
+                    //    catch (System.TimeoutException)
+                    //    {
+                    //        if (i == 2)
+                    //            throw;
+                    //    }
+                    //}
+
+                }
+            }
+
+        }
+
+        void ReadComboBoxesRegister(RegisterField rf)
+        {
+            int bitValue;
+            MaximStyle.MaximComboBox cbox;
+
+            cbox = (MaximStyle.MaximComboBox)rf.Control;
+
+            if (rf.AutoUpdate == true)
+            {
+                bitValue = rf.ReadField();
+
+                if (bitValue < cbox.Items.Count && cbox.Items.Count != 0) // Bit setting matches combobox setting
+                {
+                    cbox.SelectedItem = rf.Descriptions[bitValue];
+                }
+                else // Bit setting value outside of combobox item range
+                {
+                    cbox.Text = "0b" + Convert.ToString(bitValue, 2);
+                }
+            }
+        }
+
+        void ReadCheckBoxRegisters(List<RegisterField> fields)
+        {
+            int bitValue;
+            MaximStyle.MaximCheckBox chk;
+
+            foreach (RegisterField rf in fields)
+            {
+                chk = (MaximStyle.MaximCheckBox)rf.Control;
+
+                if (rf.AutoUpdate == true)
+                {
+                    bitValue = rf.ReadField();
+
+                    if (bitValue == 0)
+                        chk.Checked = false;
+                    else
+                        chk.Checked = true;
+                }
+            }
+        }
+
+        /// <summary>
+        /// Get bit value from register 
+        /// </summary>
+        /// <param name="field"></param>
+        /// <returns></returns>
+        /*int BitValue(RegisterField field)
+        {
+            int registerData;
+
+            registerData = max30001.ReadReg((byte)field.Register);
+
+            return (registerData >> field.Index) & ((1 << field.Width) - 1);
+        }*/
+
+        /// <summary>
+        /// Add tool tips to combo boxes and event to write registers
+        /// </summary>
+        /// <param name="list"></param>
+        void initalizeToolTipEvents(List<RegisterField> list)
+        {
+            MaximStyle.MaximComboBox cbox;
+            Label lbl;
+            StringBuilder strBuilder = new StringBuilder();
+
+            foreach (RegisterField field in list)
+            {
+                cbox = (MaximStyle.MaximComboBox)field.Control;
+                lbl = field.Label;
+
+                // Tool Tip String
+                strBuilder.Append("Bit ");
+                strBuilder.Append(field.Name.Replace("\n", String.Empty));
+                strBuilder.Append(" in Register 0x");
+                strBuilder.Append(field.Register.ToString("X2"));
+                toolTip1.SetToolTip(cbox, strBuilder.ToString());
+                if (lbl != null)
+                    toolTip1.SetToolTip(lbl, strBuilder.ToString());
+                strBuilder.Clear();
+
+                // Event to Write Registers
+                if (cbox != cboMasterClock && cbox != cboSampleRate && cbox != cboBioZSampleRate) // cboMasterClock has a special handler to support repopulation of comboboxes
+                    cbox.SelectedIndexChanged += new System.EventHandler(cboECGChannel_SelectedIndexChanged);
+            }
+        }
+
+        /// <summary>
+        /// Write corresponding register of cbox 
+        /// </summary>
+        /// <param name="cbox"></param>
+        void writeComboBox(MaximStyle.MaximComboBox cbox)
+        {
+            List<RegisterField>[] fieldLists = { ecgChannelField, ecgInputMuxField, ecgGlobalField, rToRField, bioZChannelField, bioZInputMuxField, bioZLoadField, paceChannelField};
+            RegisterField field = null;
+            //int val;
+
+            foreach (List<RegisterField> list in fieldLists)
+            {
+                foreach (RegisterField f in list)
+                {
+                    if (f.Control == cbox)
+                    {
+                        field = f;
+                        break;
+                    }
+                }
+
+                if (field != null)
+                    break;
+            }
+
+            field.WriteField((((MaximStyle.MaximComboBox)field.Control).SelectedIndex));
+        }
+
+        void writeCheckBox(MaximStyle.MaximCheckBox chk)
+        {
+            List<RegisterField>[] fieldLists = { channelEnableField };
+            RegisterField field = null;
+            //int val;
+
+            foreach (List<RegisterField> list in fieldLists)
+            {
+                foreach (RegisterField f in list)
+                {
+                    if (f.Control == chk)
+                    {
+                        field = f;
+                        break;
+                    }
+                }
+
+                if (field != null)
+                    break;
+            }
+
+            field.WriteField(((MaximStyle.MaximCheckBox)field.Control).Checked == true ? 1 : 0);
+        }
+
+        /// <summary>
+        /// Event to handle when a new item is selected in the comboboxes for ECG Channel tabs
+        /// </summary>
+        /// <param name="sender"></param>
+        /// <param name="e"></param>
+        private void cboECGChannel_SelectedIndexChanged(object sender, EventArgs e)
+        {
+            MaximStyle.MaximComboBox cbox = (MaximStyle.MaximComboBox)sender;
+
+            if (connected && !internalUpdate)
+                writeComboBox(cbox);
+        }
+
+        /// <summary>
+        /// Update sample rate for ECG View
+        /// </summary>
+        /// <param name="sender"></param>
+        /// <param name="e"></param>
+        private void cboSampleRate_SelectedIndexChanged(object sender, EventArgs e)
+        {
+            MaximStyle.MaximComboBox cbox = (MaximStyle.MaximComboBox)sender;
+
+            if (connected && !internalUpdate)
+                writeComboBox(cbox);
+
+            if (cboMasterClock.SelectedIndex > -1)
+            {
+                // Set sample rate based on clock
+                ecgView1.SampleRateEcg = ecgSampleRates[cboMasterClock.SelectedIndex][cbox.SelectedIndex];
+
+                // Set digital low pass filter
+                cboDlpf.Items.Clear();
+                ecgDlpfField.Descriptions = ecgDlpfOptions[cboMasterClock.SelectedIndex][cboSampleRate.SelectedIndex];
+                ecgDlpfField.Control = cboDlpf; // Trigger updating of descriptions
+
+                //internalUpdate = true;
+                if (connected)
+                    cboDlpf.SelectedIndex = ecgDlpfField.ReadField();
+                //internalUpdate = false;
+                //ReadComboBoxesRegisters(cboDlpf);
+            }
+
+        }
+
+        private void cboChannelGain_SelectedIndexChanged(object sender, EventArgs e)
+        {
+            MaximStyle.MaximComboBox cbox = (MaximStyle.MaximComboBox)sender;
+
+            switch (cbox.SelectedIndex)
+            {
+                case 0:
+                    ecgView1.GainECG = 20;
+                    break;
+                case 1:
+                    ecgView1.GainECG = 40;
+                    break;
+                case 2:
+                    ecgView1.GainECG = 80;
+                    break;
+                case 3:
+                    ecgView1.GainECG = 160;
+                    break;
+            }
+        }
+
+        private void chkChannelEnable_CheckedChanged(object sender, EventArgs e)
+        {
+            MaximStyle.MaximCheckBox chk = (MaximStyle.MaximCheckBox)sender;
+
+            // Write bit
+            if (connected && !internalUpdate)
+            {
+                writeCheckBox(chk);
+
+                // Do not allow user to change masked enable bits
+                channelEnableMask(chkEnECG);
+
+                // Tell ECG View the status
+                if (chk == chkEnECG)
+                {
+                    ecgView1.EnableECG = chk.Checked;
+                }
+                else if (chk == chkEnBioZ)
+                {
+                    ecgView1.EnableBioZ = chk.Checked;
+                }
+                else if (chk == chkEnPace)
+                {
+                    ecgView1.EnablePace = chk.Checked;
+                }
+                else if (chk == chkEnRtor)
+                {
+                    ecgView1.EnableRToR = chk.Checked;
+                }
+
+                // Read all enable bits
+                internalUpdate = true;
+                ReadCheckBoxRegisters(channelEnableField);
+                internalUpdate = false;
+            }
+        }
+
+        private void cboMasterClock_SelectedIndexChanged(object sender, EventArgs e)
+        {
+            MaximStyle.MaximComboBox cbo = (MaximStyle.MaximComboBox)sender;
+            int[] clock = { 32768, 32000, 32000, 31968 };
+
+            if (connected && !internalUpdate)
+                writeComboBox(cbo);
+
+            ecgView1.FrequencyMasterField = cbo.SelectedIndex;
+            //ecgView1.TimeResolution = 1.0/(2*clock[cbo.SelectedIndex]);
+
+            ecgSampleRateField.Descriptions = ecgSampleRateOptions[cbo.SelectedIndex];
+            ecgSampleRateField.Control = cboSampleRate; // Trigger updating of descriptions
+
+            cboBioZSampleRate.Items.Clear();
+            bioZSampleRateField.Descriptions = bioZSampleRateOptions[cbo.SelectedIndex];
+            bioZSampleRateField.Control = cboBioZSampleRate; // Trigger updating of descriptions
+
+            // Trigger update of current selection to new description
+            internalUpdate = true;
+            if (connected)
+            {
+                cboSampleRate.SelectedIndex = ecgSampleRateField.ReadField();
+                cboDlpf.SelectedIndex = ecgDlpfField.ReadField();
+                cboBioZSampleRate.SelectedIndex = bioZSampleRateField.ReadField();
+                cboBioZDigitalLpf.SelectedIndex = bioZDlpfField.ReadField();
+            }
+            internalUpdate = false;
+        }
+
+        private void cboRRWndw_SelectedIndexChanged(object sender, EventArgs e)
+        {
+            MaximStyle.MaximComboBox cbo = (MaximStyle.MaximComboBox)sender;
+            ecgView1.RToRWindowField = cbo.SelectedIndex;
+        }
+
+        private CustomControls.InitArgs.RToRInitStart getRToRArgs()
+        {
+            CustomControls.InitArgs.RToRInitStart initArgs = new CustomControls.InitArgs.RToRInitStart();
+
+            initArgs.Wndw = cboRRWndw.SelectedIndex;
+            initArgs.Gain = cboRRGain.SelectedIndex;
+            initArgs.En_rtor = chkEnRtor.Checked == true ? 1 : 0; 
+            initArgs.Pavg = cboRRPavg.SelectedIndex;
+            initArgs.Ptsf = cboRRPtsf.SelectedIndex;
+            initArgs.Hoff = cboRRHoff.SelectedIndex;
+            initArgs.Ravg = cboRRRavg.SelectedIndex;
+            initArgs.Rhsf = cboRRRhsf.SelectedIndex;
+            initArgs.Clr_rrint = 1; // Default from Jerry's GUI
+
+            return initArgs;
+        }
+
+        private void setRToRArgs(CustomControls.InitArgs.RToRInitStart initArgs)
+        {
+            cboRRWndw.SelectedIndex = initArgs.Wndw;
+            cboRRGain.SelectedIndex = initArgs.Gain;
+            //initArgs.En_rtor = chkEnRtor.Checked == true ? 1 : 0; //cboEnRToR.SelectedIndex;
+            cboRRPavg.SelectedIndex = initArgs.Pavg;
+            cboRRPtsf.SelectedIndex = initArgs.Ptsf;
+            cboRRHoff.SelectedIndex = initArgs.Hoff;
+            cboRRRavg.SelectedIndex = initArgs.Ravg;
+            cboRRRhsf.SelectedIndex = initArgs.Rhsf;
+            //initArgs.Clr_rrint = 2; // Default from Jerry's GUI
+        }
+        
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HspGuiSourceV301/HSPGui/ECGInputMux.cs	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,520 @@
+/*******************************************************************************
+* Copyright (C) 2016 Maxim Integrated Products, Inc., All rights Reserved.
+* 
+* This software is protected by copyright laws of the United States and
+* of foreign countries. This material may also be protected by patent laws
+* and technology transfer regulations of the United States and of foreign
+* countries. This software is furnished under a license agreement and/or a
+* nondisclosure agreement and may only be used or reproduced in accordance
+* with the terms of those agreements. Dissemination of this information to
+* any party or parties not specified in the license agreement and/or
+* nondisclosure agreement is expressly prohibited.
+*
+* The above copyright notice and this permission notice shall be included
+* in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+* OTHER DEALINGS IN THE SOFTWARE.
+*
+* Except as contained in this notice, the name of Maxim Integrated
+* Products, Inc. shall not be used except as stated in the Maxim Integrated
+* Products, Inc. Branding Policy.
+*
+* The mere transfer of this software does not imply any licenses
+* of trade secrets, proprietary technology, copyrights, patents,
+* trademarks, maskwork rights, or any other form of intellectual
+* property whatsoever. Maxim Integrated Products, Inc. retains all
+* ownership rights.
+*******************************************************************************
+*/
+
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Data;
+using System.Drawing;
+using System.Linq;
+using System.Text;
+using System.Windows.Forms;
+using HealthSensorPlatform.CustomControls;
+using HealthSensorPlatform;
+
+
+namespace HealthSensorPlatform
+{
+     // Code for ECG Input Mux Tab
+    public partial class HspForm 
+    {
+        List<RegisterField> ecgInputMuxField = new List<RegisterField>();
+
+        // Needed for dynamic changing of options
+        RegisterField ecgCalFiftyField;
+
+
+        public int[] sw = new int[15];
+
+        void initalizeECGInputMuxFields()
+        {
+            string[] enDcloffOptions = { "Disabled*", "ECG Ch.", "BioZ Ch." };
+            string[] dcloffIpolOptions = { "P: Pull Up, N: Pull Down*", "P: Pull Down, N: Pull Up" };
+            string[] dcloffImagOptions = { "0nA/Disabled*", "5nA", "10nA", "20nA", "50nA", "100nA" };
+            string[] dcloffVthOptions = { "VMID ±300mV*", "VMID ±400mV", "VMID ±450mV", "VMID ±500mV" };
+
+            string[] enUlpLonOptions = { "Disabled", "ECG Ch.", "BioZ Ch." };
+
+            string[] emuxOpenpOptions = { "Connected", "Isolated*" };
+            string[] emuxOpennOptions = { "Connected", "Isolated*" };
+            string[] emuxPolOptions = { "Non-Inverted*", "Inverted" };
+
+            string[] enRbiasOptions = { "Disabled*", "ECG Bias", "BIOZ Bias" };
+            string[] rBiasvOptions = { "50MΩ", "100MΩ*", "200MΩ" };
+            string[] rBiaspOptions = { "Disconnected*", "Connected" };
+            string[] rBiasnOptions = { "Disconnected*", "Connected" };
+
+            string[] calEnVcalOptions = { "Disabled*", "Enabled" };
+            string[] calVmodeOptions = { "Unipolar*", "Bipolar" };
+            string[] calVmagOptions = { "0.25mV*", "0.50mV" };
+            string[] calFcalOptions = { "FMSTR/128 (~256Hz)", "FMSTR/512 (~64Hz)", "FMSTR/2048 (~16Hz)", "FMSTR/8192 (~4Hz)", 
+                                      "FMSTR/2^15 (~1Hz)*", "FMSTR/2^17 (~1/4Hz)",  "FMSTR/2^19 (~1/16Hz)", "FMSTR/2^21 (~1/64Hz)" };
+            string[] calFiftyOptions = { "Time High", "50%*" };
+            string[] calThighOptions = new string[2048/8]; // Assume FMSTR = 32768 Hz
+            for (int i = 0; i < 2048/8; i++)
+            {
+                calThighOptions[i] = (30.52 * i * 8).ToString("F0") + " μs";
+            }
+            calThighOptions[0] += "*"; // Default
+
+            string[] calPSelOptions = { "None*", "VMID", "VCALP", "VCALN" };
+            string[] calNSelOptions = calPSelOptions;
+
+            RegisterField enDcloffField = new RegisterField { Name = "\nEN_DCLOFF", Register = 0x10, Index = 12, Width = 2, Descriptions = enDcloffOptions, Label = lblEnDcloff, Control = cboEnDcloff , Device = max30001};
+            RegisterField dcloffIpolField = new RegisterField { Name = "DCLOFF_IPOL", Register = 0x10, Index = 11, Width = 1, Descriptions = dcloffIpolOptions, Label = lblDcloffIpol, Control = cboDcloffIpol, Device = max30001 };
+            RegisterField dcloffImagField = new RegisterField { Name = "DCLOFF_IMAG", Register = 0x10, Index = 8, Width = 3, Descriptions = dcloffImagOptions, Label = lblDcloffImag, Control = cboDcloffImag, Device = max30001 };
+            RegisterField dcloffVthField = new RegisterField { Name = "DCLOFF_VTH", Register = 0x10, Index = 6, Width = 2, Descriptions = dcloffVthOptions, Label = lblDcloffVth, Control = cboDcloffVth, Device = max30001};
+            ecgInputMuxField.Add(enDcloffField);
+            ecgInputMuxField.Add(dcloffIpolField);
+            ecgInputMuxField.Add(dcloffImagField);
+            ecgInputMuxField.Add(dcloffVthField);
+
+            RegisterField enUlpLonField = new RegisterField { Name = "\nEN_ULP_LON", Register = 0x10, Index = 22, Width = 2, Descriptions = enDcloffOptions, Label = lblEmuxEnUlpLon, Control =  cboEmuxEnUlpLon, Device = max30001};
+            ecgInputMuxField.Add(enUlpLonField);
+
+
+            RegisterField emuxOpenpField = new RegisterField { Name = "EMUX_OPENP", Register = 0x14, Index = 21, Width = 1, Descriptions = emuxOpenpOptions, Label = lblEmuxOpenp, Control = cboEmuxOpenp, Device = max30001 };
+            RegisterField emuxOpennField = new RegisterField { Name = "EMUX_OPENN", Register = 0x14, Index = 20, Width = 1, Descriptions = emuxOpennOptions, Label = lblEmuxOpenn, Control = cboEmuxOpenn, Device = max30001 };
+            RegisterField emuxPolField = new RegisterField { Name = "EMUX_POL", Register = 0x14, Index = 23, Width = 1, Descriptions = emuxPolOptions, Label = lblEmuxPol, Control = cboEmuxPol, Device = max30001 };
+            ecgInputMuxField.Add(emuxOpenpField);
+            ecgInputMuxField.Add(emuxOpennField);
+            ecgInputMuxField.Add(emuxPolField);
+
+            RegisterField enRbiasField = new RegisterField { Name = "\nEN_RBIAS", Register = 0x10, Index = 4, Width = 2, Descriptions = enDcloffOptions, Label = lblEnRbias, Control = cboEnRbias, Device = max30001 };
+            RegisterField rBiasvField = new RegisterField { Name = "RBIASV", Register = 0x10, Index = 2, Width = 2, Descriptions = rBiasvOptions, Label = lblRbiasv, Control = cboRbiasv, Device = max30001 };
+            RegisterField rBiaspField = new RegisterField { Name = "RBIASP", Register = 0x10, Index = 1, Width = 1, Descriptions = rBiaspOptions, Label = lblRbiasp, Control = cboRbiasp, Device = max30001 };
+            RegisterField rBiasnField = new RegisterField { Name = "RBIASN", Register = 0x10, Index = 0, Width = 1, Descriptions = rBiasnOptions, Label = lblRbiasn, Control = cboRbiasn, Device = max30001 };
+            ecgInputMuxField.Add(enRbiasField);
+            ecgInputMuxField.Add(rBiasvField);
+            ecgInputMuxField.Add(rBiaspField);
+            ecgInputMuxField.Add(rBiasnField);
+
+            RegisterField calEnVcalField = new RegisterField { Name = "CAL_EN_VCAL", Register = 0x12, Index = 22, Width = 1, Descriptions = calEnVcalOptions, Label = lblCalEnVcal, Control = cboCalEnVcal, Device = max30001 };
+            RegisterField calVmodeField = new RegisterField { Name = "CAL_VMODE", Register = 0x12, Index = 21, Width = 1, Descriptions = calVmodeOptions, Label = lblCalVMode, Control = cboCalVmode, Device = max30001 };
+            RegisterField calVmagField = new RegisterField { Name = "CAL_VMAG", Register = 0x12, Index = 20, Width = 1, Descriptions = calVmagOptions, Label = lblCalVmag, Control = cboCalVmag, Device = max30001 };
+            RegisterField calFcalField = new RegisterField { Name = "CAL_FCAL", Register = 0x12, Index = 12, Width = 3, Descriptions = calFcalOptions, Label = lblCalFreq, Control = cboCalFcal, Device = max30001 };
+            ecgCalFiftyField = new RegisterField { Name = "CAL_FIFTY", Register = 0x12, Index = 11, Width = 1, Descriptions = calFiftyOptions, Label = lblCalFifty, Control = cboCalFifty, Device = max30001 };
+            RegisterField calThighField = new RegisterField { Name = "CAL_THIGH", Register = 0x12, Index = 3, Width = 8, Descriptions = calThighOptions, Label = lblCalTHigh, Control = cboCalThigh, Device = max30001 };
+            // Decreasing GUI options from 2048 to 256 
+            //RegisterField calThighField = new RegisterField { Name = "CAL_THIGH", Register = 0x12, Index = 0, Width = 10, Descriptions = calThighOptions, Label = lblCalTHigh };
+            ecgInputMuxField.Add(calEnVcalField);
+            ecgInputMuxField.Add(calVmodeField);
+            ecgInputMuxField.Add(calVmagField);
+            ecgInputMuxField.Add(calFcalField);
+            ecgInputMuxField.Add(ecgCalFiftyField);
+            ecgInputMuxField.Add(calThighField);
+
+            RegisterField calPSelField = new RegisterField { Name = "EMUX_CALP_SEL", Register = 0x14, Index = 18, Width = 2, Descriptions = calPSelOptions, Label = lblEmuxCalPSel, Control = cboEmuxCalPSel, Device = max30001 };
+            RegisterField calNSelField = new RegisterField { Name = "EMUX_CALN_SEL", Register = 0x14, Index = 16, Width = 2, Descriptions = calNSelOptions, Label = lblEmuxCalNSel, Control = cboEmuxCalNSel, Device = max30001 };
+            ecgInputMuxField.Add(calPSelField);
+            ecgInputMuxField.Add(calNSelField);
+        }
+
+        void ECGInputMuxUpdateRegisters()
+        {
+            internalUpdate = true;
+            ReadComboBoxesRegisters(ecgInputMuxField);
+            internalUpdate = false;
+        }
+        
+        private void cboCalFifty_SelectedIndexChanged(object sender, EventArgs e)
+        {
+            if (cboCalFifty.SelectedIndex == 1)
+            {
+                cboCalThigh.Enabled = false;
+            }
+            else
+            {
+                cboCalThigh.Enabled = true;
+            }
+        }
+
+        private void cboEnDcloff_SelectedIndexChanged(object sender, EventArgs e)
+        {
+            MaximStyle.MaximComboBox cbo = (MaximStyle.MaximComboBox)sender;
+
+            if (cbo.SelectedIndex == 0)
+            {
+                ecgView1.EnableDCLeadOff = false;
+            }
+            else
+            {
+                ecgView1.EnableDCLeadOff = true;
+                if (cbo.SelectedIndex == 1)
+                    ecgView1.EnableEcgDCLeadOff = true;
+                else
+                    ecgView1.EnableEcgDCLeadOff = false;
+            }
+            
+            redrawEcgMuxImage();
+        }
+
+        private void cboDcloffIpol_SelectedIndexChanged(object sender, EventArgs e)
+        {
+            redrawEcgMuxImage();
+        }
+
+        private void cboEmuxEnUlpLon_SelectedIndexChanged(object sender, EventArgs e)
+        {
+            redrawEcgMuxImage();
+        }
+
+        private void cboEmuxOpenp_SelectedIndexChanged(object sender, EventArgs e)
+        {
+            redrawEcgMuxImage();
+        }
+
+        private void cboEmuxOpenn_SelectedIndexChanged(object sender, EventArgs e)
+        {
+            redrawEcgMuxImage();
+        }
+
+        private void cboEmuxPol_SelectedIndexChanged(object sender, EventArgs e)
+        {
+            redrawEcgMuxImage();
+        }
+
+        private void cboEnRbias_SelectedIndexChanged(object sender, EventArgs e)
+        {
+            redrawEcgMuxImage();
+        }
+
+        private void cboRbiasp_SelectedIndexChanged(object sender, EventArgs e)
+        {
+            redrawEcgMuxImage();
+        }
+
+        private void cboRbiasn_SelectedIndexChanged(object sender, EventArgs e)
+        {
+            redrawEcgMuxImage();
+        }
+
+        private void cboCalEnVcal_SelectedIndexChanged(object sender, EventArgs e)
+        {
+            redrawEcgMuxImage();
+        }
+
+        private void cboEmuxCalPSel_SelectedIndexChanged(object sender, EventArgs e)
+        {
+            redrawEcgMuxImage();
+        }
+
+        private void cboEmuxCalNSel_SelectedIndexChanged(object sender, EventArgs e)
+        {
+            redrawEcgMuxImage();
+        }
+
+        private void redrawEcgMuxImage()
+        {
+            processSwitchState();
+
+            redrawSwitches();
+        }
+
+        private void processSwitchState()
+        {
+            //Logic for panel 1
+            if (cboEnDcloff.SelectedIndex == 1)
+            {
+                if (cboDcloffIpol.SelectedIndex == 0)
+                {
+                    sw[1] = 0;
+                    sw[2] = 1;
+                    sw[10] = 1;
+                    sw[11] = 0;
+                }
+                else
+                {
+                    sw[1] = 1;
+                    sw[2] = 0;
+                    sw[10] = 0;
+                    sw[11] = 1;
+                }
+            }
+            else
+            {
+                sw[1] = 0;
+                sw[2] = 0;
+                sw[10] = 0;
+                sw[11] = 0;
+            }
+            //Logic for panel 2
+            if (cboEmuxEnUlpLon.SelectedIndex == 1)
+            {
+                sw[3] = 1;
+                sw[12] = 1;
+            }
+            else
+            {
+                sw[3] = 0;
+                sw[12] = 0;
+            }
+            //Logic for panel 3
+            if (cboEmuxPol.SelectedIndex == 0)
+            {
+                sw[7] = 0;
+                sw[8] = 0;
+                if (cboEmuxOpenp.SelectedIndex == 0)
+                {
+                    sw[6] = 1;
+                }
+                else
+                {
+                    sw[6] = 0;
+                }
+                if (cboEmuxOpenn.SelectedIndex == 0)
+                {
+                    sw[9] = 1;
+                }
+                else
+                {
+                    sw[9] = 0;
+                }
+            }
+            else
+            {
+                sw[6] = 0;
+                sw[9] = 0;
+                if (cboEmuxOpenp.SelectedIndex == 0)
+                {
+                    sw[7] = 1;
+                }
+                else
+                {
+                    sw[7] = 0;
+                }
+                if (cboEmuxOpenn.SelectedIndex == 0)
+                {
+                    sw[8] = 1;
+                }
+                else
+                {
+                    sw[8] = 0;
+                }
+            }
+            //Logic for panel 4
+            if (cboEnRbias.SelectedIndex == 1)
+            {
+                if (cboRbiasp.SelectedIndex == 1)
+                    sw[4] = 1;
+                else
+                    sw[4] = 0;
+                if (cboRbiasn.SelectedIndex == 1)
+                    sw[13] = 1;
+                else
+                    sw[13] = 0;
+            }
+            else
+            {
+                sw[4] = 0;
+                sw[13] = 0;
+            }
+            //Logic 5
+            if (cboCalEnVcal.SelectedIndex == 1)
+            {
+                if (cboEmuxCalPSel.SelectedIndex == 1 | cboEmuxCalPSel.SelectedIndex == 2 |
+                    cboEmuxCalPSel.SelectedIndex == 3)
+                    sw[5] = 1;
+                else
+                {
+                    sw[5] = 0;
+                }
+                if (cboEmuxCalNSel.SelectedIndex == 1 | cboEmuxCalNSel.SelectedIndex == 2 |
+                    cboEmuxCalNSel.SelectedIndex == 3)
+                    sw[14] = 1;
+                else
+                {
+                    sw[14] = 0;
+                }
+            }
+            else
+            {
+                sw[5] = 0;
+                sw[14] = 0;
+            }
+        }
+
+        private void redrawSwitches()
+        {
+            // Dispose all Images
+            if (picSw1.Image != null)
+                picSw1.Image.Dispose();
+            if (picSw2.Image != null)
+                picSw2.Image.Dispose();
+            if (picSw3.Image != null)
+                picSw3.Image.Dispose();
+            if (picSw4.Image != null)
+                picSw4.Image.Dispose();
+            if (picSw5.Image != null)
+                picSw5.Image.Dispose();
+            if (picSw6.Image != null)
+                picSw6.Image.Dispose();
+            if (picSw7.Image != null)
+                picSw7.Image.Dispose();
+            if (picSw8.Image != null)
+                picSw8.Image.Dispose();
+            if (picSw9.Image != null)
+                picSw9.Image.Dispose();
+            if (picSw10.Image != null)
+                picSw10.Image.Dispose();
+            if (picSw11.Image != null)
+                picSw11.Image.Dispose();
+            if (picSw12.Image != null)
+                picSw12.Image.Dispose();
+            if (picSw13.Image != null)
+                picSw13.Image.Dispose();
+            if (picSw14.Image != null)
+                picSw14.Image.Dispose();
+
+            if (sw[1] == 1)
+                picSw1.Image = Properties.Resources.sw1;
+            else
+                picSw1.Image = null;
+            if (sw[2] == 1)
+                picSw2.Image = Properties.Resources.sw2;
+            else
+                picSw2.Image = null;
+            if (sw[3] == 1)
+                picSw3.Image = Properties.Resources.sw3;
+            else
+                picSw3.Image = null;
+            if (sw[4] == 1)
+                picSw4.Image = Properties.Resources.sw4;
+            else
+                picSw4.Image = null;
+            if (sw[5] == 1)
+                picSw5.Image = Properties.Resources.sw5;
+            else
+                picSw5.Image = null;
+            if (sw[6] == 1)
+                picSw6.Image = Properties.Resources.sw6;
+            else
+                picSw6.Image = null;
+            if (sw[7] == 1)
+                picSw7.Image = Properties.Resources.sw7;
+            else
+                picSw7.Image = null;
+            if (sw[8] == 1)
+                picSw8.Image = Properties.Resources.sw8;
+            else
+                picSw8.Image = null;
+            if (sw[9] == 1)
+                picSw9.Image = Properties.Resources.sw9;
+            else
+                picSw9.Image = null;
+            if (sw[10] == 1)
+                picSw10.Image = Properties.Resources.sw10;
+            else
+                picSw10.Image = null;
+            if (sw[11] == 1)
+                picSw11.Image = Properties.Resources.sw11;
+            else
+                picSw11.Image = null;
+            if (sw[12] == 1)
+                picSw12.Image = Properties.Resources.sw12;
+            else
+                picSw12.Image = null;
+            if (sw[13] == 1)
+                picSw13.Image = Properties.Resources.sw13;
+            else
+                picSw13.Image = null;
+            if (sw[14] == 1)
+                picSw14.Image = Properties.Resources.sw14;
+            else
+                picSw14.Image = null;
+        }
+
+
+        private InitArgs.EcgInitStart getEcgArgs()
+        {
+            InitArgs.EcgInitStart initArgs = new CustomControls.InitArgs.EcgInitStart();
+
+            initArgs.Openp = cboEmuxOpenp.SelectedIndex;
+            initArgs.Openn = cboEmuxOpenn.SelectedIndex;
+            initArgs.Pol = cboEmuxPol.SelectedIndex;
+            initArgs.Calp_sel = cboEmuxCalPSel.SelectedIndex;
+            initArgs.Caln_sel = cboEmuxCalNSel.SelectedIndex;
+            //initArgs.En_ecg = cboECGChannelEnable.SelectedIndex;
+            initArgs.En_ecg = chkEnECG.Checked ? 1 : 0;
+            initArgs.E_fit = 15;//0x1F; // TODO
+            initArgs.Rate = cboSampleRate.SelectedIndex;
+            initArgs.Gain = cboChannelGain.SelectedIndex;
+            initArgs.Dhpf = cboDhpf.SelectedIndex;
+            initArgs.Dlpf = cboDlpf.SelectedIndex;
+
+            return initArgs;
+        }
+
+        private void setEcgArgs(InitArgs.EcgInitStart initArgs)
+        {
+            cboEmuxOpenp.SelectedIndex = initArgs.Openp;
+            cboEmuxOpenn.SelectedIndex = initArgs.Openn;
+            cboEmuxPol.SelectedIndex = initArgs.Pol;
+            cboEmuxCalPSel.SelectedIndex = initArgs.Calp_sel;
+            cboEmuxCalNSel.SelectedIndex = initArgs.Caln_sel;
+            //initArgs.En_ecg = cboECGChannelEnable.SelectedIndex;
+            //initArgs.En_ecg = chkEnECG.Checked == true ? 1 : 0;
+            //initArgs.E_fit = 15;//0x1F; 
+            cboSampleRate.SelectedIndex = initArgs.Rate;
+            cboChannelGain.SelectedIndex = initArgs.Gain;
+            cboDhpf.SelectedIndex = initArgs.Dhpf;
+            cboDlpf.SelectedIndex = initArgs.Dlpf;
+        }
+
+        private InitArgs.FMSTRInitStart getFMSTRArgs()
+        {
+            InitArgs.FMSTRInitStart initArgs = new InitArgs.FMSTRInitStart();
+
+            initArgs.En_rbias = cboEnRbias.SelectedIndex;
+            initArgs.Rbiasv = cboRbiasv.SelectedIndex;
+            initArgs.Rbiasp = cboRbiasp.SelectedIndex;
+            initArgs.Rbiasn = cboRbiasn.SelectedIndex;
+            initArgs.Fmstr = cboMasterClock.SelectedIndex;
+
+            return initArgs;
+        }
+
+        private void setFMSTRArgs(InitArgs.FMSTRInitStart initArgs)
+        {
+            cboEnRbias.SelectedIndex = initArgs.En_rbias;
+            cboRbiasv.SelectedIndex = initArgs.Rbiasv;
+            cboRbiasp.SelectedIndex = initArgs.Rbiasp;
+            cboRbiasn.SelectedIndex = initArgs.Rbiasn;
+            cboMasterClock.SelectedIndex = initArgs.Fmstr;
+        }
+
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HspGuiSourceV301/HSPGui/FirFilter.cs	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,159 @@
+/*******************************************************************************
+* Copyright (C) 2016 Maxim Integrated Products, Inc., All rights Reserved.
+* 
+* This software is protected by copyright laws of the United States and
+* of foreign countries. This material may also be protected by patent laws
+* and technology transfer regulations of the United States and of foreign
+* countries. This software is furnished under a license agreement and/or a
+* nondisclosure agreement and may only be used or reproduced in accordance
+* with the terms of those agreements. Dissemination of this information to
+* any party or parties not specified in the license agreement and/or
+* nondisclosure agreement is expressly prohibited.
+*
+* The above copyright notice and this permission notice shall be included
+* in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+* OTHER DEALINGS IN THE SOFTWARE.
+*
+* Except as contained in this notice, the name of Maxim Integrated
+* Products, Inc. shall not be used except as stated in the Maxim Integrated
+* Products, Inc. Branding Policy.
+*
+* The mere transfer of this software does not imply any licenses
+* of trade secrets, proprietary technology, copyrights, patents,
+* trademarks, maskwork rights, or any other form of intellectual
+* property whatsoever. Maxim Integrated Products, Inc. retains all
+* ownership rights.
+*******************************************************************************
+*/
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace HealthSensorPlatform
+{
+    /// <summary>
+    /// This performs a FIR filter calculation on data provided to this class
+    /// </summary>
+    public class FirFilter
+    {
+        /// <summary>
+        /// FIR filter coefficents
+        /// </summary>
+        public double[] Coefficents;
+        /// <summary>
+        /// Internal FIFO of previous data values
+        /// </summary>
+        Queue<int> buffer;
+
+        public FirFilter()
+        {
+            double[] filterCoefficnets = new double[] {
+                0.024885237	,
+            -0.007653574	,
+            -0.007907673	,
+            -0.008893603	,
+            -0.010461763	,
+            -0.012494771	,
+            -0.014895244	,
+            -0.01757762	,
+            -0.020462913	,
+            -0.023475562	,
+            -0.026541814	,
+            -0.029589204	,
+            -0.032546822	,
+            -0.035346114	,
+            -0.037922039	,
+            -0.040214407	,
+            -0.042169293	,
+            -0.043740402	,
+            -0.044890306	,
+            -0.045591484	,
+            0.954172901	,
+            -0.045591484	,
+            -0.044890306	,
+            -0.043740402	,
+            -0.042169293	,
+            -0.040214407	,
+            -0.037922039	,
+            -0.035346114	,
+            -0.032546822	,
+            -0.029589204	,
+            -0.026541814	,
+            -0.023475562	,
+            -0.020462913	,
+            -0.01757762	,
+            -0.014895244	,
+            -0.012494771	,
+            -0.010461763	,
+            -0.008893603	,
+            -0.007907673	,
+            -0.007653574	,
+            0.024885237
+            };
+
+            Coefficents = filterCoefficnets;
+
+            buffer = new Queue<int>(Coefficents.Length);
+
+            Reset();
+        }
+
+        /// <summary>
+        /// FirFilter constructor. FIR data points initalized to zero.
+        /// </summary>
+        /// <param name="coefficents">FIR filter coefficents</param>
+        public FirFilter(double[] coefficents)
+        {
+            Coefficents = coefficents;
+
+            buffer = new Queue<int>(Coefficents.Length);
+
+            Reset();
+        }
+
+        /// <summary>
+        /// Reset filter internal state
+        /// </summary>
+        public void Reset()
+        {
+            buffer.Clear();
+
+            // initialize values to zero
+            for (int i = 0; i < Coefficents.Length; i++)
+            {
+                buffer.Enqueue(0);
+            }
+        }
+
+        /// <summary>
+        /// Compute the filtered value
+        /// </summary>
+        /// <param name="val">integer value to add to buffer for computation</param>
+        /// <returns>filter output</returns>
+        public double Compute(int val)
+        {
+            double result = 0;
+            int[] values;
+
+            buffer.Dequeue();
+            buffer.Enqueue(val);
+            values = buffer.ToArray();
+
+            for (int i = 0; i < values.Length; i++)
+            {
+                result += Coefficents[i] * values[values.Length - i - 1]; 
+            }
+
+            return result;
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HspGuiSourceV301/HSPGui/Form1.Designer.cs	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,6194 @@
+namespace HealthSensorPlatform
+{
+    partial class HspForm
+    {
+        /// <summary>
+        /// Required designer variable.
+        /// </summary>
+        private System.ComponentModel.IContainer components = null;
+
+        /// <summary>
+        /// Clean up any resources being used.
+        /// </summary>
+        /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
+        protected override void Dispose(bool disposing)
+        {
+            if (disposing && (components != null))
+            {
+                components.Dispose();
+            }
+            base.Dispose(disposing);
+        }
+
+        #region Windows Form Designer generated code
+
+        /// <summary>
+        /// Required method for Designer support - do not modify
+        /// the contents of this method with the code editor.
+        /// </summary>
+        private void InitializeComponent()
+        {
+            this.components = new System.ComponentModel.Container();
+            System.Windows.Forms.DataVisualization.Charting.ChartArea chartArea1 = new System.Windows.Forms.DataVisualization.Charting.ChartArea();
+            System.Windows.Forms.DataVisualization.Charting.ChartArea chartArea2 = new System.Windows.Forms.DataVisualization.Charting.ChartArea();
+            System.Windows.Forms.DataVisualization.Charting.ChartArea chartArea3 = new System.Windows.Forms.DataVisualization.Charting.ChartArea();
+            System.Windows.Forms.DataVisualization.Charting.Series series1 = new System.Windows.Forms.DataVisualization.Charting.Series();
+            System.Windows.Forms.DataVisualization.Charting.Series series2 = new System.Windows.Forms.DataVisualization.Charting.Series();
+            System.Windows.Forms.DataVisualization.Charting.Series series3 = new System.Windows.Forms.DataVisualization.Charting.Series();
+            System.Windows.Forms.DataVisualization.Charting.Title title1 = new System.Windows.Forms.DataVisualization.Charting.Title();
+            System.Windows.Forms.DataVisualization.Charting.ChartArea chartArea4 = new System.Windows.Forms.DataVisualization.Charting.ChartArea();
+            System.Windows.Forms.DataVisualization.Charting.ChartArea chartArea5 = new System.Windows.Forms.DataVisualization.Charting.ChartArea();
+            System.Windows.Forms.DataVisualization.Charting.ChartArea chartArea6 = new System.Windows.Forms.DataVisualization.Charting.ChartArea();
+            System.Windows.Forms.DataVisualization.Charting.Series series4 = new System.Windows.Forms.DataVisualization.Charting.Series();
+            System.Windows.Forms.DataVisualization.Charting.Series series5 = new System.Windows.Forms.DataVisualization.Charting.Series();
+            System.Windows.Forms.DataVisualization.Charting.Series series6 = new System.Windows.Forms.DataVisualization.Charting.Series();
+            System.Windows.Forms.DataVisualization.Charting.Title title2 = new System.Windows.Forms.DataVisualization.Charting.Title();
+            System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(HspForm));
+            this.txt_Status = new System.Windows.Forms.TextBox();
+            this.label1 = new System.Windows.Forms.Label();
+            this.btn_Clear = new MaximStyle.MaximButton();
+            this.ss_Status = new MaximStyle.MaximStatusStrip();
+            this.toolStripMenuItem1 = new System.Windows.Forms.ToolStripMenuItem();
+            this.exitToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+            this.toolStripMenuItem2 = new System.Windows.Forms.ToolStripMenuItem();
+            this.connectionToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+            this.disconnectToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+            this.optionsToolStripMenuItem1 = new System.Windows.Forms.ToolStripMenuItem();
+            this.registerNamesToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+            this.bioZMilliohmScaleToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+            this.toolStripSeparator1 = new System.Windows.Forms.ToolStripSeparator();
+            this.loadRegisterSettingsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+            this.saveRegisterSettingsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+            this.toolStripSeparator2 = new System.Windows.Forms.ToolStripSeparator();
+            this.loadAllRegisterSettingsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+            this.registerExportToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+            this.toolStripSeparator3 = new System.Windows.Forms.ToolStripSeparator();
+            this.showAdvancedTabToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+            this.loggingToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+            this.eCGBioZFileLogToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+            this.eCGFileLogToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+            this.rToRFileLogToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+            this.paceFileLogToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+            this.bioZFileLogToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+            this.toolStripSeparator5 = new System.Windows.Forms.ToolStripSeparator();
+            this.opticalAccelerometerFileLogToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+            this.helpToolStripMenuItem1 = new System.Windows.Forms.ToolStripMenuItem();
+            this.onlineDocumentationToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+            this.aboutToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+            this.fileToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+            this.tsm_exit = new System.Windows.Forms.ToolStripMenuItem();
+            this.deviceToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+            this.test1ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+            this.optionsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+            this.test2ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+            this.helpToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+            this.technicalDocsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+            this.tsm_EVKitDatasheet = new System.Windows.Forms.ToolStripMenuItem();
+            this.tsm_ICDatasheet = new System.Windows.Forms.ToolStripMenuItem();
+            this.tsm_about = new System.Windows.Forms.ToolStripMenuItem();
+            this.maximGroupBox1 = new MaximStyle.MaximGroupBox();
+            this.maximTabControl1 = new MaximStyle.MaximTabControl();
+            this.tpBlockDiagram = new System.Windows.Forms.TabPage();
+            this.tlbQuickStart = new System.Windows.Forms.TableLayoutPanel();
+            this.linkLabelQuickRespiration = new System.Windows.Forms.LinkLabel();
+            this.label40 = new System.Windows.Forms.Label();
+            this.linkLabelQuickOpticalSpO2 = new System.Windows.Forms.LinkLabel();
+            this.linkLabelQuickTemperature = new System.Windows.Forms.LinkLabel();
+            this.linkLabelQuickBioimpedance = new System.Windows.Forms.LinkLabel();
+            this.linkLabelQuickEcg = new System.Windows.Forms.LinkLabel();
+            this.label41 = new System.Windows.Forms.Label();
+            this.pnlBlockDiagram = new System.Windows.Forms.Panel();
+            this.label29 = new System.Windows.Forms.Label();
+            this.linkOpticalSensor = new System.Windows.Forms.LinkLabel();
+            this.linkBioZLoad = new System.Windows.Forms.LinkLabel();
+            this.linkTempSensor = new System.Windows.Forms.LinkLabel();
+            this.linkBioZMux = new System.Windows.Forms.LinkLabel();
+            this.linkEcgMux = new System.Windows.Forms.LinkLabel();
+            this.linkBioZChannel = new System.Windows.Forms.LinkLabel();
+            this.linkEcgChannel = new System.Windows.Forms.LinkLabel();
+            this.linkPaceChannel = new System.Windows.Forms.LinkLabel();
+            this.picBlockDiagram = new System.Windows.Forms.PictureBox();
+            this.tpOpticalSensor = new System.Windows.Forms.TabPage();
+            this.opticalView1 = new HealthSensorPlatform.CustomControls.OpticalView();
+            this.tpTemperature = new System.Windows.Forms.TabPage();
+            this.temperatureView1 = new HealthSensorPlatform.CustomControls.TemperatureView();
+            this.tpMAX30001EcgChannel = new System.Windows.Forms.TabPage();
+            this.cboEnRToR = new MaximStyle.MaximComboBox();
+            this.lblEnRToR = new System.Windows.Forms.Label();
+            this.flowLayoutPanel1 = new System.Windows.Forms.FlowLayoutPanel();
+            this.panel1 = new System.Windows.Forms.Panel();
+            this.pnlEcgChannel = new System.Windows.Forms.Panel();
+            this.linkLabel1 = new System.Windows.Forms.LinkLabel();
+            this.label30 = new System.Windows.Forms.Label();
+            this.label28 = new System.Windows.Forms.Label();
+            this.lblFast = new System.Windows.Forms.Label();
+            this.lblChannelGain = new System.Windows.Forms.Label();
+            this.cboFastTh = new MaximStyle.MaximComboBox();
+            this.lblSampleRate = new System.Windows.Forms.Label();
+            this.lblFastTh = new System.Windows.Forms.Label();
+            this.lblDlpf = new System.Windows.Forms.Label();
+            this.lblDhpf = new System.Windows.Forms.Label();
+            this.cboDhpf = new MaximStyle.MaximComboBox();
+            this.cboFast = new MaximStyle.MaximComboBox();
+            this.cboDlpf = new MaximStyle.MaximComboBox();
+            this.cboChannelGain = new MaximStyle.MaximComboBox();
+            this.cboSampleRate = new MaximStyle.MaximComboBox();
+            this.picEcgChannel = new System.Windows.Forms.PictureBox();
+            this.grpRToR = new MaximStyle.MaximGroupBox();
+            this.cboRRRavg = new MaximStyle.MaximComboBox();
+            this.lblRRRavg = new System.Windows.Forms.Label();
+            this.cboRRHoff = new MaximStyle.MaximComboBox();
+            this.lblRRHoff = new System.Windows.Forms.Label();
+            this.cboRRRhsf = new MaximStyle.MaximComboBox();
+            this.lblRRRhsf = new System.Windows.Forms.Label();
+            this.cboRRPtsf = new MaximStyle.MaximComboBox();
+            this.lblRRPtsf = new System.Windows.Forms.Label();
+            this.cboRRPavg = new MaximStyle.MaximComboBox();
+            this.lblRRPavg = new System.Windows.Forms.Label();
+            this.cboRRGain = new MaximStyle.MaximComboBox();
+            this.lblRRGain = new System.Windows.Forms.Label();
+            this.cboRRWndw = new MaximStyle.MaximComboBox();
+            this.lblRRWndw = new System.Windows.Forms.Label();
+            this.tpMAX30001InputMux = new System.Windows.Forms.TabPage();
+            this.pnlEcgMux = new System.Windows.Forms.Panel();
+            this.label26 = new System.Windows.Forms.Label();
+            this.lblEmuxEnUlpLon = new System.Windows.Forms.Label();
+            this.label32 = new System.Windows.Forms.Label();
+            this.cboCalEnVcal = new MaximStyle.MaximComboBox();
+            this.cboCalVmode = new MaximStyle.MaximComboBox();
+            this.cboEmuxEnUlpLon = new MaximStyle.MaximComboBox();
+            this.cboDcloffImag = new MaximStyle.MaximComboBox();
+            this.cboEmuxPol = new MaximStyle.MaximComboBox();
+            this.cboEmuxCalNSel = new MaximStyle.MaximComboBox();
+            this.lblEmuxPol = new System.Windows.Forms.Label();
+            this.lblEmuxCalNSel = new System.Windows.Forms.Label();
+            this.lblCalEnVcal = new System.Windows.Forms.Label();
+            this.cboEmuxCalPSel = new MaximStyle.MaximComboBox();
+            this.lblCalVMode = new System.Windows.Forms.Label();
+            this.lblEmuxCalPSel = new System.Windows.Forms.Label();
+            this.lblDcloffImag = new System.Windows.Forms.Label();
+            this.cboCalVmag = new MaximStyle.MaximComboBox();
+            this.cboRbiasn = new MaximStyle.MaximComboBox();
+            this.cboCalFifty = new MaximStyle.MaximComboBox();
+            this.lblRbiasn = new System.Windows.Forms.Label();
+            this.cboCalThigh = new MaximStyle.MaximComboBox();
+            this.cboRbiasp = new MaximStyle.MaximComboBox();
+            this.cboCalFcal = new MaximStyle.MaximComboBox();
+            this.lblRbiasp = new System.Windows.Forms.Label();
+            this.lblCalFifty = new System.Windows.Forms.Label();
+            this.cboRbiasv = new MaximStyle.MaximComboBox();
+            this.lblCalTHigh = new System.Windows.Forms.Label();
+            this.lblRbiasv = new System.Windows.Forms.Label();
+            this.lblCalFreq = new System.Windows.Forms.Label();
+            this.cboEnRbias = new MaximStyle.MaximComboBox();
+            this.lblCalVmag = new System.Windows.Forms.Label();
+            this.lblEnRbias = new System.Windows.Forms.Label();
+            this.lblEmuxOpenp = new System.Windows.Forms.Label();
+            this.lblDcloffVth = new System.Windows.Forms.Label();
+            this.lblEmuxOpenn = new System.Windows.Forms.Label();
+            this.cboDcloffVth = new MaximStyle.MaximComboBox();
+            this.cboEmuxOpenp = new MaximStyle.MaximComboBox();
+            this.cboDcloffIpol = new MaximStyle.MaximComboBox();
+            this.cboEmuxOpenn = new MaximStyle.MaximComboBox();
+            this.lblDcloffIpol = new System.Windows.Forms.Label();
+            this.lblEnDcloff = new System.Windows.Forms.Label();
+            this.cboEnDcloff = new MaximStyle.MaximComboBox();
+            this.picECGLeadConfig = new System.Windows.Forms.PictureBox();
+            this.picSw1 = new System.Windows.Forms.PictureBox();
+            this.picSw2 = new System.Windows.Forms.PictureBox();
+            this.pictureBox1 = new System.Windows.Forms.PictureBox();
+            this.picSw3 = new System.Windows.Forms.PictureBox();
+            this.picSw4 = new System.Windows.Forms.PictureBox();
+            this.picSw5 = new System.Windows.Forms.PictureBox();
+            this.picSw6 = new System.Windows.Forms.PictureBox();
+            this.picSw7 = new System.Windows.Forms.PictureBox();
+            this.picSw8 = new System.Windows.Forms.PictureBox();
+            this.picSw9 = new System.Windows.Forms.PictureBox();
+            this.picSw10 = new System.Windows.Forms.PictureBox();
+            this.picSw11 = new System.Windows.Forms.PictureBox();
+            this.picSw12 = new System.Windows.Forms.PictureBox();
+            this.picSw13 = new System.Windows.Forms.PictureBox();
+            this.picSw14 = new System.Windows.Forms.PictureBox();
+            this.pnlMAX30001Global = new System.Windows.Forms.Panel();
+            this.grpChannelPlotEnable = new MaximStyle.MaximGroupBox();
+            this.chkEnRtor = new MaximStyle.MaximCheckBox();
+            this.chkEnECG = new MaximStyle.MaximCheckBox();
+            this.chkEnBioZ = new MaximStyle.MaximCheckBox();
+            this.chkEnPace = new MaximStyle.MaximCheckBox();
+            this.maximGroupBox8 = new MaximStyle.MaximGroupBox();
+            this.maximButton5 = new MaximStyle.MaximButton();
+            this.maximComboBox9 = new MaximStyle.MaximComboBox();
+            this.grpGlobalControls = new MaximStyle.MaximGroupBox();
+            this.label39 = new System.Windows.Forms.Label();
+            this.cboMasterClock = new MaximStyle.MaximComboBox();
+            this.label31 = new System.Windows.Forms.Label();
+            this.tpBioZChannel = new System.Windows.Forms.TabPage();
+            this.pnlBioZChannel = new System.Windows.Forms.Panel();
+            this.label34 = new System.Windows.Forms.Label();
+            this.cboBioZAnalogHpf = new MaximStyle.MaximComboBox();
+            this.cboBioZExternalResistorBiasEnable = new MaximStyle.MaximComboBox();
+            this.cboBioZChannelGain = new MaximStyle.MaximComboBox();
+            this.label25 = new System.Windows.Forms.Label();
+            this.cboBioZSampleRate = new MaximStyle.MaximComboBox();
+            this.cboBioZCurrentGeneratorFrequency = new MaximStyle.MaximComboBox();
+            this.cboBioZDigitalLpf = new MaximStyle.MaximComboBox();
+            this.lblBioZCurrentGeneratorFrequency = new System.Windows.Forms.Label();
+            this.cboBioZDigitalHpf = new MaximStyle.MaximComboBox();
+            this.label21 = new System.Windows.Forms.Label();
+            this.cboBioZACLeadOffOverRangeThreshold = new MaximStyle.MaximComboBox();
+            this.cboBioZCurrentGeneratorMagnitude = new MaximStyle.MaximComboBox();
+            this.cboBioZACLeadOffUnderRangeThreshold = new MaximStyle.MaximComboBox();
+            this.cboBioZModulationPhaseOffset = new MaximStyle.MaximComboBox();
+            this.cboBioZDigitalLeadOffDetectionEnable = new MaximStyle.MaximComboBox();
+            this.lblBioZExternalResistorBiasEnable = new System.Windows.Forms.Label();
+            this.cboBioZCurrentGeneratorMonitor = new MaximStyle.MaximComboBox();
+            this.lblBioZCurrentGeneratorMonitor = new System.Windows.Forms.Label();
+            this.cboBioZCurrentGeneratorMode = new MaximStyle.MaximComboBox();
+            this.lblBioZCurrentGeneratorMode = new System.Windows.Forms.Label();
+            this.lblBioZAnalogHpf = new System.Windows.Forms.Label();
+            this.lblBioZModulationPhaseOffset = new System.Windows.Forms.Label();
+            this.linkLabel2 = new System.Windows.Forms.LinkLabel();
+            this.lblBioZCurrentGeneratorMagnitude = new System.Windows.Forms.Label();
+            this.lblBioZChannelGain = new System.Windows.Forms.Label();
+            this.lblBioZACLeadOffUnderRangeThreshold = new System.Windows.Forms.Label();
+            this.lblBioZSampleRate = new System.Windows.Forms.Label();
+            this.lblBioZACLeadOffOverRangeThreshold = new System.Windows.Forms.Label();
+            this.lblBioZDigitalLpf = new System.Windows.Forms.Label();
+            this.lblBioZDigitalLeadOffDetectionEnable = new System.Windows.Forms.Label();
+            this.lblBioZDigitalHpf = new System.Windows.Forms.Label();
+            this.picBioZChannel = new System.Windows.Forms.PictureBox();
+            this.tpMAX30001BioZInputMux = new System.Windows.Forms.TabPage();
+            this.pnlBioZMux = new System.Windows.Forms.Panel();
+            this.label36 = new System.Windows.Forms.Label();
+            this.linkLabelBioZLoad = new System.Windows.Forms.LinkLabel();
+            this.cboBioZCalEnVcal = new MaximStyle.MaximComboBox();
+            this.lblBmuxEnUlpLon = new System.Windows.Forms.Label();
+            this.cboBioZCalVMode = new MaximStyle.MaximComboBox();
+            this.cboBmuxEnUlpLon = new MaximStyle.MaximComboBox();
+            this.cboBioZDcloffImag = new MaximStyle.MaximComboBox();
+            this.lblBioZCalEnVcal = new System.Windows.Forms.Label();
+            this.label27 = new System.Windows.Forms.Label();
+            this.lblBioZCalVMode = new System.Windows.Forms.Label();
+            this.cboBioZBmuxCalnSel = new MaximStyle.MaximComboBox();
+            this.lblBioZDcloffImag = new System.Windows.Forms.Label();
+            this.lblBioZBmuxCalnSel = new System.Windows.Forms.Label();
+            this.cboBioZCalVmag = new MaximStyle.MaximComboBox();
+            this.cboBioZBmuxCalpSel = new MaximStyle.MaximComboBox();
+            this.cboBioZCalFifty = new MaximStyle.MaximComboBox();
+            this.lblBioZBmuxCalpSel = new System.Windows.Forms.Label();
+            this.cboBioZCalThigh = new MaximStyle.MaximComboBox();
+            this.cboBioZRbiasn = new MaximStyle.MaximComboBox();
+            this.cboBioZCalFcal = new MaximStyle.MaximComboBox();
+            this.lblBioZRbiasn = new System.Windows.Forms.Label();
+            this.lblBioZCalFifty = new System.Windows.Forms.Label();
+            this.cboBioZRbiasp = new MaximStyle.MaximComboBox();
+            this.lblBioZCalThigh = new System.Windows.Forms.Label();
+            this.lblBioZRbiasp = new System.Windows.Forms.Label();
+            this.lblBioZCalFcal = new System.Windows.Forms.Label();
+            this.cboBioZRbiasv = new MaximStyle.MaximComboBox();
+            this.lblBioZCalVmag = new System.Windows.Forms.Label();
+            this.lblBioZRbiasv = new System.Windows.Forms.Label();
+            this.lblBioZBmuxOpenp = new System.Windows.Forms.Label();
+            this.cboBioZEnRbias = new MaximStyle.MaximComboBox();
+            this.lblBioZBmuxOpenn = new System.Windows.Forms.Label();
+            this.lblBioZEnRbias = new System.Windows.Forms.Label();
+            this.cboBioZBmuxOpenp = new MaximStyle.MaximComboBox();
+            this.lblBioZDcloffVth = new System.Windows.Forms.Label();
+            this.cboBioZBmuxOpenn = new MaximStyle.MaximComboBox();
+            this.cboBioZDcloffVth = new MaximStyle.MaximComboBox();
+            this.lblBioZEnDcloff = new System.Windows.Forms.Label();
+            this.cboBioZDcloffIpol = new MaximStyle.MaximComboBox();
+            this.cboBioZEnDcloff = new MaximStyle.MaximComboBox();
+            this.lblBioZDcloffIpol = new System.Windows.Forms.Label();
+            this.pictureBox2 = new System.Windows.Forms.PictureBox();
+            this.picLoff1 = new System.Windows.Forms.PictureBox();
+            this.picLoff2 = new System.Windows.Forms.PictureBox();
+            this.picLeadOn = new System.Windows.Forms.PictureBox();
+            this.picBioZsw1 = new System.Windows.Forms.PictureBox();
+            this.picBioZsw2 = new System.Windows.Forms.PictureBox();
+            this.picLeadBias1 = new System.Windows.Forms.PictureBox();
+            this.picLeadBias2 = new System.Windows.Forms.PictureBox();
+            this.picBioZCal1 = new System.Windows.Forms.PictureBox();
+            this.picBioZCal2 = new System.Windows.Forms.PictureBox();
+            this.tpMAX30001BioZLoad = new System.Windows.Forms.TabPage();
+            this.pnlBioZLoad = new System.Windows.Forms.Panel();
+            this.label37 = new System.Windows.Forms.Label();
+            this.lblBioZBmuxEnBist = new System.Windows.Forms.Label();
+            this.cboBioZBmuxRnom = new MaximStyle.MaximComboBox();
+            this.lblBioZBmuxRmod = new System.Windows.Forms.Label();
+            this.lblBioZBmuxRnom = new System.Windows.Forms.Label();
+            this.lblBioZBmuxFbist = new System.Windows.Forms.Label();
+            this.cboBioZBmuxFbist = new MaximStyle.MaximComboBox();
+            this.label33 = new System.Windows.Forms.Label();
+            this.cboBioZBmuxRmod = new MaximStyle.MaximComboBox();
+            this.cboBioZBmuxEnBist = new MaximStyle.MaximComboBox();
+            this.picBioZLoad = new System.Windows.Forms.PictureBox();
+            this.picBioZLloff1 = new System.Windows.Forms.PictureBox();
+            this.picBioZLloff2 = new System.Windows.Forms.PictureBox();
+            this.picBioZLlon = new System.Windows.Forms.PictureBox();
+            this.picBioZLsw1 = new System.Windows.Forms.PictureBox();
+            this.picBioZLlb2 = new System.Windows.Forms.PictureBox();
+            this.picBioZLcal2 = new System.Windows.Forms.PictureBox();
+            this.picBioZLcal1 = new System.Windows.Forms.PictureBox();
+            this.picBioZLlb1 = new System.Windows.Forms.PictureBox();
+            this.picBioZLsw2 = new System.Windows.Forms.PictureBox();
+            this.picBioZLresload = new System.Windows.Forms.PictureBox();
+            this.tpMAX30001Pace = new System.Windows.Forms.TabPage();
+            this.pnlPace = new System.Windows.Forms.Panel();
+            this.label38 = new System.Windows.Forms.Label();
+            this.cboPaceAnalogHpf = new MaximStyle.MaximComboBox();
+            this.label35 = new System.Windows.Forms.Label();
+            this.lblPaceAnalogHpf = new System.Windows.Forms.Label();
+            this.cboPaceDetectorNegativeThreshold = new MaximStyle.MaximComboBox();
+            this.lblPaceBufferBandwidth = new System.Windows.Forms.Label();
+            this.cboPaceDetectorPostiveThreshold = new MaximStyle.MaximComboBox();
+            this.lblPaceSignalSelection = new System.Windows.Forms.Label();
+            this.cboPaceDifferentiatorMode = new MaximStyle.MaximComboBox();
+            this.lblPaceInputPolarity = new System.Windows.Forms.Label();
+            this.cboPaceChannelGain = new MaximStyle.MaximComboBox();
+            this.lblPaceChannelGain = new System.Windows.Forms.Label();
+            this.cboPaceInputPolarity = new MaximStyle.MaximComboBox();
+            this.lblPaceDifferentiatorMode = new System.Windows.Forms.Label();
+            this.cboPaceSignalSelection = new MaximStyle.MaximComboBox();
+            this.lblPaceDetectorPostiveThreshold = new System.Windows.Forms.Label();
+            this.cboPaceBufferBandwidth = new MaximStyle.MaximComboBox();
+            this.lblPaceDetectorNegativeThreshold = new System.Windows.Forms.Label();
+            this.picPaceChannel = new System.Windows.Forms.PictureBox();
+            this.tpMAX30001Plots = new System.Windows.Forms.TabPage();
+            this.ecgView1 = new HealthSensorPlatform.CustomControls.EcgView();
+            this.tpFlashLog = new System.Windows.Forms.TabPage();
+            this.dataLoggingView1 = new HealthSensorPlatform.CustomControls.DataLoggingView();
+            this.tpRegisters = new System.Windows.Forms.TabPage();
+            this.tableLayoutPanel1 = new System.Windows.Forms.TableLayoutPanel();
+            this.cboRegisterTabDevice = new MaximStyle.MaximComboBox();
+            this.pnlRegMAX30205_U18 = new System.Windows.Forms.Panel();
+            this.rvMAX30205_U18 = new Maxim.CustomControls.RegisterView();
+            this.pnlRegMAX14720 = new System.Windows.Forms.Panel();
+            this.rvMAX14720 = new Maxim.CustomControls.RegisterView();
+            this.pnlRegMAX30101 = new System.Windows.Forms.Panel();
+            this.rvMAX30101 = new Maxim.CustomControls.RegisterView();
+            this.pnlRegMAX30001 = new System.Windows.Forms.Panel();
+            this.rvMAX30001 = new Maxim.CustomControls.RegisterView();
+            this.pnlRegMAX30205 = new System.Windows.Forms.Panel();
+            this.rvMAX30205 = new Maxim.CustomControls.RegisterView();
+            this.pnlRegLIS2HD = new System.Windows.Forms.Panel();
+            this.rvLIS2HD = new Maxim.CustomControls.RegisterView();
+            this.tpPrimitives = new System.Windows.Forms.TabPage();
+            this.primitivesView1 = new HealthSensorPlatform.CustomControls.PrimitivesView();
+            this.label16 = new System.Windows.Forms.Label();
+            this.label12 = new System.Windows.Forms.Label();
+            this.label13 = new System.Windows.Forms.Label();
+            this.label14 = new System.Windows.Forms.Label();
+            this.label15 = new System.Windows.Forms.Label();
+            this.label5 = new System.Windows.Forms.Label();
+            this.label9 = new System.Windows.Forms.Label();
+            this.label10 = new System.Windows.Forms.Label();
+            this.label11 = new System.Windows.Forms.Label();
+            this.label8 = new System.Windows.Forms.Label();
+            this.label4 = new System.Windows.Forms.Label();
+            this.label6 = new System.Windows.Forms.Label();
+            this.label7 = new System.Windows.Forms.Label();
+            this.label17 = new System.Windows.Forms.Label();
+            this.label18 = new System.Windows.Forms.Label();
+            this.label19 = new System.Windows.Forms.Label();
+            this.label20 = new System.Windows.Forms.Label();
+            this.label22 = new System.Windows.Forms.Label();
+            this.label3 = new System.Windows.Forms.Label();
+            this.label2 = new System.Windows.Forms.Label();
+            this.label23 = new System.Windows.Forms.Label();
+            this.label24 = new System.Windows.Forms.Label();
+            this.chart1 = new System.Windows.Forms.DataVisualization.Charting.Chart();
+            this.maximGroupBox2 = new MaximStyle.MaximGroupBox();
+            this.numericUpDown1 = new System.Windows.Forms.NumericUpDown();
+            this.comboBox1 = new System.Windows.Forms.ComboBox();
+            this.maximGroupBox3 = new MaximStyle.MaximGroupBox();
+            this.chart2 = new System.Windows.Forms.DataVisualization.Charting.Chart();
+            this.maximGroupBox4 = new MaximStyle.MaximGroupBox();
+            this.comboBox2 = new System.Windows.Forms.ComboBox();
+            this.comboBox3 = new System.Windows.Forms.ComboBox();
+            this.comboBox4 = new System.Windows.Forms.ComboBox();
+            this.comboBox5 = new System.Windows.Forms.ComboBox();
+            this.maximGroupBox5 = new MaximStyle.MaximGroupBox();
+            this.comboBox6 = new System.Windows.Forms.ComboBox();
+            this.comboBox7 = new System.Windows.Forms.ComboBox();
+            this.comboBox8 = new System.Windows.Forms.ComboBox();
+            this.comboBox9 = new System.Windows.Forms.ComboBox();
+            this.maximGroupBox6 = new MaximStyle.MaximGroupBox();
+            this.comboBox10 = new System.Windows.Forms.ComboBox();
+            this.comboBox11 = new System.Windows.Forms.ComboBox();
+            this.comboBox12 = new System.Windows.Forms.ComboBox();
+            this.maximGroupBox7 = new MaximStyle.MaximGroupBox();
+            this.textBox1 = new System.Windows.Forms.TextBox();
+            this.maximButton1 = new MaximStyle.MaximButton();
+            this.maximButton2 = new MaximStyle.MaximButton();
+            this.comboBox13 = new System.Windows.Forms.ComboBox();
+            this.maximButton3 = new MaximStyle.MaximButton();
+            this.maximButton4 = new MaximStyle.MaximButton();
+            this.comboBox14 = new System.Windows.Forms.ComboBox();
+            this.toolTip1 = new System.Windows.Forms.ToolTip(this.components);
+            this.menuStrip1 = new System.Windows.Forms.MenuStrip();
+            this.toolStripMenuItem3 = new System.Windows.Forms.ToolStripMenuItem();
+            this.toolStripMenuItem4 = new System.Windows.Forms.ToolStripMenuItem();
+            this.toolStripMenuItem5 = new System.Windows.Forms.ToolStripMenuItem();
+            this.toolStripMenuItem6 = new System.Windows.Forms.ToolStripMenuItem();
+            this.toolStripMenuItem7 = new System.Windows.Forms.ToolStripMenuItem();
+            this.toolStripMenuItem8 = new System.Windows.Forms.ToolStripMenuItem();
+            this.toolStripMenuItem9 = new System.Windows.Forms.ToolStripMenuItem();
+            this.toolStripMenuItem10 = new System.Windows.Forms.ToolStripMenuItem();
+            this.toolStripSeparator4 = new System.Windows.Forms.ToolStripSeparator();
+            this.toolStripMenuItem11 = new System.Windows.Forms.ToolStripMenuItem();
+            this.toolStripMenuItem12 = new System.Windows.Forms.ToolStripMenuItem();
+            this.toolStripSeparator6 = new System.Windows.Forms.ToolStripSeparator();
+            this.toolStripMenuItem13 = new System.Windows.Forms.ToolStripMenuItem();
+            this.toolStripMenuItem14 = new System.Windows.Forms.ToolStripMenuItem();
+            this.toolStripSeparator7 = new System.Windows.Forms.ToolStripSeparator();
+            this.toolStripMenuItem15 = new System.Windows.Forms.ToolStripMenuItem();
+            this.toolStripMenuItem16 = new System.Windows.Forms.ToolStripMenuItem();
+            this.toolStripMenuItem17 = new System.Windows.Forms.ToolStripMenuItem();
+            this.toolStripMenuItem18 = new System.Windows.Forms.ToolStripMenuItem();
+            this.toolStripMenuItem19 = new System.Windows.Forms.ToolStripMenuItem();
+            this.toolStripMenuItem20 = new System.Windows.Forms.ToolStripMenuItem();
+            this.toolStripMenuItem21 = new System.Windows.Forms.ToolStripMenuItem();
+            this.toolStripSeparator8 = new System.Windows.Forms.ToolStripSeparator();
+            this.toolStripMenuItem22 = new System.Windows.Forms.ToolStripMenuItem();
+            this.toolStripMenuItem23 = new System.Windows.Forms.ToolStripMenuItem();
+            this.toolStripMenuItem24 = new System.Windows.Forms.ToolStripMenuItem();
+            this.toolStripMenuItem25 = new System.Windows.Forms.ToolStripMenuItem();
+            this.maximGroupBox1.SuspendLayout();
+            this.maximTabControl1.SuspendLayout();
+            this.tpBlockDiagram.SuspendLayout();
+            this.tlbQuickStart.SuspendLayout();
+            this.pnlBlockDiagram.SuspendLayout();
+            ((System.ComponentModel.ISupportInitialize)(this.picBlockDiagram)).BeginInit();
+            this.tpOpticalSensor.SuspendLayout();
+            this.tpTemperature.SuspendLayout();
+            this.tpMAX30001EcgChannel.SuspendLayout();
+            this.flowLayoutPanel1.SuspendLayout();
+            this.pnlEcgChannel.SuspendLayout();
+            ((System.ComponentModel.ISupportInitialize)(this.picEcgChannel)).BeginInit();
+            this.grpRToR.SuspendLayout();
+            this.tpMAX30001InputMux.SuspendLayout();
+            this.pnlEcgMux.SuspendLayout();
+            ((System.ComponentModel.ISupportInitialize)(this.picECGLeadConfig)).BeginInit();
+            ((System.ComponentModel.ISupportInitialize)(this.picSw1)).BeginInit();
+            ((System.ComponentModel.ISupportInitialize)(this.picSw2)).BeginInit();
+            ((System.ComponentModel.ISupportInitialize)(this.pictureBox1)).BeginInit();
+            ((System.ComponentModel.ISupportInitialize)(this.picSw3)).BeginInit();
+            ((System.ComponentModel.ISupportInitialize)(this.picSw4)).BeginInit();
+            ((System.ComponentModel.ISupportInitialize)(this.picSw5)).BeginInit();
+            ((System.ComponentModel.ISupportInitialize)(this.picSw6)).BeginInit();
+            ((System.ComponentModel.ISupportInitialize)(this.picSw7)).BeginInit();
+            ((System.ComponentModel.ISupportInitialize)(this.picSw8)).BeginInit();
+            ((System.ComponentModel.ISupportInitialize)(this.picSw9)).BeginInit();
+            ((System.ComponentModel.ISupportInitialize)(this.picSw10)).BeginInit();
+            ((System.ComponentModel.ISupportInitialize)(this.picSw11)).BeginInit();
+            ((System.ComponentModel.ISupportInitialize)(this.picSw12)).BeginInit();
+            ((System.ComponentModel.ISupportInitialize)(this.picSw13)).BeginInit();
+            ((System.ComponentModel.ISupportInitialize)(this.picSw14)).BeginInit();
+            this.pnlMAX30001Global.SuspendLayout();
+            this.grpChannelPlotEnable.SuspendLayout();
+            this.maximGroupBox8.SuspendLayout();
+            this.grpGlobalControls.SuspendLayout();
+            this.tpBioZChannel.SuspendLayout();
+            this.pnlBioZChannel.SuspendLayout();
+            ((System.ComponentModel.ISupportInitialize)(this.picBioZChannel)).BeginInit();
+            this.tpMAX30001BioZInputMux.SuspendLayout();
+            this.pnlBioZMux.SuspendLayout();
+            ((System.ComponentModel.ISupportInitialize)(this.pictureBox2)).BeginInit();
+            ((System.ComponentModel.ISupportInitialize)(this.picLoff1)).BeginInit();
+            ((System.ComponentModel.ISupportInitialize)(this.picLoff2)).BeginInit();
+            ((System.ComponentModel.ISupportInitialize)(this.picLeadOn)).BeginInit();
+            ((System.ComponentModel.ISupportInitialize)(this.picBioZsw1)).BeginInit();
+            ((System.ComponentModel.ISupportInitialize)(this.picBioZsw2)).BeginInit();
+            ((System.ComponentModel.ISupportInitialize)(this.picLeadBias1)).BeginInit();
+            ((System.ComponentModel.ISupportInitialize)(this.picLeadBias2)).BeginInit();
+            ((System.ComponentModel.ISupportInitialize)(this.picBioZCal1)).BeginInit();
+            ((System.ComponentModel.ISupportInitialize)(this.picBioZCal2)).BeginInit();
+            this.tpMAX30001BioZLoad.SuspendLayout();
+            this.pnlBioZLoad.SuspendLayout();
+            ((System.ComponentModel.ISupportInitialize)(this.picBioZLoad)).BeginInit();
+            ((System.ComponentModel.ISupportInitialize)(this.picBioZLloff1)).BeginInit();
+            ((System.ComponentModel.ISupportInitialize)(this.picBioZLloff2)).BeginInit();
+            ((System.ComponentModel.ISupportInitialize)(this.picBioZLlon)).BeginInit();
+            ((System.ComponentModel.ISupportInitialize)(this.picBioZLsw1)).BeginInit();
+            ((System.ComponentModel.ISupportInitialize)(this.picBioZLlb2)).BeginInit();
+            ((System.ComponentModel.ISupportInitialize)(this.picBioZLcal2)).BeginInit();
+            ((System.ComponentModel.ISupportInitialize)(this.picBioZLcal1)).BeginInit();
+            ((System.ComponentModel.ISupportInitialize)(this.picBioZLlb1)).BeginInit();
+            ((System.ComponentModel.ISupportInitialize)(this.picBioZLsw2)).BeginInit();
+            ((System.ComponentModel.ISupportInitialize)(this.picBioZLresload)).BeginInit();
+            this.tpMAX30001Pace.SuspendLayout();
+            this.pnlPace.SuspendLayout();
+            ((System.ComponentModel.ISupportInitialize)(this.picPaceChannel)).BeginInit();
+            this.tpMAX30001Plots.SuspendLayout();
+            this.tpFlashLog.SuspendLayout();
+            this.tpRegisters.SuspendLayout();
+            this.tableLayoutPanel1.SuspendLayout();
+            this.pnlRegMAX30205_U18.SuspendLayout();
+            this.pnlRegMAX14720.SuspendLayout();
+            this.pnlRegMAX30101.SuspendLayout();
+            this.pnlRegMAX30001.SuspendLayout();
+            this.pnlRegMAX30205.SuspendLayout();
+            this.pnlRegLIS2HD.SuspendLayout();
+            this.tpPrimitives.SuspendLayout();
+            ((System.ComponentModel.ISupportInitialize)(this.chart1)).BeginInit();
+            ((System.ComponentModel.ISupportInitialize)(this.numericUpDown1)).BeginInit();
+            ((System.ComponentModel.ISupportInitialize)(this.chart2)).BeginInit();
+            this.menuStrip1.SuspendLayout();
+            this.SuspendLayout();
+            // 
+            // txt_Status
+            // 
+            this.txt_Status.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left) 
+            | System.Windows.Forms.AnchorStyles.Right)));
+            this.txt_Status.BackColor = System.Drawing.Color.White;
+            this.txt_Status.Font = new System.Drawing.Font("Arial", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+            this.txt_Status.Location = new System.Drawing.Point(8, 46);
+            this.txt_Status.Multiline = true;
+            this.txt_Status.Name = "txt_Status";
+            this.txt_Status.ReadOnly = true;
+            this.txt_Status.ScrollBars = System.Windows.Forms.ScrollBars.Vertical;
+            this.txt_Status.Size = new System.Drawing.Size(555, 245);
+            this.txt_Status.TabIndex = 2;
+            this.txt_Status.TabStop = false;
+            this.txt_Status.TextChanged += new System.EventHandler(this.txt_Status_TextChanged);
+            // 
+            // label1
+            // 
+            this.label1.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
+            this.label1.AutoSize = true;
+            this.label1.Font = new System.Drawing.Font("Arial", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+            this.label1.Location = new System.Drawing.Point(13, 55);
+            this.label1.Name = "label1";
+            this.label1.Size = new System.Drawing.Size(123, 15);
+            this.label1.TabIndex = 24;
+            this.label1.Text = "PROX_INT_THRESH";
+            this.label1.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
+            // 
+            // btn_Clear
+            // 
+            this.btn_Clear.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
+            this.btn_Clear.Location = new System.Drawing.Point(484, 12);
+            this.btn_Clear.Name = "btn_Clear";
+            this.btn_Clear.Size = new System.Drawing.Size(81, 22);
+            this.btn_Clear.TabIndex = 6;
+            this.btn_Clear.Text = "Clear Log";
+            this.btn_Clear.UseVisualStyleBackColor = true;
+            this.btn_Clear.Click += new System.EventHandler(this.btn_Clear_Click);
+            // 
+            // ss_Status
+            // 
+            this.ss_Status.ImageScalingSize = new System.Drawing.Size(20, 20);
+            this.ss_Status.Location = new System.Drawing.Point(0, 656);
+            this.ss_Status.Name = "ss_Status";
+            this.ss_Status.Size = new System.Drawing.Size(961, 26);
+            this.ss_Status.TabIndex = 16;
+            this.ss_Status.Text = "maximStatusStrip1";
+            // 
+            // toolStripMenuItem1
+            // 
+            this.toolStripMenuItem1.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
+            this.exitToolStripMenuItem});
+            this.toolStripMenuItem1.Name = "toolStripMenuItem1";
+            this.toolStripMenuItem1.Size = new System.Drawing.Size(41, 20);
+            this.toolStripMenuItem1.Text = "File";
+            // 
+            // exitToolStripMenuItem
+            // 
+            this.exitToolStripMenuItem.Name = "exitToolStripMenuItem";
+            this.exitToolStripMenuItem.Size = new System.Drawing.Size(99, 22);
+            this.exitToolStripMenuItem.Text = "Exit";
+            this.exitToolStripMenuItem.Click += new System.EventHandler(this.exitToolStripMenuItem_Click);
+            // 
+            // toolStripMenuItem2
+            // 
+            this.toolStripMenuItem2.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
+            this.connectionToolStripMenuItem,
+            this.disconnectToolStripMenuItem});
+            this.toolStripMenuItem2.Name = "toolStripMenuItem2";
+            this.toolStripMenuItem2.Size = new System.Drawing.Size(58, 20);
+            this.toolStripMenuItem2.Text = "Device";
+            // 
+            // connectionToolStripMenuItem
+            // 
+            this.connectionToolStripMenuItem.Name = "connectionToolStripMenuItem";
+            this.connectionToolStripMenuItem.Size = new System.Drawing.Size(141, 22);
+            this.connectionToolStripMenuItem.Text = "Connect";
+            this.connectionToolStripMenuItem.Click += new System.EventHandler(this.connectionToolStripMenuItem_Click);
+            // 
+            // disconnectToolStripMenuItem
+            // 
+            this.disconnectToolStripMenuItem.Name = "disconnectToolStripMenuItem";
+            this.disconnectToolStripMenuItem.Size = new System.Drawing.Size(141, 22);
+            this.disconnectToolStripMenuItem.Text = "Disconnect";
+            this.disconnectToolStripMenuItem.Click += new System.EventHandler(this.disconnectToolStripMenuItem_Click);
+            // 
+            // optionsToolStripMenuItem1
+            // 
+            this.optionsToolStripMenuItem1.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
+            this.registerNamesToolStripMenuItem,
+            this.bioZMilliohmScaleToolStripMenuItem,
+            this.toolStripSeparator1,
+            this.loadRegisterSettingsToolStripMenuItem,
+            this.saveRegisterSettingsToolStripMenuItem,
+            this.toolStripSeparator2,
+            this.loadAllRegisterSettingsToolStripMenuItem,
+            this.registerExportToolStripMenuItem,
+            this.toolStripSeparator3,
+            this.showAdvancedTabToolStripMenuItem});
+            this.optionsToolStripMenuItem1.Name = "optionsToolStripMenuItem1";
+            this.optionsToolStripMenuItem1.Size = new System.Drawing.Size(65, 20);
+            this.optionsToolStripMenuItem1.Text = "Options";
+            // 
+            // registerNamesToolStripMenuItem
+            // 
+            this.registerNamesToolStripMenuItem.CheckOnClick = true;
+            this.registerNamesToolStripMenuItem.Name = "registerNamesToolStripMenuItem";
+            this.registerNamesToolStripMenuItem.Size = new System.Drawing.Size(274, 22);
+            this.registerNamesToolStripMenuItem.Text = "Show MAX30001 Register Names";
+            this.registerNamesToolStripMenuItem.Click += new System.EventHandler(this.registerNamesToolStripMenuItem_Click);
+            // 
+            // bioZMilliohmScaleToolStripMenuItem
+            // 
+            this.bioZMilliohmScaleToolStripMenuItem.CheckOnClick = true;
+            this.bioZMilliohmScaleToolStripMenuItem.Name = "bioZMilliohmScaleToolStripMenuItem";
+            this.bioZMilliohmScaleToolStripMenuItem.Size = new System.Drawing.Size(274, 22);
+            this.bioZMilliohmScaleToolStripMenuItem.Text = "BioZ Milliohm Scale";
+            this.bioZMilliohmScaleToolStripMenuItem.Click += new System.EventHandler(this.bioZMilliohmScaleToolStripMenuItem_Click);
+            // 
+            // toolStripSeparator1
+            // 
+            this.toolStripSeparator1.Name = "toolStripSeparator1";
+            this.toolStripSeparator1.Size = new System.Drawing.Size(271, 6);
+            // 
+            // loadRegisterSettingsToolStripMenuItem
+            // 
+            this.loadRegisterSettingsToolStripMenuItem.Name = "loadRegisterSettingsToolStripMenuItem";
+            this.loadRegisterSettingsToolStripMenuItem.Size = new System.Drawing.Size(274, 22);
+            this.loadRegisterSettingsToolStripMenuItem.Text = "Load MAX30001 Register Settings";
+            this.loadRegisterSettingsToolStripMenuItem.Visible = false;
+            // 
+            // saveRegisterSettingsToolStripMenuItem
+            // 
+            this.saveRegisterSettingsToolStripMenuItem.Name = "saveRegisterSettingsToolStripMenuItem";
+            this.saveRegisterSettingsToolStripMenuItem.Size = new System.Drawing.Size(274, 22);
+            this.saveRegisterSettingsToolStripMenuItem.Text = "Save MAX30001 Register Settings";
+            this.saveRegisterSettingsToolStripMenuItem.Visible = false;
+            // 
+            // toolStripSeparator2
+            // 
+            this.toolStripSeparator2.Name = "toolStripSeparator2";
+            this.toolStripSeparator2.Size = new System.Drawing.Size(271, 6);
+            this.toolStripSeparator2.Visible = false;
+            // 
+            // loadAllRegisterSettingsToolStripMenuItem
+            // 
+            this.loadAllRegisterSettingsToolStripMenuItem.Name = "loadAllRegisterSettingsToolStripMenuItem";
+            this.loadAllRegisterSettingsToolStripMenuItem.Size = new System.Drawing.Size(274, 22);
+            this.loadAllRegisterSettingsToolStripMenuItem.Text = "Load Register Settings";
+            this.loadAllRegisterSettingsToolStripMenuItem.Click += new System.EventHandler(this.loadAllRegisterSettingsToolStripMenuItem_Click);
+            // 
+            // registerExportToolStripMenuItem
+            // 
+            this.registerExportToolStripMenuItem.Name = "registerExportToolStripMenuItem";
+            this.registerExportToolStripMenuItem.Size = new System.Drawing.Size(274, 22);
+            this.registerExportToolStripMenuItem.Text = "Export Register Settings";
+            this.registerExportToolStripMenuItem.Click += new System.EventHandler(this.registerExportToolStripMenuItem_Click);
+            // 
+            // toolStripSeparator3
+            // 
+            this.toolStripSeparator3.Name = "toolStripSeparator3";
+            this.toolStripSeparator3.Size = new System.Drawing.Size(271, 6);
+            // 
+            // showAdvancedTabToolStripMenuItem
+            // 
+            this.showAdvancedTabToolStripMenuItem.CheckOnClick = true;
+            this.showAdvancedTabToolStripMenuItem.Name = "showAdvancedTabToolStripMenuItem";
+            this.showAdvancedTabToolStripMenuItem.Size = new System.Drawing.Size(274, 22);
+            this.showAdvancedTabToolStripMenuItem.Text = "Show Advanced Tab";
+            this.showAdvancedTabToolStripMenuItem.Click += new System.EventHandler(this.showAdvancedTabToolStripMenuItem_Click);
+            // 
+            // loggingToolStripMenuItem
+            // 
+            this.loggingToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
+            this.eCGBioZFileLogToolStripMenuItem,
+            this.eCGFileLogToolStripMenuItem,
+            this.rToRFileLogToolStripMenuItem,
+            this.paceFileLogToolStripMenuItem,
+            this.bioZFileLogToolStripMenuItem,
+            this.toolStripSeparator5,
+            this.opticalAccelerometerFileLogToolStripMenuItem});
+            this.loggingToolStripMenuItem.Name = "loggingToolStripMenuItem";
+            this.loggingToolStripMenuItem.Size = new System.Drawing.Size(65, 20);
+            this.loggingToolStripMenuItem.Text = "Logging";
+            // 
+            // eCGBioZFileLogToolStripMenuItem
+            // 
+            this.eCGBioZFileLogToolStripMenuItem.Name = "eCGBioZFileLogToolStripMenuItem";
+            this.eCGBioZFileLogToolStripMenuItem.Size = new System.Drawing.Size(204, 22);
+            this.eCGBioZFileLogToolStripMenuItem.Text = "ECG/BioZ File Log";
+            this.eCGBioZFileLogToolStripMenuItem.Visible = false;
+            // 
+            // eCGFileLogToolStripMenuItem
+            // 
+            this.eCGFileLogToolStripMenuItem.Name = "eCGFileLogToolStripMenuItem";
+            this.eCGFileLogToolStripMenuItem.Size = new System.Drawing.Size(204, 22);
+            this.eCGFileLogToolStripMenuItem.Text = "ECG File Log";
+            this.eCGFileLogToolStripMenuItem.Click += new System.EventHandler(this.eCGFileLogToolStripMenuItem_Click);
+            // 
+            // rToRFileLogToolStripMenuItem
+            // 
+            this.rToRFileLogToolStripMenuItem.Name = "rToRFileLogToolStripMenuItem";
+            this.rToRFileLogToolStripMenuItem.Size = new System.Drawing.Size(204, 22);
+            this.rToRFileLogToolStripMenuItem.Text = "R-To-R File Log";
+            this.rToRFileLogToolStripMenuItem.Click += new System.EventHandler(this.rToRFileLogToolStripMenuItem_Click);
+            // 
+            // paceFileLogToolStripMenuItem
+            // 
+            this.paceFileLogToolStripMenuItem.Name = "paceFileLogToolStripMenuItem";
+            this.paceFileLogToolStripMenuItem.Size = new System.Drawing.Size(204, 22);
+            this.paceFileLogToolStripMenuItem.Text = "Pace File Log";
+            this.paceFileLogToolStripMenuItem.Click += new System.EventHandler(this.paceFileLogToolStripMenuItem_Click);
+            // 
+            // bioZFileLogToolStripMenuItem
+            // 
+            this.bioZFileLogToolStripMenuItem.Name = "bioZFileLogToolStripMenuItem";
+            this.bioZFileLogToolStripMenuItem.Size = new System.Drawing.Size(204, 22);
+            this.bioZFileLogToolStripMenuItem.Text = "BioZ File Log";
+            this.bioZFileLogToolStripMenuItem.Click += new System.EventHandler(this.bioZFileLogToolStripMenuItem_Click);
+            // 
+            // toolStripSeparator5
+            // 
+            this.toolStripSeparator5.Name = "toolStripSeparator5";
+            this.toolStripSeparator5.Size = new System.Drawing.Size(201, 6);
+            // 
+            // opticalAccelerometerFileLogToolStripMenuItem
+            // 
+            this.opticalAccelerometerFileLogToolStripMenuItem.Name = "opticalAccelerometerFileLogToolStripMenuItem";
+            this.opticalAccelerometerFileLogToolStripMenuItem.Size = new System.Drawing.Size(204, 22);
+            this.opticalAccelerometerFileLogToolStripMenuItem.Text = "Optical/Accel File Log";
+            this.opticalAccelerometerFileLogToolStripMenuItem.Click += new System.EventHandler(this.opticalAccelerometerFileLogToolStripMenuItem_Click);
+            // 
+            // helpToolStripMenuItem1
+            // 
+            this.helpToolStripMenuItem1.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
+            this.onlineDocumentationToolStripMenuItem,
+            this.aboutToolStripMenuItem});
+            this.helpToolStripMenuItem1.Name = "helpToolStripMenuItem1";
+            this.helpToolStripMenuItem1.Size = new System.Drawing.Size(46, 20);
+            this.helpToolStripMenuItem1.Text = "Help";
+            // 
+            // onlineDocumentationToolStripMenuItem
+            // 
+            this.onlineDocumentationToolStripMenuItem.Name = "onlineDocumentationToolStripMenuItem";
+            this.onlineDocumentationToolStripMenuItem.Size = new System.Drawing.Size(204, 22);
+            this.onlineDocumentationToolStripMenuItem.Text = "Online Documentation";
+            this.onlineDocumentationToolStripMenuItem.Click += new System.EventHandler(this.onlineDocumentationToolStripMenuItem_Click);
+            // 
+            // aboutToolStripMenuItem
+            // 
+            this.aboutToolStripMenuItem.Name = "aboutToolStripMenuItem";
+            this.aboutToolStripMenuItem.Size = new System.Drawing.Size(204, 22);
+            this.aboutToolStripMenuItem.Text = "About";
+            this.aboutToolStripMenuItem.Click += new System.EventHandler(this.aboutToolStripMenuItem_Click);
+            // 
+            // fileToolStripMenuItem
+            // 
+            this.fileToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
+            this.tsm_exit});
+            this.fileToolStripMenuItem.Name = "fileToolStripMenuItem";
+            this.fileToolStripMenuItem.Size = new System.Drawing.Size(41, 20);
+            this.fileToolStripMenuItem.Text = "&File";
+            // 
+            // tsm_exit
+            // 
+            this.tsm_exit.Name = "tsm_exit";
+            this.tsm_exit.Size = new System.Drawing.Size(67, 22);
+            // 
+            // deviceToolStripMenuItem
+            // 
+            this.deviceToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
+            this.test1ToolStripMenuItem});
+            this.deviceToolStripMenuItem.Name = "deviceToolStripMenuItem";
+            this.deviceToolStripMenuItem.Size = new System.Drawing.Size(58, 20);
+            this.deviceToolStripMenuItem.Text = "&Device";
+            // 
+            // test1ToolStripMenuItem
+            // 
+            this.test1ToolStripMenuItem.Name = "test1ToolStripMenuItem";
+            this.test1ToolStripMenuItem.Size = new System.Drawing.Size(99, 22);
+            this.test1ToolStripMenuItem.Text = "test1";
+            // 
+            // optionsToolStripMenuItem
+            // 
+            this.optionsToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
+            this.test2ToolStripMenuItem});
+            this.optionsToolStripMenuItem.Name = "optionsToolStripMenuItem";
+            this.optionsToolStripMenuItem.Size = new System.Drawing.Size(65, 20);
+            this.optionsToolStripMenuItem.Text = "&Options";
+            // 
+            // test2ToolStripMenuItem
+            // 
+            this.test2ToolStripMenuItem.Name = "test2ToolStripMenuItem";
+            this.test2ToolStripMenuItem.Size = new System.Drawing.Size(99, 22);
+            this.test2ToolStripMenuItem.Text = "test2";
+            // 
+            // helpToolStripMenuItem
+            // 
+            this.helpToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
+            this.technicalDocsToolStripMenuItem,
+            this.tsm_about});
+            this.helpToolStripMenuItem.Name = "helpToolStripMenuItem";
+            this.helpToolStripMenuItem.Size = new System.Drawing.Size(46, 20);
+            this.helpToolStripMenuItem.Text = "&Help";
+            // 
+            // technicalDocsToolStripMenuItem
+            // 
+            this.technicalDocsToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
+            this.tsm_EVKitDatasheet,
+            this.tsm_ICDatasheet});
+            this.technicalDocsToolStripMenuItem.Name = "technicalDocsToolStripMenuItem";
+            this.technicalDocsToolStripMenuItem.Size = new System.Drawing.Size(154, 22);
+            this.technicalDocsToolStripMenuItem.Text = "Technical Docs";
+            // 
+            // tsm_EVKitDatasheet
+            // 
+            this.tsm_EVKitDatasheet.Name = "tsm_EVKitDatasheet";
+            this.tsm_EVKitDatasheet.Size = new System.Drawing.Size(67, 22);
+            // 
+            // tsm_ICDatasheet
+            // 
+            this.tsm_ICDatasheet.Name = "tsm_ICDatasheet";
+            this.tsm_ICDatasheet.Size = new System.Drawing.Size(67, 22);
+            // 
+            // tsm_about
+            // 
+            this.tsm_about.Name = "tsm_about";
+            this.tsm_about.Size = new System.Drawing.Size(154, 22);
+            // 
+            // maximGroupBox1
+            // 
+            this.maximGroupBox1.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) 
+            | System.Windows.Forms.AnchorStyles.Left) 
+            | System.Windows.Forms.AnchorStyles.Right)));
+            this.maximGroupBox1.BackgroundColor = System.Drawing.Color.White;
+            this.maximGroupBox1.Controls.Add(this.txt_Status);
+            this.maximGroupBox1.Controls.Add(this.btn_Clear);
+            this.maximGroupBox1.Location = new System.Drawing.Point(628, 11);
+            this.maximGroupBox1.Name = "maximGroupBox1";
+            this.maximGroupBox1.Size = new System.Drawing.Size(452, 577);
+            this.maximGroupBox1.TabIndex = 38;
+            this.maximGroupBox1.TabStop = false;
+            this.maximGroupBox1.Text = "Accelerometer Measurements";
+            this.maximGroupBox1.TitleEnable = false;
+            // 
+            // maximTabControl1
+            // 
+            this.maximTabControl1.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) 
+            | System.Windows.Forms.AnchorStyles.Left) 
+            | System.Windows.Forms.AnchorStyles.Right)));
+            this.maximTabControl1.Controls.Add(this.tpBlockDiagram);
+            this.maximTabControl1.Controls.Add(this.tpOpticalSensor);
+            this.maximTabControl1.Controls.Add(this.tpTemperature);
+            this.maximTabControl1.Controls.Add(this.tpMAX30001EcgChannel);
+            this.maximTabControl1.Controls.Add(this.tpMAX30001InputMux);
+            this.maximTabControl1.Controls.Add(this.tpBioZChannel);
+            this.maximTabControl1.Controls.Add(this.tpMAX30001BioZInputMux);
+            this.maximTabControl1.Controls.Add(this.tpMAX30001BioZLoad);
+            this.maximTabControl1.Controls.Add(this.tpMAX30001Pace);
+            this.maximTabControl1.Controls.Add(this.tpMAX30001Plots);
+            this.maximTabControl1.Controls.Add(this.tpFlashLog);
+            this.maximTabControl1.Controls.Add(this.tpRegisters);
+            this.maximTabControl1.Controls.Add(this.tpPrimitives);
+            this.maximTabControl1.Font = new System.Drawing.Font("Arial", 9F);
+            this.maximTabControl1.Location = new System.Drawing.Point(-1, 23);
+            this.maximTabControl1.Name = "maximTabControl1";
+            this.maximTabControl1.SelectedIndex = 0;
+            this.maximTabControl1.Size = new System.Drawing.Size(961, 636);
+            this.maximTabControl1.TabIndex = 29;
+            this.maximTabControl1.SelectedIndexChanged += new System.EventHandler(this.maximTabControl1_SelectedIndexChanged);
+            this.maximTabControl1.Selecting += new System.Windows.Forms.TabControlCancelEventHandler(this.maximTabControl1_Selecting);
+            // 
+            // tpBlockDiagram
+            // 
+            this.tpBlockDiagram.Controls.Add(this.tlbQuickStart);
+            this.tpBlockDiagram.Controls.Add(this.pnlBlockDiagram);
+            this.tpBlockDiagram.Location = new System.Drawing.Point(4, 26);
+            this.tpBlockDiagram.Name = "tpBlockDiagram";
+            this.tpBlockDiagram.Size = new System.Drawing.Size(953, 606);
+            this.tpBlockDiagram.TabIndex = 19;
+            this.tpBlockDiagram.Text = "Home";
+            this.tpBlockDiagram.UseVisualStyleBackColor = true;
+            // 
+            // tlbQuickStart
+            // 
+            this.tlbQuickStart.ColumnCount = 1;
+            this.tlbQuickStart.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F));
+            this.tlbQuickStart.Controls.Add(this.linkLabelQuickRespiration, 0, 5);
+            this.tlbQuickStart.Controls.Add(this.label40, 0, 0);
+            this.tlbQuickStart.Controls.Add(this.linkLabelQuickOpticalSpO2, 0, 1);
+            this.tlbQuickStart.Controls.Add(this.linkLabelQuickTemperature, 0, 2);
+            this.tlbQuickStart.Controls.Add(this.linkLabelQuickBioimpedance, 0, 4);
+            this.tlbQuickStart.Controls.Add(this.linkLabelQuickEcg, 0, 3);
+            this.tlbQuickStart.Controls.Add(this.label41, 0, 6);
+            this.tlbQuickStart.Location = new System.Drawing.Point(811, 55);
+            this.tlbQuickStart.Name = "tlbQuickStart";
+            this.tlbQuickStart.RowCount = 7;
+            this.tlbQuickStart.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 16.66667F));
+            this.tlbQuickStart.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 16.66667F));
+            this.tlbQuickStart.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 16.66667F));
+            this.tlbQuickStart.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 16.66667F));
+            this.tlbQuickStart.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 16.66667F));
+            this.tlbQuickStart.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 16.66667F));
+            this.tlbQuickStart.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 150F));
+            this.tlbQuickStart.Size = new System.Drawing.Size(127, 310);
+            this.tlbQuickStart.TabIndex = 11;
+            // 
+            // linkLabelQuickRespiration
+            // 
+            this.linkLabelQuickRespiration.AutoSize = true;
+            this.linkLabelQuickRespiration.Font = new System.Drawing.Font("Arial", 11.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+            this.linkLabelQuickRespiration.LinkBehavior = System.Windows.Forms.LinkBehavior.NeverUnderline;
+            this.linkLabelQuickRespiration.LinkColor = System.Drawing.Color.FromArgb(((int)(((byte)(0)))), ((int)(((byte)(178)))), ((int)(((byte)(169)))));
+            this.linkLabelQuickRespiration.Location = new System.Drawing.Point(3, 130);
+            this.linkLabelQuickRespiration.Name = "linkLabelQuickRespiration";
+            this.linkLabelQuickRespiration.Size = new System.Drawing.Size(91, 17);
+            this.linkLabelQuickRespiration.TabIndex = 6;
+            this.linkLabelQuickRespiration.TabStop = true;
+            this.linkLabelQuickRespiration.Text = "• Respiration";
+            this.linkLabelQuickRespiration.LinkClicked += new System.Windows.Forms.LinkLabelLinkClickedEventHandler(this.linkLabelQuickRespiration_LinkClicked);
+            // 
+            // label40
+            // 
+            this.label40.AutoSize = true;
+            this.label40.Font = new System.Drawing.Font("Arial", 11.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+            this.label40.Location = new System.Drawing.Point(3, 0);
+            this.label40.Name = "label40";
+            this.label40.Size = new System.Drawing.Size(81, 17);
+            this.label40.TabIndex = 0;
+            this.label40.Text = "Quick Start";
+            // 
+            // linkLabelQuickOpticalSpO2
+            // 
+            this.linkLabelQuickOpticalSpO2.AutoSize = true;
+            this.linkLabelQuickOpticalSpO2.Font = new System.Drawing.Font("Arial", 11.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+            this.linkLabelQuickOpticalSpO2.LinkBehavior = System.Windows.Forms.LinkBehavior.NeverUnderline;
+            this.linkLabelQuickOpticalSpO2.LinkColor = System.Drawing.Color.FromArgb(((int)(((byte)(0)))), ((int)(((byte)(178)))), ((int)(((byte)(169)))));
+            this.linkLabelQuickOpticalSpO2.Location = new System.Drawing.Point(3, 26);
+            this.linkLabelQuickOpticalSpO2.Name = "linkLabelQuickOpticalSpO2";
+            this.linkLabelQuickOpticalSpO2.Size = new System.Drawing.Size(114, 17);
+            this.linkLabelQuickOpticalSpO2.TabIndex = 1;
+            this.linkLabelQuickOpticalSpO2.TabStop = true;
+            this.linkLabelQuickOpticalSpO2.Text = "• Optical - SpO2";
+            this.linkLabelQuickOpticalSpO2.LinkClicked += new System.Windows.Forms.LinkLabelLinkClickedEventHandler(this.linkLabelQuickOpticalSpO2_LinkClicked);
+            // 
+            // linkLabelQuickTemperature
+            // 
+            this.linkLabelQuickTemperature.AutoSize = true;
+            this.linkLabelQuickTemperature.Font = new System.Drawing.Font("Arial", 11.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+            this.linkLabelQuickTemperature.LinkBehavior = System.Windows.Forms.LinkBehavior.NeverUnderline;
+            this.linkLabelQuickTemperature.LinkColor = System.Drawing.Color.FromArgb(((int)(((byte)(0)))), ((int)(((byte)(178)))), ((int)(((byte)(169)))));
+            this.linkLabelQuickTemperature.Location = new System.Drawing.Point(3, 52);
+            this.linkLabelQuickTemperature.Name = "linkLabelQuickTemperature";
+            this.linkLabelQuickTemperature.Size = new System.Drawing.Size(99, 17);
+            this.linkLabelQuickTemperature.TabIndex = 2;
+            this.linkLabelQuickTemperature.TabStop = true;
+            this.linkLabelQuickTemperature.Text = "• Temperature";
+            this.linkLabelQuickTemperature.LinkClicked += new System.Windows.Forms.LinkLabelLinkClickedEventHandler(this.linkLabelQuickTemperature_LinkClicked);
+            // 
+            // linkLabelQuickBioimpedance
+            // 
+            this.linkLabelQuickBioimpedance.AutoSize = true;
+            this.linkLabelQuickBioimpedance.Font = new System.Drawing.Font("Arial", 11.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+            this.linkLabelQuickBioimpedance.LinkBehavior = System.Windows.Forms.LinkBehavior.NeverUnderline;
+            this.linkLabelQuickBioimpedance.LinkColor = System.Drawing.Color.FromArgb(((int)(((byte)(0)))), ((int)(((byte)(178)))), ((int)(((byte)(169)))));
+            this.linkLabelQuickBioimpedance.Location = new System.Drawing.Point(3, 104);
+            this.linkLabelQuickBioimpedance.Name = "linkLabelQuickBioimpedance";
+            this.linkLabelQuickBioimpedance.Size = new System.Drawing.Size(110, 17);
+            this.linkLabelQuickBioimpedance.TabIndex = 3;
+            this.linkLabelQuickBioimpedance.TabStop = true;
+            this.linkLabelQuickBioimpedance.Text = "• Bioimpedance";
+            this.linkLabelQuickBioimpedance.LinkClicked += new System.Windows.Forms.LinkLabelLinkClickedEventHandler(this.linkLabelQuickBioimpedance_LinkClicked);
+            // 
+            // linkLabelQuickEcg
+            // 
+            this.linkLabelQuickEcg.AutoSize = true;
+            this.linkLabelQuickEcg.Font = new System.Drawing.Font("Arial", 11.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+            this.linkLabelQuickEcg.LinkBehavior = System.Windows.Forms.LinkBehavior.NeverUnderline;
+            this.linkLabelQuickEcg.LinkColor = System.Drawing.Color.FromArgb(((int)(((byte)(0)))), ((int)(((byte)(178)))), ((int)(((byte)(169)))));
+            this.linkLabelQuickEcg.Location = new System.Drawing.Point(3, 78);
+            this.linkLabelQuickEcg.Name = "linkLabelQuickEcg";
+            this.linkLabelQuickEcg.Size = new System.Drawing.Size(49, 17);
+            this.linkLabelQuickEcg.TabIndex = 4;
+            this.linkLabelQuickEcg.TabStop = true;
+            this.linkLabelQuickEcg.Text = "• ECG";
+            this.linkLabelQuickEcg.LinkClicked += new System.Windows.Forms.LinkLabelLinkClickedEventHandler(this.linkLabelQuickEcg_LinkClicked);
+            // 
+            // label41
+            // 
+            this.label41.AutoSize = true;
+            this.label41.Font = new System.Drawing.Font("Arial", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+            this.label41.Location = new System.Drawing.Point(3, 156);
+            this.label41.Name = "label41";
+            this.label41.Size = new System.Drawing.Size(121, 112);
+            this.label41.TabIndex = 5;
+            this.label41.Text = "Select the above links to apply demo register settings and go to tab. Once on tab" +
+    ", review settings and then start demo.\r\n";
+            // 
+            // pnlBlockDiagram
+            // 
+            this.pnlBlockDiagram.Anchor = System.Windows.Forms.AnchorStyles.None;
+            this.pnlBlockDiagram.Controls.Add(this.label29);
+            this.pnlBlockDiagram.Controls.Add(this.linkOpticalSensor);
+            this.pnlBlockDiagram.Controls.Add(this.linkBioZLoad);
+            this.pnlBlockDiagram.Controls.Add(this.linkTempSensor);
+            this.pnlBlockDiagram.Controls.Add(this.linkBioZMux);
+            this.pnlBlockDiagram.Controls.Add(this.linkEcgMux);
+            this.pnlBlockDiagram.Controls.Add(this.linkBioZChannel);
+            this.pnlBlockDiagram.Controls.Add(this.linkEcgChannel);
+            this.pnlBlockDiagram.Controls.Add(this.linkPaceChannel);
+            this.pnlBlockDiagram.Controls.Add(this.picBlockDiagram);
+            this.pnlBlockDiagram.Location = new System.Drawing.Point(163, 9);
+            this.pnlBlockDiagram.Name = "pnlBlockDiagram";
+            this.pnlBlockDiagram.Size = new System.Drawing.Size(636, 587);
+            this.pnlBlockDiagram.TabIndex = 10;
+            // 
+            // label29
+            // 
+            this.label29.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
+            this.label29.AutoSize = true;
+            this.label29.Location = new System.Drawing.Point(434, 559);
+            this.label29.Name = "label29";
+            this.label29.Size = new System.Drawing.Size(144, 15);
+            this.label29.TabIndex = 9;
+            this.label29.Text = "Teal text are links to tabs.";
+            // 
+            // linkOpticalSensor
+            // 
+            this.linkOpticalSensor.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) 
+            | System.Windows.Forms.AnchorStyles.Left) 
+            | System.Windows.Forms.AnchorStyles.Right)));
+            this.linkOpticalSensor.AutoSize = true;
+            this.linkOpticalSensor.Font = new System.Drawing.Font("Calibri", 12F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+            this.linkOpticalSensor.LinkBehavior = System.Windows.Forms.LinkBehavior.NeverUnderline;
+            this.linkOpticalSensor.LinkColor = System.Drawing.Color.FromArgb(((int)(((byte)(0)))), ((int)(((byte)(178)))), ((int)(((byte)(169)))));
+            this.linkOpticalSensor.Location = new System.Drawing.Point(74, 130);
+            this.linkOpticalSensor.Name = "linkOpticalSensor";
+            this.linkOpticalSensor.Size = new System.Drawing.Size(107, 19);
+            this.linkOpticalSensor.TabIndex = 2;
+            this.linkOpticalSensor.TabStop = true;
+            this.linkOpticalSensor.Text = "Optical Sensor";
+            this.linkOpticalSensor.LinkClicked += new System.Windows.Forms.LinkLabelLinkClickedEventHandler(this.linkOpticalSensor_Click);
+            // 
+            // linkBioZLoad
+            // 
+            this.linkBioZLoad.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) 
+            | System.Windows.Forms.AnchorStyles.Left) 
+            | System.Windows.Forms.AnchorStyles.Right)));
+            this.linkBioZLoad.AutoSize = true;
+            this.linkBioZLoad.DisabledLinkColor = System.Drawing.Color.White;
+            this.linkBioZLoad.Font = new System.Drawing.Font("Calibri", 12F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+            this.linkBioZLoad.LinkBehavior = System.Windows.Forms.LinkBehavior.NeverUnderline;
+            this.linkBioZLoad.LinkColor = System.Drawing.Color.FromArgb(((int)(((byte)(0)))), ((int)(((byte)(178)))), ((int)(((byte)(169)))));
+            this.linkBioZLoad.Location = new System.Drawing.Point(462, 337);
+            this.linkBioZLoad.Name = "linkBioZLoad";
+            this.linkBioZLoad.Size = new System.Drawing.Size(76, 19);
+            this.linkBioZLoad.TabIndex = 8;
+            this.linkBioZLoad.TabStop = true;
+            this.linkBioZLoad.Text = "BioZ Load";
+            this.linkBioZLoad.LinkClicked += new System.Windows.Forms.LinkLabelLinkClickedEventHandler(this.linkBioZLoad_LinkClicked);
+            // 
+            // linkTempSensor
+            // 
+            this.linkTempSensor.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) 
+            | System.Windows.Forms.AnchorStyles.Left) 
+            | System.Windows.Forms.AnchorStyles.Right)));
+            this.linkTempSensor.AutoSize = true;
+            this.linkTempSensor.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(225)))), ((int)(((byte)(255)))), ((int)(((byte)(254)))));
+            this.linkTempSensor.Font = new System.Drawing.Font("Calibri", 12F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+            this.linkTempSensor.LinkBehavior = System.Windows.Forms.LinkBehavior.NeverUnderline;
+            this.linkTempSensor.LinkColor = System.Drawing.Color.FromArgb(((int)(((byte)(0)))), ((int)(((byte)(178)))), ((int)(((byte)(169)))));
+            this.linkTempSensor.Location = new System.Drawing.Point(77, 51);
+            this.linkTempSensor.Name = "linkTempSensor";
+            this.linkTempSensor.Size = new System.Drawing.Size(97, 19);
+            this.linkTempSensor.TabIndex = 1;
+            this.linkTempSensor.TabStop = true;
+            this.linkTempSensor.Text = "Temperature";
+            this.linkTempSensor.LinkClicked += new System.Windows.Forms.LinkLabelLinkClickedEventHandler(this.linkTempSensor_LinkClicked);
+            // 
+            // linkBioZMux
+            // 
+            this.linkBioZMux.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) 
+            | System.Windows.Forms.AnchorStyles.Left) 
+            | System.Windows.Forms.AnchorStyles.Right)));
+            this.linkBioZMux.AutoSize = true;
+            this.linkBioZMux.DisabledLinkColor = System.Drawing.Color.White;
+            this.linkBioZMux.Font = new System.Drawing.Font("Calibri", 12F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+            this.linkBioZMux.LinkBehavior = System.Windows.Forms.LinkBehavior.NeverUnderline;
+            this.linkBioZMux.LinkColor = System.Drawing.Color.FromArgb(((int)(((byte)(0)))), ((int)(((byte)(178)))), ((int)(((byte)(169)))));
+            this.linkBioZMux.Location = new System.Drawing.Point(462, 308);
+            this.linkBioZMux.Name = "linkBioZMux";
+            this.linkBioZMux.Size = new System.Drawing.Size(76, 19);
+            this.linkBioZMux.TabIndex = 7;
+            this.linkBioZMux.TabStop = true;
+            this.linkBioZMux.Text = "BioZ MUX";
+            this.linkBioZMux.LinkClicked += new System.Windows.Forms.LinkLabelLinkClickedEventHandler(this.linkBioZMux_LinkClicked);
+            // 
+            // linkEcgMux
+            // 
+            this.linkEcgMux.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) 
+            | System.Windows.Forms.AnchorStyles.Left) 
+            | System.Windows.Forms.AnchorStyles.Right)));
+            this.linkEcgMux.AutoSize = true;
+            this.linkEcgMux.Font = new System.Drawing.Font("Calibri", 12F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+            this.linkEcgMux.LinkBehavior = System.Windows.Forms.LinkBehavior.NeverUnderline;
+            this.linkEcgMux.LinkColor = System.Drawing.Color.FromArgb(((int)(((byte)(0)))), ((int)(((byte)(178)))), ((int)(((byte)(169)))));
+            this.linkEcgMux.Location = new System.Drawing.Point(463, 158);
+            this.linkEcgMux.Name = "linkEcgMux";
+            this.linkEcgMux.Size = new System.Drawing.Size(72, 19);
+            this.linkEcgMux.TabIndex = 4;
+            this.linkEcgMux.TabStop = true;
+            this.linkEcgMux.Text = "ECG MUX";
+            this.linkEcgMux.LinkClicked += new System.Windows.Forms.LinkLabelLinkClickedEventHandler(this.linkEcgMux_LinkClicked);
+            // 
+            // linkBioZChannel
+            // 
+            this.linkBioZChannel.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) 
+            | System.Windows.Forms.AnchorStyles.Left) 
+            | System.Windows.Forms.AnchorStyles.Right)));
+            this.linkBioZChannel.AutoSize = true;
+            this.linkBioZChannel.DisabledLinkColor = System.Drawing.Color.White;
+            this.linkBioZChannel.Font = new System.Drawing.Font("Calibri", 12F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+            this.linkBioZChannel.LinkBehavior = System.Windows.Forms.LinkBehavior.NeverUnderline;
+            this.linkBioZChannel.LinkColor = System.Drawing.Color.FromArgb(((int)(((byte)(0)))), ((int)(((byte)(178)))), ((int)(((byte)(169)))));
+            this.linkBioZChannel.Location = new System.Drawing.Point(450, 279);
+            this.linkBioZChannel.Name = "linkBioZChannel";
+            this.linkBioZChannel.Size = new System.Drawing.Size(98, 19);
+            this.linkBioZChannel.TabIndex = 6;
+            this.linkBioZChannel.TabStop = true;
+            this.linkBioZChannel.Text = "BioZ Channel";
+            this.linkBioZChannel.LinkClicked += new System.Windows.Forms.LinkLabelLinkClickedEventHandler(this.linkBioZChannel_LinkClicked);
+            // 
+            // linkEcgChannel
+            // 
+            this.linkEcgChannel.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) 
+            | System.Windows.Forms.AnchorStyles.Left) 
+            | System.Windows.Forms.AnchorStyles.Right)));
+            this.linkEcgChannel.AutoSize = true;
+            this.linkEcgChannel.Font = new System.Drawing.Font("Calibri", 12F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+            this.linkEcgChannel.LinkBehavior = System.Windows.Forms.LinkBehavior.NeverUnderline;
+            this.linkEcgChannel.LinkColor = System.Drawing.Color.FromArgb(((int)(((byte)(0)))), ((int)(((byte)(178)))), ((int)(((byte)(169)))));
+            this.linkEcgChannel.Location = new System.Drawing.Point(453, 129);
+            this.linkEcgChannel.Name = "linkEcgChannel";
+            this.linkEcgChannel.Size = new System.Drawing.Size(94, 19);
+            this.linkEcgChannel.TabIndex = 3;
+            this.linkEcgChannel.TabStop = true;
+            this.linkEcgChannel.Text = "ECG Channel";
+            this.linkEcgChannel.LinkClicked += new System.Windows.Forms.LinkLabelLinkClickedEventHandler(this.linkEcgChannel_LinkClicked);
+            // 
+            // linkPaceChannel
+            // 
+            this.linkPaceChannel.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) 
+            | System.Windows.Forms.AnchorStyles.Left) 
+            | System.Windows.Forms.AnchorStyles.Right)));
+            this.linkPaceChannel.AutoSize = true;
+            this.linkPaceChannel.DisabledLinkColor = System.Drawing.Color.White;
+            this.linkPaceChannel.Font = new System.Drawing.Font("Calibri", 12F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+            this.linkPaceChannel.LinkBehavior = System.Windows.Forms.LinkBehavior.NeverUnderline;
+            this.linkPaceChannel.LinkColor = System.Drawing.Color.FromArgb(((int)(((byte)(0)))), ((int)(((byte)(178)))), ((int)(((byte)(169)))));
+            this.linkPaceChannel.Location = new System.Drawing.Point(451, 187);
+            this.linkPaceChannel.Name = "linkPaceChannel";
+            this.linkPaceChannel.Size = new System.Drawing.Size(100, 19);
+            this.linkPaceChannel.TabIndex = 5;
+            this.linkPaceChannel.TabStop = true;
+            this.linkPaceChannel.Text = "Pace Channel";
+            this.linkPaceChannel.LinkClicked += new System.Windows.Forms.LinkLabelLinkClickedEventHandler(this.linkPaceChannel_LinkClicked);
+            // 
+            // picBlockDiagram
+            // 
+            this.picBlockDiagram.Dock = System.Windows.Forms.DockStyle.Fill;
+            this.picBlockDiagram.Image = global::HealthSensorPlatform.Properties.Resources.system_block_diagram;
+            this.picBlockDiagram.Location = new System.Drawing.Point(0, 0);
+            this.picBlockDiagram.Name = "picBlockDiagram";
+            this.picBlockDiagram.Size = new System.Drawing.Size(636, 587);
+            this.picBlockDiagram.SizeMode = System.Windows.Forms.PictureBoxSizeMode.Zoom;
+            this.picBlockDiagram.TabIndex = 0;
+            this.picBlockDiagram.TabStop = false;
+            // 
+            // tpOpticalSensor
+            // 
+            this.tpOpticalSensor.Controls.Add(this.opticalView1);
+            this.tpOpticalSensor.Location = new System.Drawing.Point(4, 26);
+            this.tpOpticalSensor.Name = "tpOpticalSensor";
+            this.tpOpticalSensor.Padding = new System.Windows.Forms.Padding(3);
+            this.tpOpticalSensor.Size = new System.Drawing.Size(953, 606);
+            this.tpOpticalSensor.TabIndex = 6;
+            this.tpOpticalSensor.Text = "Optical";
+            this.tpOpticalSensor.UseVisualStyleBackColor = true;
+            // 
+            // opticalView1
+            // 
+            this.opticalView1.BackColor = System.Drawing.Color.White;
+            this.opticalView1.Connected = false;
+            this.opticalView1.Dock = System.Windows.Forms.DockStyle.Fill;
+            this.opticalView1.Location = new System.Drawing.Point(3, 3);
+            this.opticalView1.Margin = new System.Windows.Forms.Padding(4);
+            this.opticalView1.Name = "opticalView1";
+            this.opticalView1.Size = new System.Drawing.Size(947, 600);
+            this.opticalView1.TabIndex = 0;
+            // 
+            // tpTemperature
+            // 
+            this.tpTemperature.Controls.Add(this.temperatureView1);
+            this.tpTemperature.Location = new System.Drawing.Point(4, 26);
+            this.tpTemperature.Name = "tpTemperature";
+            this.tpTemperature.Padding = new System.Windows.Forms.Padding(3);
+            this.tpTemperature.Size = new System.Drawing.Size(953, 606);
+            this.tpTemperature.TabIndex = 12;
+            this.tpTemperature.Text = "Temperature";
+            this.tpTemperature.UseVisualStyleBackColor = true;
+            // 
+            // temperatureView1
+            // 
+            this.temperatureView1.BackColor = System.Drawing.Color.White;
+            this.temperatureView1.Connected = false;
+            this.temperatureView1.Dock = System.Windows.Forms.DockStyle.Fill;
+            this.temperatureView1.Location = new System.Drawing.Point(3, 3);
+            this.temperatureView1.Margin = new System.Windows.Forms.Padding(4);
+            this.temperatureView1.Name = "temperatureView1";
+            this.temperatureView1.RefreshRate = 10;
+            this.temperatureView1.Size = new System.Drawing.Size(947, 600);
+            this.temperatureView1.TabIndex = 0;
+            // 
+            // tpMAX30001EcgChannel
+            // 
+            this.tpMAX30001EcgChannel.Controls.Add(this.cboEnRToR);
+            this.tpMAX30001EcgChannel.Controls.Add(this.lblEnRToR);
+            this.tpMAX30001EcgChannel.Controls.Add(this.flowLayoutPanel1);
+            this.tpMAX30001EcgChannel.Location = new System.Drawing.Point(4, 26);
+            this.tpMAX30001EcgChannel.Name = "tpMAX30001EcgChannel";
+            this.tpMAX30001EcgChannel.Size = new System.Drawing.Size(953, 606);
+            this.tpMAX30001EcgChannel.TabIndex = 7;
+            this.tpMAX30001EcgChannel.Text = "ECG Channel";
+            this.tpMAX30001EcgChannel.UseVisualStyleBackColor = true;
+            // 
+            // cboEnRToR
+            // 
+            this.cboEnRToR.BackColor = System.Drawing.Color.White;
+            this.cboEnRToR.DropDownHeight = 200;
+            this.cboEnRToR.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
+            this.cboEnRToR.DropDownWidth = 95;
+            this.cboEnRToR.Location = new System.Drawing.Point(480, 506);
+            this.cboEnRToR.Name = "cboEnRToR";
+            this.cboEnRToR.Size = new System.Drawing.Size(95, 21);
+            this.cboEnRToR.TabIndex = 5;
+            this.cboEnRToR.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
+            this.cboEnRToR.TextAlignDropDownList = System.Windows.Forms.HorizontalAlignment.Left;
+            this.cboEnRToR.Visible = false;
+            // 
+            // lblEnRToR
+            // 
+            this.lblEnRToR.AutoSize = true;
+            this.lblEnRToR.Location = new System.Drawing.Point(477, 488);
+            this.lblEnRToR.Name = "lblEnRToR";
+            this.lblEnRToR.Size = new System.Drawing.Size(140, 15);
+            this.lblEnRToR.TabIndex = 4;
+            this.lblEnRToR.Text = "R-to-R Detection Enable";
+            this.lblEnRToR.Visible = false;
+            // 
+            // flowLayoutPanel1
+            // 
+            this.flowLayoutPanel1.Controls.Add(this.panel1);
+            this.flowLayoutPanel1.Controls.Add(this.pnlEcgChannel);
+            this.flowLayoutPanel1.Controls.Add(this.grpRToR);
+            this.flowLayoutPanel1.Dock = System.Windows.Forms.DockStyle.Fill;
+            this.flowLayoutPanel1.Location = new System.Drawing.Point(0, 0);
+            this.flowLayoutPanel1.Name = "flowLayoutPanel1";
+            this.flowLayoutPanel1.Size = new System.Drawing.Size(953, 606);
+            this.flowLayoutPanel1.TabIndex = 48;
+            // 
+            // panel1
+            // 
+            this.panel1.Location = new System.Drawing.Point(3, 3);
+            this.panel1.Name = "panel1";
+            this.panel1.Size = new System.Drawing.Size(5, 274);
+            this.panel1.TabIndex = 48;
+            // 
+            // pnlEcgChannel
+            // 
+            this.pnlEcgChannel.Controls.Add(this.linkLabel1);
+            this.pnlEcgChannel.Controls.Add(this.label30);
+            this.pnlEcgChannel.Controls.Add(this.label28);
+            this.pnlEcgChannel.Controls.Add(this.lblFast);
+            this.pnlEcgChannel.Controls.Add(this.lblChannelGain);
+            this.pnlEcgChannel.Controls.Add(this.cboFastTh);
+            this.pnlEcgChannel.Controls.Add(this.lblSampleRate);
+            this.pnlEcgChannel.Controls.Add(this.lblFastTh);
+            this.pnlEcgChannel.Controls.Add(this.lblDlpf);
+            this.pnlEcgChannel.Controls.Add(this.lblDhpf);
+            this.pnlEcgChannel.Controls.Add(this.cboDhpf);
+            this.pnlEcgChannel.Controls.Add(this.cboFast);
+            this.pnlEcgChannel.Controls.Add(this.cboDlpf);
+            this.pnlEcgChannel.Controls.Add(this.cboChannelGain);
+            this.pnlEcgChannel.Controls.Add(this.cboSampleRate);
+            this.pnlEcgChannel.Controls.Add(this.picEcgChannel);
+            this.pnlEcgChannel.Location = new System.Drawing.Point(14, 3);
+            this.pnlEcgChannel.Name = "pnlEcgChannel";
+            this.pnlEcgChannel.Size = new System.Drawing.Size(894, 274);
+            this.pnlEcgChannel.TabIndex = 47;
+            // 
+            // linkLabel1
+            // 
+            this.linkLabel1.LinkBehavior = System.Windows.Forms.LinkBehavior.NeverUnderline;
+            this.linkLabel1.LinkColor = System.Drawing.Color.FromArgb(((int)(((byte)(0)))), ((int)(((byte)(178)))), ((int)(((byte)(169)))));
+            this.linkLabel1.Location = new System.Drawing.Point(56, 65);
+            this.linkLabel1.Name = "linkLabel1";
+            this.linkLabel1.Size = new System.Drawing.Size(60, 54);
+            this.linkLabel1.TabIndex = 44;
+            this.linkLabel1.TabStop = true;
+            this.linkLabel1.Text = "ECG Input MUX";
+            this.linkLabel1.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
+            this.linkLabel1.VisitedLinkColor = System.Drawing.Color.FromArgb(((int)(((byte)(0)))), ((int)(((byte)(178)))), ((int)(((byte)(169)))));
+            this.linkLabel1.LinkClicked += new System.Windows.Forms.LinkLabelLinkClickedEventHandler(this.linkLabel1_LinkClicked);
+            // 
+            // label30
+            // 
+            this.label30.AutoSize = true;
+            this.label30.Location = new System.Drawing.Point(783, 257);
+            this.label30.Name = "label30";
+            this.label30.Size = new System.Drawing.Size(108, 15);
+            this.label30.TabIndex = 46;
+            this.label30.Text = "* Power-on default";
+            // 
+            // label28
+            // 
+            this.label28.AutoSize = true;
+            this.label28.Location = new System.Drawing.Point(267, 138);
+            this.label28.Name = "label28";
+            this.label28.Size = new System.Drawing.Size(113, 15);
+            this.label28.TabIndex = 41;
+            this.label28.Text = "DC Offset Recovery";
+            // 
+            // lblFast
+            // 
+            this.lblFast.AutoSize = true;
+            this.lblFast.Location = new System.Drawing.Point(267, 157);
+            this.lblFast.Name = "lblFast";
+            this.lblFast.Size = new System.Drawing.Size(117, 15);
+            this.lblFast.TabIndex = 11;
+            this.lblFast.Text = "Fast Recovery Mode";
+            // 
+            // lblChannelGain
+            // 
+            this.lblChannelGain.AutoSize = true;
+            this.lblChannelGain.Location = new System.Drawing.Point(463, 157);
+            this.lblChannelGain.Name = "lblChannelGain";
+            this.lblChannelGain.Size = new System.Drawing.Size(83, 15);
+            this.lblChannelGain.TabIndex = 12;
+            this.lblChannelGain.Text = "Channel Gain";
+            // 
+            // cboFastTh
+            // 
+            this.cboFastTh.BackColor = System.Drawing.Color.White;
+            this.cboFastTh.DropDownHeight = 200;
+            this.cboFastTh.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
+            this.cboFastTh.DropDownWidth = 162;
+            this.cboFastTh.Location = new System.Drawing.Point(270, 221);
+            this.cboFastTh.Name = "cboFastTh";
+            this.cboFastTh.Size = new System.Drawing.Size(162, 21);
+            this.cboFastTh.TabIndex = 43;
+            this.cboFastTh.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
+            this.cboFastTh.TextAlignDropDownList = System.Windows.Forms.HorizontalAlignment.Left;
+            // 
+            // lblSampleRate
+            // 
+            this.lblSampleRate.AutoSize = true;
+            this.lblSampleRate.Location = new System.Drawing.Point(581, 157);
+            this.lblSampleRate.Name = "lblSampleRate";
+            this.lblSampleRate.Size = new System.Drawing.Size(79, 15);
+            this.lblSampleRate.TabIndex = 13;
+            this.lblSampleRate.Text = "Sample Rate";
+            // 
+            // lblFastTh
+            // 
+            this.lblFastTh.AutoSize = true;
+            this.lblFastTh.Location = new System.Drawing.Point(267, 202);
+            this.lblFastTh.Name = "lblFastTh";
+            this.lblFastTh.Size = new System.Drawing.Size(143, 15);
+            this.lblFastTh.TabIndex = 42;
+            this.lblFastTh.Text = "Fast Recovery Threshold";
+            // 
+            // lblDlpf
+            // 
+            this.lblDlpf.AutoSize = true;
+            this.lblDlpf.Location = new System.Drawing.Point(713, 157);
+            this.lblDlpf.Name = "lblDlpf";
+            this.lblDlpf.Size = new System.Drawing.Size(102, 15);
+            this.lblDlpf.TabIndex = 14;
+            this.lblDlpf.Text = "Digital LPF Cutoff";
+            // 
+            // lblDhpf
+            // 
+            this.lblDhpf.AutoSize = true;
+            this.lblDhpf.Location = new System.Drawing.Point(713, 202);
+            this.lblDhpf.Name = "lblDhpf";
+            this.lblDhpf.Size = new System.Drawing.Size(104, 15);
+            this.lblDhpf.TabIndex = 15;
+            this.lblDhpf.Text = "Digital HPF Cutoff";
+            // 
+            // cboDhpf
+            // 
+            this.cboDhpf.BackColor = System.Drawing.Color.White;
+            this.cboDhpf.DropDownHeight = 200;
+            this.cboDhpf.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
+            this.cboDhpf.DropDownWidth = 118;
+            this.cboDhpf.Location = new System.Drawing.Point(716, 220);
+            this.cboDhpf.Name = "cboDhpf";
+            this.cboDhpf.Size = new System.Drawing.Size(118, 21);
+            this.cboDhpf.TabIndex = 20;
+            this.cboDhpf.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
+            this.cboDhpf.TextAlignDropDownList = System.Windows.Forms.HorizontalAlignment.Left;
+            // 
+            // cboFast
+            // 
+            this.cboFast.BackColor = System.Drawing.Color.White;
+            this.cboFast.DropDownHeight = 200;
+            this.cboFast.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
+            this.cboFast.DropDownWidth = 163;
+            this.cboFast.Location = new System.Drawing.Point(269, 176);
+            this.cboFast.Name = "cboFast";
+            this.cboFast.Size = new System.Drawing.Size(163, 21);
+            this.cboFast.TabIndex = 16;
+            this.cboFast.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
+            this.cboFast.TextAlignDropDownList = System.Windows.Forms.HorizontalAlignment.Left;
+            // 
+            // cboDlpf
+            // 
+            this.cboDlpf.BackColor = System.Drawing.Color.White;
+            this.cboDlpf.DropDownHeight = 200;
+            this.cboDlpf.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
+            this.cboDlpf.DropDownWidth = 118;
+            this.cboDlpf.Location = new System.Drawing.Point(716, 175);
+            this.cboDlpf.Name = "cboDlpf";
+            this.cboDlpf.Size = new System.Drawing.Size(118, 21);
+            this.cboDlpf.TabIndex = 19;
+            this.cboDlpf.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
+            this.cboDlpf.TextAlignDropDownList = System.Windows.Forms.HorizontalAlignment.Left;
+            // 
+            // cboChannelGain
+            // 
+            this.cboChannelGain.BackColor = System.Drawing.Color.White;
+            this.cboChannelGain.DropDownHeight = 200;
+            this.cboChannelGain.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
+            this.cboChannelGain.DropDownWidth = 95;
+            this.cboChannelGain.Location = new System.Drawing.Point(463, 175);
+            this.cboChannelGain.Name = "cboChannelGain";
+            this.cboChannelGain.Size = new System.Drawing.Size(95, 21);
+            this.cboChannelGain.TabIndex = 17;
+            this.cboChannelGain.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
+            this.cboChannelGain.TextAlignDropDownList = System.Windows.Forms.HorizontalAlignment.Left;
+            // 
+            // cboSampleRate
+            // 
+            this.cboSampleRate.BackColor = System.Drawing.Color.White;
+            this.cboSampleRate.DropDownHeight = 200;
+            this.cboSampleRate.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
+            this.cboSampleRate.DropDownWidth = 95;
+            this.cboSampleRate.Location = new System.Drawing.Point(581, 175);
+            this.cboSampleRate.Name = "cboSampleRate";
+            this.cboSampleRate.Size = new System.Drawing.Size(95, 21);
+            this.cboSampleRate.TabIndex = 18;
+            this.cboSampleRate.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
+            this.cboSampleRate.TextAlignDropDownList = System.Windows.Forms.HorizontalAlignment.Left;
+            this.cboSampleRate.SelectedIndexChanged += new System.EventHandler(this.cboSampleRate_SelectedIndexChanged);
+            // 
+            // picEcgChannel
+            // 
+            this.picEcgChannel.BackgroundImageLayout = System.Windows.Forms.ImageLayout.None;
+            this.picEcgChannel.Dock = System.Windows.Forms.DockStyle.Fill;
+            this.picEcgChannel.Image = global::HealthSensorPlatform.Properties.Resources.ecg_channel_block;
+            this.picEcgChannel.Location = new System.Drawing.Point(0, 0);
+            this.picEcgChannel.Name = "picEcgChannel";
+            this.picEcgChannel.Size = new System.Drawing.Size(894, 274);
+            this.picEcgChannel.SizeMode = System.Windows.Forms.PictureBoxSizeMode.Zoom;
+            this.picEcgChannel.TabIndex = 0;
+            this.picEcgChannel.TabStop = false;
+            // 
+            // grpRToR
+            // 
+            this.grpRToR.BackgroundColor = System.Drawing.Color.White;
+            this.grpRToR.Controls.Add(this.cboRRRavg);
+            this.grpRToR.Controls.Add(this.lblRRRavg);
+            this.grpRToR.Controls.Add(this.cboRRHoff);
+            this.grpRToR.Controls.Add(this.lblRRHoff);
+            this.grpRToR.Controls.Add(this.cboRRRhsf);
+            this.grpRToR.Controls.Add(this.lblRRRhsf);
+            this.grpRToR.Controls.Add(this.cboRRPtsf);
+            this.grpRToR.Controls.Add(this.lblRRPtsf);
+            this.grpRToR.Controls.Add(this.cboRRPavg);
+            this.grpRToR.Controls.Add(this.lblRRPavg);
+            this.grpRToR.Controls.Add(this.cboRRGain);
+            this.grpRToR.Controls.Add(this.lblRRGain);
+            this.grpRToR.Controls.Add(this.cboRRWndw);
+            this.grpRToR.Controls.Add(this.lblRRWndw);
+            this.grpRToR.Location = new System.Drawing.Point(3, 283);
+            this.grpRToR.Name = "grpRToR";
+            this.grpRToR.Size = new System.Drawing.Size(468, 220);
+            this.grpRToR.TabIndex = 45;
+            this.grpRToR.TabStop = false;
+            this.grpRToR.Text = "R-to-R";
+            // 
+            // cboRRRavg
+            // 
+            this.cboRRRavg.BackColor = System.Drawing.Color.White;
+            this.cboRRRavg.DropDownHeight = 200;
+            this.cboRRRavg.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
+            this.cboRRRavg.DropDownWidth = 95;
+            this.cboRRRavg.Location = new System.Drawing.Point(200, 182);
+            this.cboRRRavg.Name = "cboRRRavg";
+            this.cboRRRavg.Size = new System.Drawing.Size(95, 21);
+            this.cboRRRavg.TabIndex = 15;
+            this.cboRRRavg.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
+            this.cboRRRavg.TextAlignDropDownList = System.Windows.Forms.HorizontalAlignment.Left;
+            // 
+            // lblRRRavg
+            // 
+            this.lblRRRavg.AutoSize = true;
+            this.lblRRRavg.Location = new System.Drawing.Point(197, 164);
+            this.lblRRRavg.Name = "lblRRRavg";
+            this.lblRRRavg.Size = new System.Drawing.Size(180, 15);
+            this.lblRRRavg.TabIndex = 14;
+            this.lblRRRavg.Text = "Interval Averaging Weight Factor";
+            // 
+            // cboRRHoff
+            // 
+            this.cboRRHoff.BackColor = System.Drawing.Color.White;
+            this.cboRRHoff.DropDownHeight = 200;
+            this.cboRRHoff.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
+            this.cboRRHoff.DropDownWidth = 95;
+            this.cboRRHoff.Location = new System.Drawing.Point(14, 140);
+            this.cboRRHoff.Name = "cboRRHoff";
+            this.cboRRHoff.Size = new System.Drawing.Size(95, 21);
+            this.cboRRHoff.TabIndex = 13;
+            this.cboRRHoff.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
+            this.cboRRHoff.TextAlignDropDownList = System.Windows.Forms.HorizontalAlignment.Left;
+            // 
+            // lblRRHoff
+            // 
+            this.lblRRHoff.AutoSize = true;
+            this.lblRRHoff.Location = new System.Drawing.Point(11, 122);
+            this.lblRRHoff.Name = "lblRRHoff";
+            this.lblRRHoff.Size = new System.Drawing.Size(105, 15);
+            this.lblRRHoff.TabIndex = 12;
+            this.lblRRHoff.Text = "Minimum Hold Off";
+            // 
+            // cboRRRhsf
+            // 
+            this.cboRRRhsf.BackColor = System.Drawing.Color.White;
+            this.cboRRRhsf.DropDownHeight = 200;
+            this.cboRRRhsf.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
+            this.cboRRRhsf.DropDownWidth = 95;
+            this.cboRRRhsf.Location = new System.Drawing.Point(200, 140);
+            this.cboRRRhsf.Name = "cboRRRhsf";
+            this.cboRRRhsf.Size = new System.Drawing.Size(95, 21);
+            this.cboRRRhsf.TabIndex = 11;
+            this.cboRRRhsf.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
+            this.cboRRRhsf.TextAlignDropDownList = System.Windows.Forms.HorizontalAlignment.Left;
+            // 
+            // lblRRRhsf
+            // 
+            this.lblRRRhsf.AutoSize = true;
+            this.lblRRRhsf.Location = new System.Drawing.Point(197, 122);
+            this.lblRRRhsf.Name = "lblRRRhsf";
+            this.lblRRRhsf.Size = new System.Drawing.Size(174, 15);
+            this.lblRRRhsf.TabIndex = 10;
+            this.lblRRRhsf.Text = "Interval Hold Off Scaling Factor";
+            // 
+            // cboRRPtsf
+            // 
+            this.cboRRPtsf.BackColor = System.Drawing.Color.White;
+            this.cboRRPtsf.DropDownHeight = 200;
+            this.cboRRPtsf.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
+            this.cboRRPtsf.DropDownWidth = 95;
+            this.cboRRPtsf.Location = new System.Drawing.Point(200, 98);
+            this.cboRRPtsf.Name = "cboRRPtsf";
+            this.cboRRPtsf.Size = new System.Drawing.Size(95, 21);
+            this.cboRRPtsf.TabIndex = 9;
+            this.cboRRPtsf.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
+            this.cboRRPtsf.TextAlignDropDownList = System.Windows.Forms.HorizontalAlignment.Left;
+            // 
+            // lblRRPtsf
+            // 
+            this.lblRRPtsf.AutoSize = true;
+            this.lblRRPtsf.Location = new System.Drawing.Point(197, 80);
+            this.lblRRPtsf.Name = "lblRRPtsf";
+            this.lblRRPtsf.Size = new System.Drawing.Size(175, 15);
+            this.lblRRPtsf.TabIndex = 8;
+            this.lblRRPtsf.Text = "Peak Threshold Scaling Factor";
+            // 
+            // cboRRPavg
+            // 
+            this.cboRRPavg.BackColor = System.Drawing.Color.White;
+            this.cboRRPavg.DropDownHeight = 200;
+            this.cboRRPavg.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
+            this.cboRRPavg.DropDownWidth = 95;
+            this.cboRRPavg.Location = new System.Drawing.Point(200, 56);
+            this.cboRRPavg.Name = "cboRRPavg";
+            this.cboRRPavg.Size = new System.Drawing.Size(95, 21);
+            this.cboRRPavg.TabIndex = 7;
+            this.cboRRPavg.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
+            this.cboRRPavg.TextAlignDropDownList = System.Windows.Forms.HorizontalAlignment.Left;
+            // 
+            // lblRRPavg
+            // 
+            this.lblRRPavg.AutoSize = true;
+            this.lblRRPavg.Location = new System.Drawing.Point(197, 38);
+            this.lblRRPavg.Name = "lblRRPavg";
+            this.lblRRPavg.Size = new System.Drawing.Size(169, 15);
+            this.lblRRPavg.TabIndex = 6;
+            this.lblRRPavg.Text = "Peak Averaging Weight Factor";
+            // 
+            // cboRRGain
+            // 
+            this.cboRRGain.BackColor = System.Drawing.Color.White;
+            this.cboRRGain.DropDownHeight = 200;
+            this.cboRRGain.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
+            this.cboRRGain.DropDownWidth = 95;
+            this.cboRRGain.Location = new System.Drawing.Point(14, 56);
+            this.cboRRGain.Name = "cboRRGain";
+            this.cboRRGain.Size = new System.Drawing.Size(95, 21);
+            this.cboRRGain.TabIndex = 3;
+            this.cboRRGain.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
+            this.cboRRGain.TextAlignDropDownList = System.Windows.Forms.HorizontalAlignment.Left;
+            // 
+            // lblRRGain
+            // 
+            this.lblRRGain.AutoSize = true;
+            this.lblRRGain.Location = new System.Drawing.Point(11, 38);
+            this.lblRRGain.Name = "lblRRGain";
+            this.lblRRGain.Size = new System.Drawing.Size(33, 15);
+            this.lblRRGain.TabIndex = 2;
+            this.lblRRGain.Text = "Gain";
+            // 
+            // cboRRWndw
+            // 
+            this.cboRRWndw.BackColor = System.Drawing.Color.White;
+            this.cboRRWndw.DropDownHeight = 200;
+            this.cboRRWndw.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
+            this.cboRRWndw.DropDownWidth = 95;
+            this.cboRRWndw.Location = new System.Drawing.Point(14, 98);
+            this.cboRRWndw.Name = "cboRRWndw";
+            this.cboRRWndw.Size = new System.Drawing.Size(95, 21);
+            this.cboRRWndw.TabIndex = 1;
+            this.cboRRWndw.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
+            this.cboRRWndw.TextAlignDropDownList = System.Windows.Forms.HorizontalAlignment.Left;
+            this.cboRRWndw.SelectedIndexChanged += new System.EventHandler(this.cboRRWndw_SelectedIndexChanged);
+            // 
+            // lblRRWndw
+            // 
+            this.lblRRWndw.AutoSize = true;
+            this.lblRRWndw.Location = new System.Drawing.Point(11, 80);
+            this.lblRRWndw.Name = "lblRRWndw";
+            this.lblRRWndw.Size = new System.Drawing.Size(141, 15);
+            this.lblRRWndw.TabIndex = 0;
+            this.lblRRWndw.Text = "Window Averaging Width";
+            // 
+            // tpMAX30001InputMux
+            // 
+            this.tpMAX30001InputMux.Controls.Add(this.pnlEcgMux);
+            this.tpMAX30001InputMux.Controls.Add(this.pnlMAX30001Global);
+            this.tpMAX30001InputMux.Location = new System.Drawing.Point(4, 26);
+            this.tpMAX30001InputMux.Name = "tpMAX30001InputMux";
+            this.tpMAX30001InputMux.Size = new System.Drawing.Size(953, 606);
+            this.tpMAX30001InputMux.TabIndex = 13;
+            this.tpMAX30001InputMux.Text = "ECG MUX";
+            this.tpMAX30001InputMux.UseVisualStyleBackColor = true;
+            // 
+            // pnlEcgMux
+            // 
+            this.pnlEcgMux.Controls.Add(this.label26);
+            this.pnlEcgMux.Controls.Add(this.lblEmuxEnUlpLon);
+            this.pnlEcgMux.Controls.Add(this.label32);
+            this.pnlEcgMux.Controls.Add(this.cboCalEnVcal);
+            this.pnlEcgMux.Controls.Add(this.cboCalVmode);
+            this.pnlEcgMux.Controls.Add(this.cboEmuxEnUlpLon);
+            this.pnlEcgMux.Controls.Add(this.cboDcloffImag);
+            this.pnlEcgMux.Controls.Add(this.cboEmuxPol);
+            this.pnlEcgMux.Controls.Add(this.cboEmuxCalNSel);
+            this.pnlEcgMux.Controls.Add(this.lblEmuxPol);
+            this.pnlEcgMux.Controls.Add(this.lblEmuxCalNSel);
+            this.pnlEcgMux.Controls.Add(this.lblCalEnVcal);
+            this.pnlEcgMux.Controls.Add(this.cboEmuxCalPSel);
+            this.pnlEcgMux.Controls.Add(this.lblCalVMode);
+            this.pnlEcgMux.Controls.Add(this.lblEmuxCalPSel);
+            this.pnlEcgMux.Controls.Add(this.lblDcloffImag);
+            this.pnlEcgMux.Controls.Add(this.cboCalVmag);
+            this.pnlEcgMux.Controls.Add(this.cboRbiasn);
+            this.pnlEcgMux.Controls.Add(this.cboCalFifty);
+            this.pnlEcgMux.Controls.Add(this.lblRbiasn);
+            this.pnlEcgMux.Controls.Add(this.cboCalThigh);
+            this.pnlEcgMux.Controls.Add(this.cboRbiasp);
+            this.pnlEcgMux.Controls.Add(this.cboCalFcal);
+            this.pnlEcgMux.Controls.Add(this.lblRbiasp);
+            this.pnlEcgMux.Controls.Add(this.lblCalFifty);
+            this.pnlEcgMux.Controls.Add(this.cboRbiasv);
+            this.pnlEcgMux.Controls.Add(this.lblCalTHigh);
+            this.pnlEcgMux.Controls.Add(this.lblRbiasv);
+            this.pnlEcgMux.Controls.Add(this.lblCalFreq);
+            this.pnlEcgMux.Controls.Add(this.cboEnRbias);
+            this.pnlEcgMux.Controls.Add(this.lblCalVmag);
+            this.pnlEcgMux.Controls.Add(this.lblEnRbias);
+            this.pnlEcgMux.Controls.Add(this.lblEmuxOpenp);
+            this.pnlEcgMux.Controls.Add(this.lblDcloffVth);
+            this.pnlEcgMux.Controls.Add(this.lblEmuxOpenn);
+            this.pnlEcgMux.Controls.Add(this.cboDcloffVth);
+            this.pnlEcgMux.Controls.Add(this.cboEmuxOpenp);
+            this.pnlEcgMux.Controls.Add(this.cboDcloffIpol);
+            this.pnlEcgMux.Controls.Add(this.cboEmuxOpenn);
+            this.pnlEcgMux.Controls.Add(this.lblDcloffIpol);
+            this.pnlEcgMux.Controls.Add(this.lblEnDcloff);
+            this.pnlEcgMux.Controls.Add(this.cboEnDcloff);
+            this.pnlEcgMux.Controls.Add(this.picECGLeadConfig);
+            this.pnlEcgMux.Controls.Add(this.picSw1);
+            this.pnlEcgMux.Controls.Add(this.picSw2);
+            this.pnlEcgMux.Controls.Add(this.pictureBox1);
+            this.pnlEcgMux.Controls.Add(this.picSw3);
+            this.pnlEcgMux.Controls.Add(this.picSw4);
+            this.pnlEcgMux.Controls.Add(this.picSw5);
+            this.pnlEcgMux.Controls.Add(this.picSw6);
+            this.pnlEcgMux.Controls.Add(this.picSw7);
+            this.pnlEcgMux.Controls.Add(this.picSw8);
+            this.pnlEcgMux.Controls.Add(this.picSw9);
+            this.pnlEcgMux.Controls.Add(this.picSw10);
+            this.pnlEcgMux.Controls.Add(this.picSw11);
+            this.pnlEcgMux.Controls.Add(this.picSw12);
+            this.pnlEcgMux.Controls.Add(this.picSw13);
+            this.pnlEcgMux.Controls.Add(this.picSw14);
+            this.pnlEcgMux.Location = new System.Drawing.Point(0, 0);
+            this.pnlEcgMux.Margin = new System.Windows.Forms.Padding(2);
+            this.pnlEcgMux.Name = "pnlEcgMux";
+            this.pnlEcgMux.Size = new System.Drawing.Size(942, 496);
+            this.pnlEcgMux.TabIndex = 88;
+            // 
+            // label26
+            // 
+            this.label26.AutoSize = true;
+            this.label26.Location = new System.Drawing.Point(54, 479);
+            this.label26.Name = "label26";
+            this.label26.Size = new System.Drawing.Size(361, 15);
+            this.label26.TabIndex = 83;
+            this.label26.Text = "(Options with grey background apply to both ECG and BioZ MUX.)";
+            // 
+            // lblEmuxEnUlpLon
+            // 
+            this.lblEmuxEnUlpLon.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(240)))), ((int)(((byte)(240)))), ((int)(((byte)(240)))));
+            this.lblEmuxEnUlpLon.Location = new System.Drawing.Point(299, 321);
+            this.lblEmuxEnUlpLon.Name = "lblEmuxEnUlpLon";
+            this.lblEmuxEnUlpLon.Size = new System.Drawing.Size(93, 33);
+            this.lblEmuxEnUlpLon.TabIndex = 87;
+            this.lblEmuxEnUlpLon.Text = "Lead-On Check Enable";
+            // 
+            // label32
+            // 
+            this.label32.AutoSize = true;
+            this.label32.Location = new System.Drawing.Point(819, 479);
+            this.label32.Name = "label32";
+            this.label32.Size = new System.Drawing.Size(112, 15);
+            this.label32.TabIndex = 86;
+            this.label32.Text = "* Power-On Default";
+            // 
+            // cboCalEnVcal
+            // 
+            this.cboCalEnVcal.BackColor = System.Drawing.Color.White;
+            this.cboCalEnVcal.DropDownHeight = 200;
+            this.cboCalEnVcal.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
+            this.cboCalEnVcal.DropDownWidth = 97;
+            this.cboCalEnVcal.Location = new System.Drawing.Point(723, 257);
+            this.cboCalEnVcal.Name = "cboCalEnVcal";
+            this.cboCalEnVcal.Size = new System.Drawing.Size(97, 20);
+            this.cboCalEnVcal.TabIndex = 42;
+            this.cboCalEnVcal.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
+            this.cboCalEnVcal.TextAlignDropDownList = System.Windows.Forms.HorizontalAlignment.Left;
+            this.cboCalEnVcal.SelectedIndexChanged += new System.EventHandler(this.cboCalEnVcal_SelectedIndexChanged);
+            // 
+            // cboCalVmode
+            // 
+            this.cboCalVmode.BackColor = System.Drawing.Color.White;
+            this.cboCalVmode.DropDownHeight = 200;
+            this.cboCalVmode.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
+            this.cboCalVmode.DropDownWidth = 97;
+            this.cboCalVmode.Location = new System.Drawing.Point(723, 298);
+            this.cboCalVmode.Name = "cboCalVmode";
+            this.cboCalVmode.Size = new System.Drawing.Size(97, 20);
+            this.cboCalVmode.TabIndex = 43;
+            this.cboCalVmode.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
+            this.cboCalVmode.TextAlignDropDownList = System.Windows.Forms.HorizontalAlignment.Left;
+            // 
+            // cboEmuxEnUlpLon
+            // 
+            this.cboEmuxEnUlpLon.BackColor = System.Drawing.Color.White;
+            this.cboEmuxEnUlpLon.DropDownHeight = 200;
+            this.cboEmuxEnUlpLon.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
+            this.cboEmuxEnUlpLon.DropDownWidth = 90;
+            this.cboEmuxEnUlpLon.Location = new System.Drawing.Point(301, 358);
+            this.cboEmuxEnUlpLon.Name = "cboEmuxEnUlpLon";
+            this.cboEmuxEnUlpLon.Size = new System.Drawing.Size(90, 20);
+            this.cboEmuxEnUlpLon.TabIndex = 84;
+            this.cboEmuxEnUlpLon.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
+            this.cboEmuxEnUlpLon.TextAlignDropDownList = System.Windows.Forms.HorizontalAlignment.Left;
+            this.cboEmuxEnUlpLon.SelectedIndexChanged += new System.EventHandler(this.cboEmuxEnUlpLon_SelectedIndexChanged);
+            // 
+            // cboDcloffImag
+            // 
+            this.cboDcloffImag.BackColor = System.Drawing.Color.White;
+            this.cboDcloffImag.DropDownHeight = 200;
+            this.cboDcloffImag.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
+            this.cboDcloffImag.DropDownWidth = 129;
+            this.cboDcloffImag.Location = new System.Drawing.Point(102, 380);
+            this.cboDcloffImag.Name = "cboDcloffImag";
+            this.cboDcloffImag.Size = new System.Drawing.Size(129, 20);
+            this.cboDcloffImag.TabIndex = 44;
+            this.cboDcloffImag.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
+            this.cboDcloffImag.TextAlignDropDownList = System.Windows.Forms.HorizontalAlignment.Left;
+            // 
+            // cboEmuxPol
+            // 
+            this.cboEmuxPol.BackColor = System.Drawing.Color.White;
+            this.cboEmuxPol.DropDownHeight = 200;
+            this.cboEmuxPol.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
+            this.cboEmuxPol.DropDownWidth = 102;
+            this.cboEmuxPol.Location = new System.Drawing.Point(424, 301);
+            this.cboEmuxPol.Name = "cboEmuxPol";
+            this.cboEmuxPol.Size = new System.Drawing.Size(102, 21);
+            this.cboEmuxPol.TabIndex = 45;
+            this.cboEmuxPol.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
+            this.cboEmuxPol.TextAlignDropDownList = System.Windows.Forms.HorizontalAlignment.Left;
+            this.cboEmuxPol.SelectedIndexChanged += new System.EventHandler(this.cboEmuxPol_SelectedIndexChanged);
+            // 
+            // cboEmuxCalNSel
+            // 
+            this.cboEmuxCalNSel.BackColor = System.Drawing.Color.White;
+            this.cboEmuxCalNSel.DropDownHeight = 200;
+            this.cboEmuxCalNSel.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
+            this.cboEmuxCalNSel.DropDownWidth = 95;
+            this.cboEmuxCalNSel.Location = new System.Drawing.Point(723, 122);
+            this.cboEmuxCalNSel.Name = "cboEmuxCalNSel";
+            this.cboEmuxCalNSel.Size = new System.Drawing.Size(95, 21);
+            this.cboEmuxCalNSel.TabIndex = 82;
+            this.cboEmuxCalNSel.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
+            this.cboEmuxCalNSel.TextAlignDropDownList = System.Windows.Forms.HorizontalAlignment.Left;
+            this.cboEmuxCalNSel.SelectedIndexChanged += new System.EventHandler(this.cboEmuxCalNSel_SelectedIndexChanged);
+            // 
+            // lblEmuxPol
+            // 
+            this.lblEmuxPol.AutoSize = true;
+            this.lblEmuxPol.BackColor = System.Drawing.Color.White;
+            this.lblEmuxPol.Location = new System.Drawing.Point(424, 285);
+            this.lblEmuxPol.Name = "lblEmuxPol";
+            this.lblEmuxPol.Size = new System.Drawing.Size(96, 15);
+            this.lblEmuxPol.TabIndex = 46;
+            this.lblEmuxPol.Text = "ECGP/N Polarity";
+            // 
+            // lblEmuxCalNSel
+            // 
+            this.lblEmuxCalNSel.AutoSize = true;
+            this.lblEmuxCalNSel.BackColor = System.Drawing.Color.White;
+            this.lblEmuxCalNSel.Location = new System.Drawing.Point(720, 103);
+            this.lblEmuxCalNSel.Name = "lblEmuxCalNSel";
+            this.lblEmuxCalNSel.Size = new System.Drawing.Size(105, 15);
+            this.lblEmuxCalNSel.TabIndex = 81;
+            this.lblEmuxCalNSel.Text = "ECGN Calibration";
+            // 
+            // lblCalEnVcal
+            // 
+            this.lblCalEnVcal.AutoSize = true;
+            this.lblCalEnVcal.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(240)))), ((int)(((byte)(240)))), ((int)(((byte)(240)))));
+            this.lblCalEnVcal.Location = new System.Drawing.Point(720, 238);
+            this.lblCalEnVcal.Name = "lblCalEnVcal";
+            this.lblCalEnVcal.Size = new System.Drawing.Size(109, 15);
+            this.lblCalEnVcal.TabIndex = 47;
+            this.lblCalEnVcal.Text = "Calibration Enable";
+            // 
+            // cboEmuxCalPSel
+            // 
+            this.cboEmuxCalPSel.BackColor = System.Drawing.Color.White;
+            this.cboEmuxCalPSel.DropDownHeight = 200;
+            this.cboEmuxCalPSel.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
+            this.cboEmuxCalPSel.DropDownWidth = 95;
+            this.cboEmuxCalPSel.Location = new System.Drawing.Point(723, 79);
+            this.cboEmuxCalPSel.Name = "cboEmuxCalPSel";
+            this.cboEmuxCalPSel.Size = new System.Drawing.Size(95, 21);
+            this.cboEmuxCalPSel.TabIndex = 80;
+            this.cboEmuxCalPSel.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
+            this.cboEmuxCalPSel.TextAlignDropDownList = System.Windows.Forms.HorizontalAlignment.Left;
+            this.cboEmuxCalPSel.SelectedIndexChanged += new System.EventHandler(this.cboEmuxCalPSel_SelectedIndexChanged);
+            // 
+            // lblCalVMode
+            // 
+            this.lblCalVMode.AutoSize = true;
+            this.lblCalVMode.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(240)))), ((int)(((byte)(240)))), ((int)(((byte)(240)))));
+            this.lblCalVMode.Location = new System.Drawing.Point(720, 280);
+            this.lblCalVMode.Name = "lblCalVMode";
+            this.lblCalVMode.Size = new System.Drawing.Size(91, 15);
+            this.lblCalVMode.TabIndex = 48;
+            this.lblCalVMode.Text = "Mode Selection";
+            // 
+            // lblEmuxCalPSel
+            // 
+            this.lblEmuxCalPSel.AutoSize = true;
+            this.lblEmuxCalPSel.BackColor = System.Drawing.Color.White;
+            this.lblEmuxCalPSel.Location = new System.Drawing.Point(720, 60);
+            this.lblEmuxCalPSel.Name = "lblEmuxCalPSel";
+            this.lblEmuxCalPSel.Size = new System.Drawing.Size(104, 15);
+            this.lblEmuxCalPSel.TabIndex = 79;
+            this.lblEmuxCalPSel.Text = "ECGP Calibration";
+            // 
+            // lblDcloffImag
+            // 
+            this.lblDcloffImag.AutoSize = true;
+            this.lblDcloffImag.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(240)))), ((int)(((byte)(240)))), ((int)(((byte)(240)))));
+            this.lblDcloffImag.Location = new System.Drawing.Point(99, 362);
+            this.lblDcloffImag.Name = "lblDcloffImag";
+            this.lblDcloffImag.Size = new System.Drawing.Size(108, 15);
+            this.lblDcloffImag.TabIndex = 49;
+            this.lblDcloffImag.Text = "Current Magnitude";
+            // 
+            // cboCalVmag
+            // 
+            this.cboCalVmag.BackColor = System.Drawing.Color.White;
+            this.cboCalVmag.DropDownHeight = 200;
+            this.cboCalVmag.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
+            this.cboCalVmag.DropDownWidth = 97;
+            this.cboCalVmag.Location = new System.Drawing.Point(723, 339);
+            this.cboCalVmag.Name = "cboCalVmag";
+            this.cboCalVmag.Size = new System.Drawing.Size(97, 21);
+            this.cboCalVmag.TabIndex = 50;
+            this.cboCalVmag.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
+            this.cboCalVmag.TextAlignDropDownList = System.Windows.Forms.HorizontalAlignment.Left;
+            // 
+            // cboRbiasn
+            // 
+            this.cboRbiasn.BackColor = System.Drawing.Color.White;
+            this.cboRbiasn.DropDownHeight = 200;
+            this.cboRbiasn.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
+            this.cboRbiasn.DropDownWidth = 116;
+            this.cboRbiasn.Location = new System.Drawing.Point(548, 423);
+            this.cboRbiasn.Name = "cboRbiasn";
+            this.cboRbiasn.Size = new System.Drawing.Size(116, 20);
+            this.cboRbiasn.TabIndex = 77;
+            this.cboRbiasn.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
+            this.cboRbiasn.TextAlignDropDownList = System.Windows.Forms.HorizontalAlignment.Left;
+            this.cboRbiasn.SelectedIndexChanged += new System.EventHandler(this.cboRbiasn_SelectedIndexChanged);
+            // 
+            // cboCalFifty
+            // 
+            this.cboCalFifty.BackColor = System.Drawing.Color.White;
+            this.cboCalFifty.DropDownHeight = 200;
+            this.cboCalFifty.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
+            this.cboCalFifty.DropDownWidth = 95;
+            this.cboCalFifty.Location = new System.Drawing.Point(723, 422);
+            this.cboCalFifty.Name = "cboCalFifty";
+            this.cboCalFifty.Size = new System.Drawing.Size(95, 21);
+            this.cboCalFifty.TabIndex = 51;
+            this.cboCalFifty.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
+            this.cboCalFifty.TextAlignDropDownList = System.Windows.Forms.HorizontalAlignment.Left;
+            this.cboCalFifty.SelectedIndexChanged += new System.EventHandler(this.cboCalFifty_SelectedIndexChanged);
+            // 
+            // lblRbiasn
+            // 
+            this.lblRbiasn.AutoSize = true;
+            this.lblRbiasn.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(240)))), ((int)(((byte)(240)))), ((int)(((byte)(240)))));
+            this.lblRbiasn.Location = new System.Drawing.Point(548, 406);
+            this.lblRbiasn.Name = "lblRbiasn";
+            this.lblRbiasn.Size = new System.Drawing.Size(133, 15);
+            this.lblRbiasn.TabIndex = 76;
+            this.lblRbiasn.Text = "Neg. Input Bias Enable";
+            // 
+            // cboCalThigh
+            // 
+            this.cboCalThigh.BackColor = System.Drawing.Color.White;
+            this.cboCalThigh.DropDownHeight = 200;
+            this.cboCalThigh.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
+            this.cboCalThigh.DropDownWidth = 72;
+            this.cboCalThigh.Location = new System.Drawing.Point(824, 422);
+            this.cboCalThigh.Name = "cboCalThigh";
+            this.cboCalThigh.Size = new System.Drawing.Size(72, 21);
+            this.cboCalThigh.TabIndex = 52;
+            this.cboCalThigh.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
+            this.cboCalThigh.TextAlignDropDownList = System.Windows.Forms.HorizontalAlignment.Left;
+            // 
+            // cboRbiasp
+            // 
+            this.cboRbiasp.BackColor = System.Drawing.Color.White;
+            this.cboRbiasp.DropDownHeight = 200;
+            this.cboRbiasp.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
+            this.cboRbiasp.DropDownWidth = 116;
+            this.cboRbiasp.Location = new System.Drawing.Point(548, 380);
+            this.cboRbiasp.Name = "cboRbiasp";
+            this.cboRbiasp.Size = new System.Drawing.Size(116, 20);
+            this.cboRbiasp.TabIndex = 75;
+            this.cboRbiasp.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
+            this.cboRbiasp.TextAlignDropDownList = System.Windows.Forms.HorizontalAlignment.Left;
+            this.cboRbiasp.SelectedIndexChanged += new System.EventHandler(this.cboRbiasp_SelectedIndexChanged);
+            // 
+            // cboCalFcal
+            // 
+            this.cboCalFcal.BackColor = System.Drawing.Color.White;
+            this.cboCalFcal.DropDownHeight = 200;
+            this.cboCalFcal.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
+            this.cboCalFcal.DropDownWidth = 163;
+            this.cboCalFcal.Location = new System.Drawing.Point(723, 379);
+            this.cboCalFcal.Name = "cboCalFcal";
+            this.cboCalFcal.Size = new System.Drawing.Size(163, 21);
+            this.cboCalFcal.TabIndex = 53;
+            this.cboCalFcal.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
+            this.cboCalFcal.TextAlignDropDownList = System.Windows.Forms.HorizontalAlignment.Left;
+            // 
+            // lblRbiasp
+            // 
+            this.lblRbiasp.AutoSize = true;
+            this.lblRbiasp.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(240)))), ((int)(((byte)(240)))), ((int)(((byte)(240)))));
+            this.lblRbiasp.Location = new System.Drawing.Point(548, 362);
+            this.lblRbiasp.Name = "lblRbiasp";
+            this.lblRbiasp.Size = new System.Drawing.Size(147, 15);
+            this.lblRbiasp.TabIndex = 74;
+            this.lblRbiasp.Text = "Postive Input Bias Enable";
+            // 
+            // lblCalFifty
+            // 
+            this.lblCalFifty.AutoSize = true;
+            this.lblCalFifty.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(240)))), ((int)(((byte)(240)))), ((int)(((byte)(240)))));
+            this.lblCalFifty.Location = new System.Drawing.Point(720, 403);
+            this.lblCalFifty.Name = "lblCalFifty";
+            this.lblCalFifty.Size = new System.Drawing.Size(64, 15);
+            this.lblCalFifty.TabIndex = 54;
+            this.lblCalFifty.Text = "Duty Cycle";
+            // 
+            // cboRbiasv
+            // 
+            this.cboRbiasv.BackColor = System.Drawing.Color.White;
+            this.cboRbiasv.DropDownHeight = 200;
+            this.cboRbiasv.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
+            this.cboRbiasv.DropDownWidth = 116;
+            this.cboRbiasv.Location = new System.Drawing.Point(548, 339);
+            this.cboRbiasv.Name = "cboRbiasv";
+            this.cboRbiasv.Size = new System.Drawing.Size(116, 20);
+            this.cboRbiasv.TabIndex = 73;
+            this.cboRbiasv.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
+            this.cboRbiasv.TextAlignDropDownList = System.Windows.Forms.HorizontalAlignment.Left;
+            // 
+            // lblCalTHigh
+            // 
+            this.lblCalTHigh.AutoSize = true;
+            this.lblCalTHigh.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(240)))), ((int)(((byte)(240)))), ((int)(((byte)(240)))));
+            this.lblCalTHigh.Location = new System.Drawing.Point(821, 403);
+            this.lblCalTHigh.Name = "lblCalTHigh";
+            this.lblCalTHigh.Size = new System.Drawing.Size(64, 15);
+            this.lblCalTHigh.TabIndex = 55;
+            this.lblCalTHigh.Text = "Time High";
+            // 
+            // lblRbiasv
+            // 
+            this.lblRbiasv.AutoSize = true;
+            this.lblRbiasv.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(240)))), ((int)(((byte)(240)))), ((int)(((byte)(240)))));
+            this.lblRbiasv.Location = new System.Drawing.Point(548, 321);
+            this.lblRbiasv.Name = "lblRbiasv";
+            this.lblRbiasv.Size = new System.Drawing.Size(119, 15);
+            this.lblRbiasv.TabIndex = 72;
+            this.lblRbiasv.Text = "Resistive Bias Value";
+            // 
+            // lblCalFreq
+            // 
+            this.lblCalFreq.AutoSize = true;
+            this.lblCalFreq.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(240)))), ((int)(((byte)(240)))), ((int)(((byte)(240)))));
+            this.lblCalFreq.Location = new System.Drawing.Point(720, 362);
+            this.lblCalFreq.Name = "lblCalFreq";
+            this.lblCalFreq.Size = new System.Drawing.Size(64, 15);
+            this.lblCalFreq.TabIndex = 56;
+            this.lblCalFreq.Text = "Frequency";
+            // 
+            // cboEnRbias
+            // 
+            this.cboEnRbias.BackColor = System.Drawing.Color.White;
+            this.cboEnRbias.DropDownHeight = 200;
+            this.cboEnRbias.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
+            this.cboEnRbias.DropDownWidth = 87;
+            this.cboEnRbias.Location = new System.Drawing.Point(548, 81);
+            this.cboEnRbias.Name = "cboEnRbias";
+            this.cboEnRbias.Size = new System.Drawing.Size(87, 20);
+            this.cboEnRbias.TabIndex = 71;
+            this.cboEnRbias.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
+            this.cboEnRbias.TextAlignDropDownList = System.Windows.Forms.HorizontalAlignment.Left;
+            this.cboEnRbias.SelectedIndexChanged += new System.EventHandler(this.cboEnRbias_SelectedIndexChanged);
+            // 
+            // lblCalVmag
+            // 
+            this.lblCalVmag.AutoSize = true;
+            this.lblCalVmag.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(240)))), ((int)(((byte)(240)))), ((int)(((byte)(240)))));
+            this.lblCalVmag.Location = new System.Drawing.Point(720, 321);
+            this.lblCalVmag.Name = "lblCalVmag";
+            this.lblCalVmag.Size = new System.Drawing.Size(47, 15);
+            this.lblCalVmag.TabIndex = 57;
+            this.lblCalVmag.Text = "Voltage";
+            // 
+            // lblEnRbias
+            // 
+            this.lblEnRbias.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(240)))), ((int)(((byte)(240)))), ((int)(((byte)(240)))));
+            this.lblEnRbias.Location = new System.Drawing.Point(548, 48);
+            this.lblEnRbias.Name = "lblEnRbias";
+            this.lblEnRbias.Size = new System.Drawing.Size(104, 30);
+            this.lblEnRbias.TabIndex = 70;
+            this.lblEnRbias.Text = "Resistive Lead Bias Enable";
+            // 
+            // lblEmuxOpenp
+            // 
+            this.lblEmuxOpenp.AutoSize = true;
+            this.lblEmuxOpenp.BackColor = System.Drawing.Color.White;
+            this.lblEmuxOpenp.Location = new System.Drawing.Point(424, 103);
+            this.lblEmuxOpenp.Name = "lblEmuxOpenp";
+            this.lblEmuxOpenp.Size = new System.Drawing.Size(94, 15);
+            this.lblEmuxOpenp.TabIndex = 58;
+            this.lblEmuxOpenp.Text = "ECGP Switches";
+            // 
+            // lblDcloffVth
+            // 
+            this.lblDcloffVth.AutoSize = true;
+            this.lblDcloffVth.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(240)))), ((int)(((byte)(240)))), ((int)(((byte)(240)))));
+            this.lblDcloffVth.Location = new System.Drawing.Point(99, 406);
+            this.lblDcloffVth.Name = "lblDcloffVth";
+            this.lblDcloffVth.Size = new System.Drawing.Size(106, 15);
+            this.lblDcloffVth.TabIndex = 69;
+            this.lblDcloffVth.Text = "Voltage Threshold";
+            // 
+            // lblEmuxOpenn
+            // 
+            this.lblEmuxOpenn.AutoSize = true;
+            this.lblEmuxOpenn.BackColor = System.Drawing.Color.White;
+            this.lblEmuxOpenn.Location = new System.Drawing.Point(424, 243);
+            this.lblEmuxOpenn.Name = "lblEmuxOpenn";
+            this.lblEmuxOpenn.Size = new System.Drawing.Size(95, 15);
+            this.lblEmuxOpenn.TabIndex = 59;
+            this.lblEmuxOpenn.Text = "ECGN Switches";
+            // 
+            // cboDcloffVth
+            // 
+            this.cboDcloffVth.BackColor = System.Drawing.Color.White;
+            this.cboDcloffVth.DropDownHeight = 200;
+            this.cboDcloffVth.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
+            this.cboDcloffVth.DropDownWidth = 129;
+            this.cboDcloffVth.Location = new System.Drawing.Point(102, 423);
+            this.cboDcloffVth.Name = "cboDcloffVth";
+            this.cboDcloffVth.Size = new System.Drawing.Size(129, 20);
+            this.cboDcloffVth.TabIndex = 68;
+            this.cboDcloffVth.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
+            this.cboDcloffVth.TextAlignDropDownList = System.Windows.Forms.HorizontalAlignment.Left;
+            // 
+            // cboEmuxOpenp
+            // 
+            this.cboEmuxOpenp.BackColor = System.Drawing.Color.White;
+            this.cboEmuxOpenp.DropDownHeight = 200;
+            this.cboEmuxOpenp.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
+            this.cboEmuxOpenp.DropDownWidth = 101;
+            this.cboEmuxOpenp.Location = new System.Drawing.Point(424, 121);
+            this.cboEmuxOpenp.Name = "cboEmuxOpenp";
+            this.cboEmuxOpenp.Size = new System.Drawing.Size(101, 21);
+            this.cboEmuxOpenp.TabIndex = 60;
+            this.cboEmuxOpenp.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
+            this.cboEmuxOpenp.TextAlignDropDownList = System.Windows.Forms.HorizontalAlignment.Left;
+            this.cboEmuxOpenp.SelectedIndexChanged += new System.EventHandler(this.cboEmuxOpenp_SelectedIndexChanged);
+            // 
+            // cboDcloffIpol
+            // 
+            this.cboDcloffIpol.BackColor = System.Drawing.Color.White;
+            this.cboDcloffIpol.DropDownHeight = 200;
+            this.cboDcloffIpol.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
+            this.cboDcloffIpol.DropDownWidth = 172;
+            this.cboDcloffIpol.Location = new System.Drawing.Point(102, 339);
+            this.cboDcloffIpol.Name = "cboDcloffIpol";
+            this.cboDcloffIpol.Size = new System.Drawing.Size(172, 20);
+            this.cboDcloffIpol.TabIndex = 67;
+            this.cboDcloffIpol.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
+            this.cboDcloffIpol.TextAlignDropDownList = System.Windows.Forms.HorizontalAlignment.Left;
+            this.cboDcloffIpol.SelectedIndexChanged += new System.EventHandler(this.cboDcloffIpol_SelectedIndexChanged);
+            // 
+            // cboEmuxOpenn
+            // 
+            this.cboEmuxOpenn.BackColor = System.Drawing.Color.White;
+            this.cboEmuxOpenn.DropDownHeight = 200;
+            this.cboEmuxOpenn.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
+            this.cboEmuxOpenn.DropDownWidth = 101;
+            this.cboEmuxOpenn.Location = new System.Drawing.Point(424, 261);
+            this.cboEmuxOpenn.Name = "cboEmuxOpenn";
+            this.cboEmuxOpenn.Size = new System.Drawing.Size(101, 21);
+            this.cboEmuxOpenn.TabIndex = 61;
+            this.cboEmuxOpenn.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
+            this.cboEmuxOpenn.TextAlignDropDownList = System.Windows.Forms.HorizontalAlignment.Left;
+            this.cboEmuxOpenn.SelectedIndexChanged += new System.EventHandler(this.cboEmuxOpenn_SelectedIndexChanged);
+            // 
+            // lblDcloffIpol
+            // 
+            this.lblDcloffIpol.AutoSize = true;
+            this.lblDcloffIpol.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(240)))), ((int)(((byte)(240)))), ((int)(((byte)(240)))));
+            this.lblDcloffIpol.Location = new System.Drawing.Point(99, 321);
+            this.lblDcloffIpol.Name = "lblDcloffIpol";
+            this.lblDcloffIpol.Size = new System.Drawing.Size(91, 15);
+            this.lblDcloffIpol.TabIndex = 66;
+            this.lblDcloffIpol.Text = "Current Polarity";
+            // 
+            // lblEnDcloff
+            // 
+            this.lblEnDcloff.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(240)))), ((int)(((byte)(240)))), ((int)(((byte)(240)))));
+            this.lblEnDcloff.Location = new System.Drawing.Point(99, 51);
+            this.lblEnDcloff.Name = "lblEnDcloff";
+            this.lblEnDcloff.Size = new System.Drawing.Size(94, 30);
+            this.lblEnDcloff.TabIndex = 64;
+            this.lblEnDcloff.Text = "Lead-Off Detection";
+            // 
+            // cboEnDcloff
+            // 
+            this.cboEnDcloff.BackColor = System.Drawing.Color.White;
+            this.cboEnDcloff.DropDownHeight = 200;
+            this.cboEnDcloff.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
+            this.cboEnDcloff.DropDownWidth = 90;
+            this.cboEnDcloff.Location = new System.Drawing.Point(102, 84);
+            this.cboEnDcloff.Name = "cboEnDcloff";
+            this.cboEnDcloff.Size = new System.Drawing.Size(90, 20);
+            this.cboEnDcloff.TabIndex = 65;
+            this.cboEnDcloff.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
+            this.cboEnDcloff.TextAlignDropDownList = System.Windows.Forms.HorizontalAlignment.Left;
+            this.cboEnDcloff.SelectedIndexChanged += new System.EventHandler(this.cboEnDcloff_SelectedIndexChanged);
+            // 
+            // picECGLeadConfig
+            // 
+            this.picECGLeadConfig.BackgroundImageLayout = System.Windows.Forms.ImageLayout.Zoom;
+            this.picECGLeadConfig.Dock = System.Windows.Forms.DockStyle.Fill;
+            this.picECGLeadConfig.Image = global::HealthSensorPlatform.Properties.Resources.ecg_lead_config1;
+            this.picECGLeadConfig.Location = new System.Drawing.Point(0, 0);
+            this.picECGLeadConfig.Name = "picECGLeadConfig";
+            this.picECGLeadConfig.Size = new System.Drawing.Size(942, 496);
+            this.picECGLeadConfig.SizeMode = System.Windows.Forms.PictureBoxSizeMode.Zoom;
+            this.picECGLeadConfig.TabIndex = 41;
+            this.picECGLeadConfig.TabStop = false;
+            // 
+            // picSw1
+            // 
+            this.picSw1.Dock = System.Windows.Forms.DockStyle.Fill;
+            this.picSw1.Location = new System.Drawing.Point(0, 0);
+            this.picSw1.Margin = new System.Windows.Forms.Padding(0);
+            this.picSw1.Name = "picSw1";
+            this.picSw1.Size = new System.Drawing.Size(942, 496);
+            this.picSw1.SizeMode = System.Windows.Forms.PictureBoxSizeMode.Zoom;
+            this.picSw1.TabIndex = 88;
+            this.picSw1.TabStop = false;
+            // 
+            // picSw2
+            // 
+            this.picSw2.Dock = System.Windows.Forms.DockStyle.Fill;
+            this.picSw2.Location = new System.Drawing.Point(0, 0);
+            this.picSw2.Margin = new System.Windows.Forms.Padding(0);
+            this.picSw2.Name = "picSw2";
+            this.picSw2.Size = new System.Drawing.Size(942, 496);
+            this.picSw2.SizeMode = System.Windows.Forms.PictureBoxSizeMode.Zoom;
+            this.picSw2.TabIndex = 89;
+            this.picSw2.TabStop = false;
+            // 
+            // pictureBox1
+            // 
+            this.pictureBox1.Dock = System.Windows.Forms.DockStyle.Fill;
+            this.pictureBox1.Location = new System.Drawing.Point(0, 0);
+            this.pictureBox1.Margin = new System.Windows.Forms.Padding(0);
+            this.pictureBox1.Name = "pictureBox1";
+            this.pictureBox1.Size = new System.Drawing.Size(942, 496);
+            this.pictureBox1.SizeMode = System.Windows.Forms.PictureBoxSizeMode.Zoom;
+            this.pictureBox1.TabIndex = 90;
+            this.pictureBox1.TabStop = false;
+            // 
+            // picSw3
+            // 
+            this.picSw3.Dock = System.Windows.Forms.DockStyle.Fill;
+            this.picSw3.Location = new System.Drawing.Point(0, 0);
+            this.picSw3.Margin = new System.Windows.Forms.Padding(0);
+            this.picSw3.Name = "picSw3";
+            this.picSw3.Size = new System.Drawing.Size(942, 496);
+            this.picSw3.SizeMode = System.Windows.Forms.PictureBoxSizeMode.Zoom;
+            this.picSw3.TabIndex = 91;
+            this.picSw3.TabStop = false;
+            // 
+            // picSw4
+            // 
+            this.picSw4.Dock = System.Windows.Forms.DockStyle.Fill;
+            this.picSw4.Location = new System.Drawing.Point(0, 0);
+            this.picSw4.Margin = new System.Windows.Forms.Padding(0);
+            this.picSw4.Name = "picSw4";
+            this.picSw4.Size = new System.Drawing.Size(942, 496);
+            this.picSw4.SizeMode = System.Windows.Forms.PictureBoxSizeMode.Zoom;
+            this.picSw4.TabIndex = 92;
+            this.picSw4.TabStop = false;
+            // 
+            // picSw5
+            // 
+            this.picSw5.Dock = System.Windows.Forms.DockStyle.Fill;
+            this.picSw5.Location = new System.Drawing.Point(0, 0);
+            this.picSw5.Margin = new System.Windows.Forms.Padding(0);
+            this.picSw5.Name = "picSw5";
+            this.picSw5.Size = new System.Drawing.Size(942, 496);
+            this.picSw5.SizeMode = System.Windows.Forms.PictureBoxSizeMode.Zoom;
+            this.picSw5.TabIndex = 93;
+            this.picSw5.TabStop = false;
+            // 
+            // picSw6
+            // 
+            this.picSw6.Dock = System.Windows.Forms.DockStyle.Fill;
+            this.picSw6.Location = new System.Drawing.Point(0, 0);
+            this.picSw6.Margin = new System.Windows.Forms.Padding(0);
+            this.picSw6.Name = "picSw6";
+            this.picSw6.Size = new System.Drawing.Size(942, 496);
+            this.picSw6.SizeMode = System.Windows.Forms.PictureBoxSizeMode.Zoom;
+            this.picSw6.TabIndex = 94;
+            this.picSw6.TabStop = false;
+            // 
+            // picSw7
+            // 
+            this.picSw7.Dock = System.Windows.Forms.DockStyle.Fill;
+            this.picSw7.Location = new System.Drawing.Point(0, 0);
+            this.picSw7.Margin = new System.Windows.Forms.Padding(0);
+            this.picSw7.Name = "picSw7";
+            this.picSw7.Size = new System.Drawing.Size(942, 496);
+            this.picSw7.SizeMode = System.Windows.Forms.PictureBoxSizeMode.Zoom;
+            this.picSw7.TabIndex = 95;
+            this.picSw7.TabStop = false;
+            // 
+            // picSw8
+            // 
+            this.picSw8.Dock = System.Windows.Forms.DockStyle.Fill;
+            this.picSw8.Location = new System.Drawing.Point(0, 0);
+            this.picSw8.Margin = new System.Windows.Forms.Padding(0);
+            this.picSw8.Name = "picSw8";
+            this.picSw8.Size = new System.Drawing.Size(942, 496);
+            this.picSw8.SizeMode = System.Windows.Forms.PictureBoxSizeMode.Zoom;
+            this.picSw8.TabIndex = 96;
+            this.picSw8.TabStop = false;
+            // 
+            // picSw9
+            // 
+            this.picSw9.Dock = System.Windows.Forms.DockStyle.Fill;
+            this.picSw9.Location = new System.Drawing.Point(0, 0);
+            this.picSw9.Margin = new System.Windows.Forms.Padding(0);
+            this.picSw9.Name = "picSw9";
+            this.picSw9.Size = new System.Drawing.Size(942, 496);
+            this.picSw9.SizeMode = System.Windows.Forms.PictureBoxSizeMode.Zoom;
+            this.picSw9.TabIndex = 97;
+            this.picSw9.TabStop = false;
+            // 
+            // picSw10
+            // 
+            this.picSw10.Dock = System.Windows.Forms.DockStyle.Fill;
+            this.picSw10.Location = new System.Drawing.Point(0, 0);
+            this.picSw10.Margin = new System.Windows.Forms.Padding(0);
+            this.picSw10.Name = "picSw10";
+            this.picSw10.Size = new System.Drawing.Size(942, 496);
+            this.picSw10.SizeMode = System.Windows.Forms.PictureBoxSizeMode.Zoom;
+            this.picSw10.TabIndex = 98;
+            this.picSw10.TabStop = false;
+            // 
+            // picSw11
+            // 
+            this.picSw11.Dock = System.Windows.Forms.DockStyle.Fill;
+            this.picSw11.Location = new System.Drawing.Point(0, 0);
+            this.picSw11.Margin = new System.Windows.Forms.Padding(0);
+            this.picSw11.Name = "picSw11";
+            this.picSw11.Size = new System.Drawing.Size(942, 496);
+            this.picSw11.SizeMode = System.Windows.Forms.PictureBoxSizeMode.Zoom;
+            this.picSw11.TabIndex = 99;
+            this.picSw11.TabStop = false;
+            // 
+            // picSw12
+            // 
+            this.picSw12.Dock = System.Windows.Forms.DockStyle.Fill;
+            this.picSw12.Location = new System.Drawing.Point(0, 0);
+            this.picSw12.Margin = new System.Windows.Forms.Padding(0);
+            this.picSw12.Name = "picSw12";
+            this.picSw12.Size = new System.Drawing.Size(942, 496);
+            this.picSw12.SizeMode = System.Windows.Forms.PictureBoxSizeMode.Zoom;
+            this.picSw12.TabIndex = 100;
+            this.picSw12.TabStop = false;
+            // 
+            // picSw13
+            // 
+            this.picSw13.Dock = System.Windows.Forms.DockStyle.Fill;
+            this.picSw13.Location = new System.Drawing.Point(0, 0);
+            this.picSw13.Margin = new System.Windows.Forms.Padding(0);
+            this.picSw13.Name = "picSw13";
+            this.picSw13.Size = new System.Drawing.Size(942, 496);
+            this.picSw13.SizeMode = System.Windows.Forms.PictureBoxSizeMode.Zoom;
+            this.picSw13.TabIndex = 101;
+            this.picSw13.TabStop = false;
+            // 
+            // picSw14
+            // 
+            this.picSw14.Dock = System.Windows.Forms.DockStyle.Fill;
+            this.picSw14.Location = new System.Drawing.Point(0, 0);
+            this.picSw14.Margin = new System.Windows.Forms.Padding(0);
+            this.picSw14.Name = "picSw14";
+            this.picSw14.Size = new System.Drawing.Size(942, 496);
+            this.picSw14.SizeMode = System.Windows.Forms.PictureBoxSizeMode.Zoom;
+            this.picSw14.TabIndex = 102;
+            this.picSw14.TabStop = false;
+            // 
+            // pnlMAX30001Global
+            // 
+            this.pnlMAX30001Global.Controls.Add(this.grpChannelPlotEnable);
+            this.pnlMAX30001Global.Controls.Add(this.maximGroupBox8);
+            this.pnlMAX30001Global.Controls.Add(this.grpGlobalControls);
+            this.pnlMAX30001Global.Dock = System.Windows.Forms.DockStyle.Bottom;
+            this.pnlMAX30001Global.Location = new System.Drawing.Point(0, 513);
+            this.pnlMAX30001Global.Name = "pnlMAX30001Global";
+            this.pnlMAX30001Global.Size = new System.Drawing.Size(953, 93);
+            this.pnlMAX30001Global.TabIndex = 78;
+            // 
+            // grpChannelPlotEnable
+            // 
+            this.grpChannelPlotEnable.BackgroundColor = System.Drawing.Color.White;
+            this.grpChannelPlotEnable.Controls.Add(this.chkEnRtor);
+            this.grpChannelPlotEnable.Controls.Add(this.chkEnECG);
+            this.grpChannelPlotEnable.Controls.Add(this.chkEnBioZ);
+            this.grpChannelPlotEnable.Controls.Add(this.chkEnPace);
+            this.grpChannelPlotEnable.Location = new System.Drawing.Point(172, 5);
+            this.grpChannelPlotEnable.Name = "grpChannelPlotEnable";
+            this.grpChannelPlotEnable.Size = new System.Drawing.Size(301, 84);
+            this.grpChannelPlotEnable.TabIndex = 64;
+            this.grpChannelPlotEnable.TabStop = false;
+            this.grpChannelPlotEnable.Text = "Channel/Plot Enable";
+            // 
+            // chkEnRtor
+            // 
+            this.chkEnRtor.AutoSize = true;
+            this.chkEnRtor.Location = new System.Drawing.Point(99, 54);
+            this.chkEnRtor.Name = "chkEnRtor";
+            this.chkEnRtor.Size = new System.Drawing.Size(62, 19);
+            this.chkEnRtor.TabIndex = 12;
+            this.chkEnRtor.Text = "R-to-R";
+            this.chkEnRtor.UseVisualStyleBackColor = true;
+            this.chkEnRtor.CheckedChanged += new System.EventHandler(this.chkChannelEnable_CheckedChanged);
+            // 
+            // chkEnECG
+            // 
+            this.chkEnECG.AutoSize = true;
+            this.chkEnECG.Location = new System.Drawing.Point(15, 28);
+            this.chkEnECG.Name = "chkEnECG";
+            this.chkEnECG.Size = new System.Drawing.Size(52, 19);
+            this.chkEnECG.TabIndex = 9;
+            this.chkEnECG.Text = "ECG";
+            this.chkEnECG.UseVisualStyleBackColor = true;
+            this.chkEnECG.CheckedChanged += new System.EventHandler(this.chkChannelEnable_CheckedChanged);
+            // 
+            // chkEnBioZ
+            // 
+            this.chkEnBioZ.AutoSize = true;
+            this.chkEnBioZ.Location = new System.Drawing.Point(99, 29);
+            this.chkEnBioZ.Name = "chkEnBioZ";
+            this.chkEnBioZ.Size = new System.Drawing.Size(51, 19);
+            this.chkEnBioZ.TabIndex = 10;
+            this.chkEnBioZ.Text = "BioZ";
+            this.chkEnBioZ.UseVisualStyleBackColor = true;
+            this.chkEnBioZ.CheckedChanged += new System.EventHandler(this.chkChannelEnable_CheckedChanged);
+            // 
+            // chkEnPace
+            // 
+            this.chkEnPace.AutoSize = true;
+            this.chkEnPace.Location = new System.Drawing.Point(15, 53);
+            this.chkEnPace.Name = "chkEnPace";
+            this.chkEnPace.Size = new System.Drawing.Size(54, 19);
+            this.chkEnPace.TabIndex = 11;
+            this.chkEnPace.Text = "Pace";
+            this.chkEnPace.UseVisualStyleBackColor = true;
+            this.chkEnPace.CheckedChanged += new System.EventHandler(this.chkChannelEnable_CheckedChanged);
+            // 
+            // maximGroupBox8
+            // 
+            this.maximGroupBox8.BackgroundColor = System.Drawing.Color.White;
+            this.maximGroupBox8.Controls.Add(this.maximButton5);
+            this.maximGroupBox8.Controls.Add(this.maximComboBox9);
+            this.maximGroupBox8.Location = new System.Drawing.Point(479, 5);
+            this.maximGroupBox8.Name = "maximGroupBox8";
+            this.maximGroupBox8.Size = new System.Drawing.Size(249, 82);
+            this.maximGroupBox8.TabIndex = 62;
+            this.maximGroupBox8.TabStop = false;
+            this.maximGroupBox8.Text = "MAX30001 Preset Configuration";
+            this.maximGroupBox8.Visible = false;
+            // 
+            // maximButton5
+            // 
+            this.maximButton5.Location = new System.Drawing.Point(83, 54);
+            this.maximButton5.Name = "maximButton5";
+            this.maximButton5.Size = new System.Drawing.Size(75, 23);
+            this.maximButton5.TabIndex = 1;
+            this.maximButton5.Text = "Run Preset";
+            this.maximButton5.UseVisualStyleBackColor = true;
+            // 
+            // maximComboBox9
+            // 
+            this.maximComboBox9.BackColor = System.Drawing.Color.White;
+            this.maximComboBox9.DropDownHeight = 200;
+            this.maximComboBox9.DropDownWidth = 227;
+            this.maximComboBox9.Location = new System.Drawing.Point(11, 28);
+            this.maximComboBox9.Name = "maximComboBox9";
+            this.maximComboBox9.Size = new System.Drawing.Size(227, 21);
+            this.maximComboBox9.TabIndex = 0;
+            this.maximComboBox9.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
+            this.maximComboBox9.TextAlignDropDownList = System.Windows.Forms.HorizontalAlignment.Left;
+            // 
+            // grpGlobalControls
+            // 
+            this.grpGlobalControls.BackgroundColor = System.Drawing.Color.White;
+            this.grpGlobalControls.Controls.Add(this.label39);
+            this.grpGlobalControls.Controls.Add(this.cboMasterClock);
+            this.grpGlobalControls.Controls.Add(this.label31);
+            this.grpGlobalControls.Location = new System.Drawing.Point(3, 5);
+            this.grpGlobalControls.Name = "grpGlobalControls";
+            this.grpGlobalControls.Size = new System.Drawing.Size(163, 84);
+            this.grpGlobalControls.TabIndex = 63;
+            this.grpGlobalControls.TabStop = false;
+            this.grpGlobalControls.Text = "MAX30001 Global Controls";
+            // 
+            // label39
+            // 
+            this.label39.AutoSize = true;
+            this.label39.Location = new System.Drawing.Point(14, 65);
+            this.label39.Name = "label39";
+            this.label39.Size = new System.Drawing.Size(112, 15);
+            this.label39.TabIndex = 9;
+            this.label39.Text = "* Power-On Default";
+            // 
+            // cboMasterClock
+            // 
+            this.cboMasterClock.BackColor = System.Drawing.Color.White;
+            this.cboMasterClock.DropDownHeight = 200;
+            this.cboMasterClock.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
+            this.cboMasterClock.DropDownWidth = 126;
+            this.cboMasterClock.Location = new System.Drawing.Point(16, 42);
+            this.cboMasterClock.Name = "cboMasterClock";
+            this.cboMasterClock.Size = new System.Drawing.Size(126, 21);
+            this.cboMasterClock.TabIndex = 8;
+            this.cboMasterClock.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
+            this.cboMasterClock.TextAlignDropDownList = System.Windows.Forms.HorizontalAlignment.Left;
+            this.cboMasterClock.SelectedIndexChanged += new System.EventHandler(this.cboMasterClock_SelectedIndexChanged);
+            // 
+            // label31
+            // 
+            this.label31.AutoSize = true;
+            this.label31.Location = new System.Drawing.Point(13, 25);
+            this.label31.Name = "label31";
+            this.label31.Size = new System.Drawing.Size(129, 15);
+            this.label31.TabIndex = 7;
+            this.label31.Text = "Master Clock (FMSTR)";
+            // 
+            // tpBioZChannel
+            // 
+            this.tpBioZChannel.Controls.Add(this.pnlBioZChannel);
+            this.tpBioZChannel.Location = new System.Drawing.Point(4, 26);
+            this.tpBioZChannel.Name = "tpBioZChannel";
+            this.tpBioZChannel.Size = new System.Drawing.Size(953, 606);
+            this.tpBioZChannel.TabIndex = 14;
+            this.tpBioZChannel.Text = "BioZ Channel";
+            this.tpBioZChannel.UseVisualStyleBackColor = true;
+            // 
+            // pnlBioZChannel
+            // 
+            this.pnlBioZChannel.Controls.Add(this.label34);
+            this.pnlBioZChannel.Controls.Add(this.cboBioZAnalogHpf);
+            this.pnlBioZChannel.Controls.Add(this.cboBioZExternalResistorBiasEnable);
+            this.pnlBioZChannel.Controls.Add(this.cboBioZChannelGain);
+            this.pnlBioZChannel.Controls.Add(this.label25);
+            this.pnlBioZChannel.Controls.Add(this.cboBioZSampleRate);
+            this.pnlBioZChannel.Controls.Add(this.cboBioZCurrentGeneratorFrequency);
+            this.pnlBioZChannel.Controls.Add(this.cboBioZDigitalLpf);
+            this.pnlBioZChannel.Controls.Add(this.lblBioZCurrentGeneratorFrequency);
+            this.pnlBioZChannel.Controls.Add(this.cboBioZDigitalHpf);
+            this.pnlBioZChannel.Controls.Add(this.label21);
+            this.pnlBioZChannel.Controls.Add(this.cboBioZACLeadOffOverRangeThreshold);
+            this.pnlBioZChannel.Controls.Add(this.cboBioZCurrentGeneratorMagnitude);
+            this.pnlBioZChannel.Controls.Add(this.cboBioZACLeadOffUnderRangeThreshold);
+            this.pnlBioZChannel.Controls.Add(this.cboBioZModulationPhaseOffset);
+            this.pnlBioZChannel.Controls.Add(this.cboBioZDigitalLeadOffDetectionEnable);
+            this.pnlBioZChannel.Controls.Add(this.lblBioZExternalResistorBiasEnable);
+            this.pnlBioZChannel.Controls.Add(this.cboBioZCurrentGeneratorMonitor);
+            this.pnlBioZChannel.Controls.Add(this.lblBioZCurrentGeneratorMonitor);
+            this.pnlBioZChannel.Controls.Add(this.cboBioZCurrentGeneratorMode);
+            this.pnlBioZChannel.Controls.Add(this.lblBioZCurrentGeneratorMode);
+            this.pnlBioZChannel.Controls.Add(this.lblBioZAnalogHpf);
+            this.pnlBioZChannel.Controls.Add(this.lblBioZModulationPhaseOffset);
+            this.pnlBioZChannel.Controls.Add(this.linkLabel2);
+            this.pnlBioZChannel.Controls.Add(this.lblBioZCurrentGeneratorMagnitude);
+            this.pnlBioZChannel.Controls.Add(this.lblBioZChannelGain);
+            this.pnlBioZChannel.Controls.Add(this.lblBioZACLeadOffUnderRangeThreshold);
+            this.pnlBioZChannel.Controls.Add(this.lblBioZSampleRate);
+            this.pnlBioZChannel.Controls.Add(this.lblBioZACLeadOffOverRangeThreshold);
+            this.pnlBioZChannel.Controls.Add(this.lblBioZDigitalLpf);
+            this.pnlBioZChannel.Controls.Add(this.lblBioZDigitalLeadOffDetectionEnable);
+            this.pnlBioZChannel.Controls.Add(this.lblBioZDigitalHpf);
+            this.pnlBioZChannel.Controls.Add(this.picBioZChannel);
+            this.pnlBioZChannel.Location = new System.Drawing.Point(0, 5);
+            this.pnlBioZChannel.Margin = new System.Windows.Forms.Padding(2);
+            this.pnlBioZChannel.Name = "pnlBioZChannel";
+            this.pnlBioZChannel.Size = new System.Drawing.Size(946, 522);
+            this.pnlBioZChannel.TabIndex = 48;
+            // 
+            // label34
+            // 
+            this.label34.AutoSize = true;
+            this.label34.Location = new System.Drawing.Point(813, 491);
+            this.label34.Name = "label34";
+            this.label34.Size = new System.Drawing.Size(112, 15);
+            this.label34.TabIndex = 47;
+            this.label34.Text = "* Power-On Default";
+            // 
+            // cboBioZAnalogHpf
+            // 
+            this.cboBioZAnalogHpf.BackColor = System.Drawing.Color.White;
+            this.cboBioZAnalogHpf.DropDownHeight = 200;
+            this.cboBioZAnalogHpf.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
+            this.cboBioZAnalogHpf.DropDownWidth = 95;
+            this.cboBioZAnalogHpf.Location = new System.Drawing.Point(94, 145);
+            this.cboBioZAnalogHpf.Name = "cboBioZAnalogHpf";
+            this.cboBioZAnalogHpf.Size = new System.Drawing.Size(95, 21);
+            this.cboBioZAnalogHpf.TabIndex = 2;
+            this.cboBioZAnalogHpf.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
+            this.cboBioZAnalogHpf.TextAlignDropDownList = System.Windows.Forms.HorizontalAlignment.Left;
+            // 
+            // cboBioZExternalResistorBiasEnable
+            // 
+            this.cboBioZExternalResistorBiasEnable.BackColor = System.Drawing.Color.White;
+            this.cboBioZExternalResistorBiasEnable.DropDownHeight = 200;
+            this.cboBioZExternalResistorBiasEnable.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
+            this.cboBioZExternalResistorBiasEnable.DropDownWidth = 118;
+            this.cboBioZExternalResistorBiasEnable.Location = new System.Drawing.Point(80, 393);
+            this.cboBioZExternalResistorBiasEnable.Name = "cboBioZExternalResistorBiasEnable";
+            this.cboBioZExternalResistorBiasEnable.Size = new System.Drawing.Size(118, 21);
+            this.cboBioZExternalResistorBiasEnable.TabIndex = 12;
+            this.cboBioZExternalResistorBiasEnable.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
+            this.cboBioZExternalResistorBiasEnable.TextAlignDropDownList = System.Windows.Forms.HorizontalAlignment.Left;
+            // 
+            // cboBioZChannelGain
+            // 
+            this.cboBioZChannelGain.BackColor = System.Drawing.Color.White;
+            this.cboBioZChannelGain.DropDownHeight = 200;
+            this.cboBioZChannelGain.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
+            this.cboBioZChannelGain.DropDownWidth = 95;
+            this.cboBioZChannelGain.Location = new System.Drawing.Point(459, 141);
+            this.cboBioZChannelGain.Name = "cboBioZChannelGain";
+            this.cboBioZChannelGain.Size = new System.Drawing.Size(95, 21);
+            this.cboBioZChannelGain.TabIndex = 5;
+            this.cboBioZChannelGain.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
+            this.cboBioZChannelGain.TextAlignDropDownList = System.Windows.Forms.HorizontalAlignment.Left;
+            this.cboBioZChannelGain.SelectedIndexChanged += new System.EventHandler(this.cboBioZChannelGain_SelectedIndexChanged);
+            // 
+            // label25
+            // 
+            this.label25.AutoSize = true;
+            this.label25.Location = new System.Drawing.Point(231, 266);
+            this.label25.Name = "label25";
+            this.label25.Size = new System.Drawing.Size(106, 15);
+            this.label25.TabIndex = 32;
+            this.label25.Text = "Current Generator";
+            // 
+            // cboBioZSampleRate
+            // 
+            this.cboBioZSampleRate.BackColor = System.Drawing.Color.White;
+            this.cboBioZSampleRate.DropDownHeight = 200;
+            this.cboBioZSampleRate.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
+            this.cboBioZSampleRate.DropDownWidth = 95;
+            this.cboBioZSampleRate.Location = new System.Drawing.Point(575, 141);
+            this.cboBioZSampleRate.Name = "cboBioZSampleRate";
+            this.cboBioZSampleRate.Size = new System.Drawing.Size(95, 21);
+            this.cboBioZSampleRate.TabIndex = 6;
+            this.cboBioZSampleRate.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
+            this.cboBioZSampleRate.TextAlignDropDownList = System.Windows.Forms.HorizontalAlignment.Left;
+            this.cboBioZSampleRate.SelectedIndexChanged += new System.EventHandler(this.cboBioZSampleRate_SelectedIndexChanged);
+            // 
+            // cboBioZCurrentGeneratorFrequency
+            // 
+            this.cboBioZCurrentGeneratorFrequency.BackColor = System.Drawing.Color.White;
+            this.cboBioZCurrentGeneratorFrequency.DropDownHeight = 200;
+            this.cboBioZCurrentGeneratorFrequency.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
+            this.cboBioZCurrentGeneratorFrequency.DropDownWidth = 192;
+            this.cboBioZCurrentGeneratorFrequency.Location = new System.Drawing.Point(234, 303);
+            this.cboBioZCurrentGeneratorFrequency.Name = "cboBioZCurrentGeneratorFrequency";
+            this.cboBioZCurrentGeneratorFrequency.Size = new System.Drawing.Size(192, 21);
+            this.cboBioZCurrentGeneratorFrequency.TabIndex = 31;
+            this.cboBioZCurrentGeneratorFrequency.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
+            this.cboBioZCurrentGeneratorFrequency.TextAlignDropDownList = System.Windows.Forms.HorizontalAlignment.Left;
+            this.cboBioZCurrentGeneratorFrequency.SelectedIndexChanged += new System.EventHandler(this.cboBioZCurrentGeneratorFrequency_SelectedIndexChanged);
+            // 
+            // cboBioZDigitalLpf
+            // 
+            this.cboBioZDigitalLpf.BackColor = System.Drawing.Color.White;
+            this.cboBioZDigitalLpf.DropDownHeight = 200;
+            this.cboBioZDigitalLpf.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
+            this.cboBioZDigitalLpf.DropDownWidth = 107;
+            this.cboBioZDigitalLpf.Location = new System.Drawing.Point(710, 141);
+            this.cboBioZDigitalLpf.Name = "cboBioZDigitalLpf";
+            this.cboBioZDigitalLpf.Size = new System.Drawing.Size(107, 21);
+            this.cboBioZDigitalLpf.TabIndex = 7;
+            this.cboBioZDigitalLpf.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
+            this.cboBioZDigitalLpf.TextAlignDropDownList = System.Windows.Forms.HorizontalAlignment.Left;
+            // 
+            // lblBioZCurrentGeneratorFrequency
+            // 
+            this.lblBioZCurrentGeneratorFrequency.AutoSize = true;
+            this.lblBioZCurrentGeneratorFrequency.Location = new System.Drawing.Point(231, 285);
+            this.lblBioZCurrentGeneratorFrequency.Name = "lblBioZCurrentGeneratorFrequency";
+            this.lblBioZCurrentGeneratorFrequency.Size = new System.Drawing.Size(64, 15);
+            this.lblBioZCurrentGeneratorFrequency.TabIndex = 30;
+            this.lblBioZCurrentGeneratorFrequency.Text = "Frequency";
+            // 
+            // cboBioZDigitalHpf
+            // 
+            this.cboBioZDigitalHpf.BackColor = System.Drawing.Color.White;
+            this.cboBioZDigitalHpf.DropDownHeight = 200;
+            this.cboBioZDigitalHpf.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
+            this.cboBioZDigitalHpf.DropDownWidth = 106;
+            this.cboBioZDigitalHpf.Location = new System.Drawing.Point(711, 183);
+            this.cboBioZDigitalHpf.Name = "cboBioZDigitalHpf";
+            this.cboBioZDigitalHpf.Size = new System.Drawing.Size(106, 21);
+            this.cboBioZDigitalHpf.TabIndex = 8;
+            this.cboBioZDigitalHpf.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
+            this.cboBioZDigitalHpf.TextAlignDropDownList = System.Windows.Forms.HorizontalAlignment.Left;
+            // 
+            // label21
+            // 
+            this.label21.AutoSize = true;
+            this.label21.Location = new System.Drawing.Point(693, 263);
+            this.label21.Name = "label21";
+            this.label21.Size = new System.Drawing.Size(146, 15);
+            this.label21.TabIndex = 29;
+            this.label21.Text = "Digital Lead Off Detection";
+            // 
+            // cboBioZACLeadOffOverRangeThreshold
+            // 
+            this.cboBioZACLeadOffOverRangeThreshold.BackColor = System.Drawing.Color.White;
+            this.cboBioZACLeadOffOverRangeThreshold.DropDownHeight = 200;
+            this.cboBioZACLeadOffOverRangeThreshold.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
+            this.cboBioZACLeadOffOverRangeThreshold.DropDownWidth = 128;
+            this.cboBioZACLeadOffOverRangeThreshold.Location = new System.Drawing.Point(696, 344);
+            this.cboBioZACLeadOffOverRangeThreshold.Name = "cboBioZACLeadOffOverRangeThreshold";
+            this.cboBioZACLeadOffOverRangeThreshold.Size = new System.Drawing.Size(128, 21);
+            this.cboBioZACLeadOffOverRangeThreshold.TabIndex = 9;
+            this.cboBioZACLeadOffOverRangeThreshold.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
+            this.cboBioZACLeadOffOverRangeThreshold.TextAlignDropDownList = System.Windows.Forms.HorizontalAlignment.Left;
+            // 
+            // cboBioZCurrentGeneratorMagnitude
+            // 
+            this.cboBioZCurrentGeneratorMagnitude.BackColor = System.Drawing.Color.White;
+            this.cboBioZCurrentGeneratorMagnitude.DropDownHeight = 200;
+            this.cboBioZCurrentGeneratorMagnitude.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
+            this.cboBioZCurrentGeneratorMagnitude.DropDownWidth = 123;
+            this.cboBioZCurrentGeneratorMagnitude.Location = new System.Drawing.Point(234, 347);
+            this.cboBioZCurrentGeneratorMagnitude.Name = "cboBioZCurrentGeneratorMagnitude";
+            this.cboBioZCurrentGeneratorMagnitude.Size = new System.Drawing.Size(123, 21);
+            this.cboBioZCurrentGeneratorMagnitude.TabIndex = 3;
+            this.cboBioZCurrentGeneratorMagnitude.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
+            this.cboBioZCurrentGeneratorMagnitude.TextAlignDropDownList = System.Windows.Forms.HorizontalAlignment.Left;
+            this.cboBioZCurrentGeneratorMagnitude.SelectedIndexChanged += new System.EventHandler(this.cboBioZCurrentGeneratorMagnitude_SelectedIndexChanged);
+            // 
+            // cboBioZACLeadOffUnderRangeThreshold
+            // 
+            this.cboBioZACLeadOffUnderRangeThreshold.BackColor = System.Drawing.Color.White;
+            this.cboBioZACLeadOffUnderRangeThreshold.DropDownHeight = 200;
+            this.cboBioZACLeadOffUnderRangeThreshold.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
+            this.cboBioZACLeadOffUnderRangeThreshold.DropDownWidth = 128;
+            this.cboBioZACLeadOffUnderRangeThreshold.Location = new System.Drawing.Point(696, 386);
+            this.cboBioZACLeadOffUnderRangeThreshold.Name = "cboBioZACLeadOffUnderRangeThreshold";
+            this.cboBioZACLeadOffUnderRangeThreshold.Size = new System.Drawing.Size(128, 21);
+            this.cboBioZACLeadOffUnderRangeThreshold.TabIndex = 10;
+            this.cboBioZACLeadOffUnderRangeThreshold.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
+            this.cboBioZACLeadOffUnderRangeThreshold.TextAlignDropDownList = System.Windows.Forms.HorizontalAlignment.Left;
+            // 
+            // cboBioZModulationPhaseOffset
+            // 
+            this.cboBioZModulationPhaseOffset.BackColor = System.Drawing.Color.White;
+            this.cboBioZModulationPhaseOffset.DropDownHeight = 200;
+            this.cboBioZModulationPhaseOffset.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
+            this.cboBioZModulationPhaseOffset.DropDownWidth = 186;
+            this.cboBioZModulationPhaseOffset.Location = new System.Drawing.Point(367, 211);
+            this.cboBioZModulationPhaseOffset.Name = "cboBioZModulationPhaseOffset";
+            this.cboBioZModulationPhaseOffset.Size = new System.Drawing.Size(186, 21);
+            this.cboBioZModulationPhaseOffset.TabIndex = 4;
+            this.cboBioZModulationPhaseOffset.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
+            this.cboBioZModulationPhaseOffset.TextAlignDropDownList = System.Windows.Forms.HorizontalAlignment.Left;
+            // 
+            // cboBioZDigitalLeadOffDetectionEnable
+            // 
+            this.cboBioZDigitalLeadOffDetectionEnable.BackColor = System.Drawing.Color.White;
+            this.cboBioZDigitalLeadOffDetectionEnable.DropDownHeight = 200;
+            this.cboBioZDigitalLeadOffDetectionEnable.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
+            this.cboBioZDigitalLeadOffDetectionEnable.DropDownWidth = 188;
+            this.cboBioZDigitalLeadOffDetectionEnable.Location = new System.Drawing.Point(696, 300);
+            this.cboBioZDigitalLeadOffDetectionEnable.Name = "cboBioZDigitalLeadOffDetectionEnable";
+            this.cboBioZDigitalLeadOffDetectionEnable.Size = new System.Drawing.Size(188, 21);
+            this.cboBioZDigitalLeadOffDetectionEnable.TabIndex = 11;
+            this.cboBioZDigitalLeadOffDetectionEnable.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
+            this.cboBioZDigitalLeadOffDetectionEnable.TextAlignDropDownList = System.Windows.Forms.HorizontalAlignment.Left;
+            this.cboBioZDigitalLeadOffDetectionEnable.SelectedIndexChanged += new System.EventHandler(this.cboBioZDigitalLeadOffDetectionEnable_SelectedIndexChanged);
+            // 
+            // lblBioZExternalResistorBiasEnable
+            // 
+            this.lblBioZExternalResistorBiasEnable.Location = new System.Drawing.Point(81, 360);
+            this.lblBioZExternalResistorBiasEnable.Name = "lblBioZExternalResistorBiasEnable";
+            this.lblBioZExternalResistorBiasEnable.Size = new System.Drawing.Size(117, 37);
+            this.lblBioZExternalResistorBiasEnable.TabIndex = 28;
+            this.lblBioZExternalResistorBiasEnable.Text = "External Resistor Bias Enable";
+            // 
+            // cboBioZCurrentGeneratorMonitor
+            // 
+            this.cboBioZCurrentGeneratorMonitor.BackColor = System.Drawing.Color.White;
+            this.cboBioZCurrentGeneratorMonitor.DropDownHeight = 200;
+            this.cboBioZCurrentGeneratorMonitor.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
+            this.cboBioZCurrentGeneratorMonitor.DropDownWidth = 123;
+            this.cboBioZCurrentGeneratorMonitor.Location = new System.Drawing.Point(234, 435);
+            this.cboBioZCurrentGeneratorMonitor.Name = "cboBioZCurrentGeneratorMonitor";
+            this.cboBioZCurrentGeneratorMonitor.Size = new System.Drawing.Size(123, 21);
+            this.cboBioZCurrentGeneratorMonitor.TabIndex = 13;
+            this.cboBioZCurrentGeneratorMonitor.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
+            this.cboBioZCurrentGeneratorMonitor.TextAlignDropDownList = System.Windows.Forms.HorizontalAlignment.Left;
+            // 
+            // lblBioZCurrentGeneratorMonitor
+            // 
+            this.lblBioZCurrentGeneratorMonitor.AutoSize = true;
+            this.lblBioZCurrentGeneratorMonitor.Location = new System.Drawing.Point(231, 417);
+            this.lblBioZCurrentGeneratorMonitor.Name = "lblBioZCurrentGeneratorMonitor";
+            this.lblBioZCurrentGeneratorMonitor.Size = new System.Drawing.Size(47, 15);
+            this.lblBioZCurrentGeneratorMonitor.TabIndex = 27;
+            this.lblBioZCurrentGeneratorMonitor.Text = "Monitor";
+            // 
+            // cboBioZCurrentGeneratorMode
+            // 
+            this.cboBioZCurrentGeneratorMode.BackColor = System.Drawing.Color.White;
+            this.cboBioZCurrentGeneratorMode.DropDownHeight = 200;
+            this.cboBioZCurrentGeneratorMode.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
+            this.cboBioZCurrentGeneratorMode.DropDownWidth = 192;
+            this.cboBioZCurrentGeneratorMode.Location = new System.Drawing.Point(234, 393);
+            this.cboBioZCurrentGeneratorMode.Name = "cboBioZCurrentGeneratorMode";
+            this.cboBioZCurrentGeneratorMode.Size = new System.Drawing.Size(192, 21);
+            this.cboBioZCurrentGeneratorMode.TabIndex = 14;
+            this.cboBioZCurrentGeneratorMode.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
+            this.cboBioZCurrentGeneratorMode.TextAlignDropDownList = System.Windows.Forms.HorizontalAlignment.Left;
+            // 
+            // lblBioZCurrentGeneratorMode
+            // 
+            this.lblBioZCurrentGeneratorMode.AutoSize = true;
+            this.lblBioZCurrentGeneratorMode.Location = new System.Drawing.Point(231, 375);
+            this.lblBioZCurrentGeneratorMode.Name = "lblBioZCurrentGeneratorMode";
+            this.lblBioZCurrentGeneratorMode.Size = new System.Drawing.Size(37, 15);
+            this.lblBioZCurrentGeneratorMode.TabIndex = 26;
+            this.lblBioZCurrentGeneratorMode.Text = "Mode";
+            // 
+            // lblBioZAnalogHpf
+            // 
+            this.lblBioZAnalogHpf.AutoSize = true;
+            this.lblBioZAnalogHpf.Location = new System.Drawing.Point(92, 128);
+            this.lblBioZAnalogHpf.Name = "lblBioZAnalogHpf";
+            this.lblBioZAnalogHpf.Size = new System.Drawing.Size(107, 15);
+            this.lblBioZAnalogHpf.TabIndex = 15;
+            this.lblBioZAnalogHpf.Text = "Analog HPF Cutoff";
+            // 
+            // lblBioZModulationPhaseOffset
+            // 
+            this.lblBioZModulationPhaseOffset.Location = new System.Drawing.Point(367, 177);
+            this.lblBioZModulationPhaseOffset.Name = "lblBioZModulationPhaseOffset";
+            this.lblBioZModulationPhaseOffset.Size = new System.Drawing.Size(86, 39);
+            this.lblBioZModulationPhaseOffset.TabIndex = 25;
+            this.lblBioZModulationPhaseOffset.Text = "Modulation Phase Offset";
+            // 
+            // linkLabel2
+            // 
+            this.linkLabel2.Font = new System.Drawing.Font("Arial", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+            this.linkLabel2.LinkBehavior = System.Windows.Forms.LinkBehavior.NeverUnderline;
+            this.linkLabel2.LinkColor = System.Drawing.Color.FromArgb(((int)(((byte)(0)))), ((int)(((byte)(178)))), ((int)(((byte)(169)))));
+            this.linkLabel2.Location = new System.Drawing.Point(74, 51);
+            this.linkLabel2.Name = "linkLabel2";
+            this.linkLabel2.Size = new System.Drawing.Size(55, 54);
+            this.linkLabel2.TabIndex = 16;
+            this.linkLabel2.TabStop = true;
+            this.linkLabel2.Text = "BioZ Input MUX";
+            this.linkLabel2.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
+            this.linkLabel2.VisitedLinkColor = System.Drawing.Color.FromArgb(((int)(((byte)(0)))), ((int)(((byte)(178)))), ((int)(((byte)(169)))));
+            this.linkLabel2.Click += new System.EventHandler(this.linkLabel2_Click);
+            // 
+            // lblBioZCurrentGeneratorMagnitude
+            // 
+            this.lblBioZCurrentGeneratorMagnitude.AutoSize = true;
+            this.lblBioZCurrentGeneratorMagnitude.Location = new System.Drawing.Point(231, 329);
+            this.lblBioZCurrentGeneratorMagnitude.Name = "lblBioZCurrentGeneratorMagnitude";
+            this.lblBioZCurrentGeneratorMagnitude.Size = new System.Drawing.Size(64, 15);
+            this.lblBioZCurrentGeneratorMagnitude.TabIndex = 24;
+            this.lblBioZCurrentGeneratorMagnitude.Text = "Magnitude";
+            // 
+            // lblBioZChannelGain
+            // 
+            this.lblBioZChannelGain.AutoSize = true;
+            this.lblBioZChannelGain.Location = new System.Drawing.Point(456, 123);
+            this.lblBioZChannelGain.Name = "lblBioZChannelGain";
+            this.lblBioZChannelGain.Size = new System.Drawing.Size(83, 15);
+            this.lblBioZChannelGain.TabIndex = 17;
+            this.lblBioZChannelGain.Text = "Channel Gain";
+            // 
+            // lblBioZACLeadOffUnderRangeThreshold
+            // 
+            this.lblBioZACLeadOffUnderRangeThreshold.AutoSize = true;
+            this.lblBioZACLeadOffUnderRangeThreshold.Location = new System.Drawing.Point(696, 368);
+            this.lblBioZACLeadOffUnderRangeThreshold.Name = "lblBioZACLeadOffUnderRangeThreshold";
+            this.lblBioZACLeadOffUnderRangeThreshold.Size = new System.Drawing.Size(160, 15);
+            this.lblBioZACLeadOffUnderRangeThreshold.TabIndex = 23;
+            this.lblBioZACLeadOffUnderRangeThreshold.Text = "AC Under-Range Threshold";
+            // 
+            // lblBioZSampleRate
+            // 
+            this.lblBioZSampleRate.AutoSize = true;
+            this.lblBioZSampleRate.Location = new System.Drawing.Point(572, 123);
+            this.lblBioZSampleRate.Name = "lblBioZSampleRate";
+            this.lblBioZSampleRate.Size = new System.Drawing.Size(79, 15);
+            this.lblBioZSampleRate.TabIndex = 18;
+            this.lblBioZSampleRate.Text = "Sample Rate";
+            // 
+            // lblBioZACLeadOffOverRangeThreshold
+            // 
+            this.lblBioZACLeadOffOverRangeThreshold.AutoSize = true;
+            this.lblBioZACLeadOffOverRangeThreshold.Location = new System.Drawing.Point(696, 326);
+            this.lblBioZACLeadOffOverRangeThreshold.Name = "lblBioZACLeadOffOverRangeThreshold";
+            this.lblBioZACLeadOffOverRangeThreshold.Size = new System.Drawing.Size(151, 15);
+            this.lblBioZACLeadOffOverRangeThreshold.TabIndex = 22;
+            this.lblBioZACLeadOffOverRangeThreshold.Text = "AC Over-Range Threshold";
+            // 
+            // lblBioZDigitalLpf
+            // 
+            this.lblBioZDigitalLpf.AutoSize = true;
+            this.lblBioZDigitalLpf.Location = new System.Drawing.Point(708, 123);
+            this.lblBioZDigitalLpf.Name = "lblBioZDigitalLpf";
+            this.lblBioZDigitalLpf.Size = new System.Drawing.Size(102, 15);
+            this.lblBioZDigitalLpf.TabIndex = 19;
+            this.lblBioZDigitalLpf.Text = "Digital LPF Cutoff";
+            // 
+            // lblBioZDigitalLeadOffDetectionEnable
+            // 
+            this.lblBioZDigitalLeadOffDetectionEnable.AutoSize = true;
+            this.lblBioZDigitalLeadOffDetectionEnable.Location = new System.Drawing.Point(693, 282);
+            this.lblBioZDigitalLeadOffDetectionEnable.Name = "lblBioZDigitalLeadOffDetectionEnable";
+            this.lblBioZDigitalLeadOffDetectionEnable.Size = new System.Drawing.Size(46, 15);
+            this.lblBioZDigitalLeadOffDetectionEnable.TabIndex = 21;
+            this.lblBioZDigitalLeadOffDetectionEnable.Text = "Enable";
+            // 
+            // lblBioZDigitalHpf
+            // 
+            this.lblBioZDigitalHpf.AutoSize = true;
+            this.lblBioZDigitalHpf.Location = new System.Drawing.Point(708, 165);
+            this.lblBioZDigitalHpf.Name = "lblBioZDigitalHpf";
+            this.lblBioZDigitalHpf.Size = new System.Drawing.Size(104, 15);
+            this.lblBioZDigitalHpf.TabIndex = 20;
+            this.lblBioZDigitalHpf.Text = "Digital HPF Cutoff";
+            // 
+            // picBioZChannel
+            // 
+            this.picBioZChannel.Dock = System.Windows.Forms.DockStyle.Fill;
+            this.picBioZChannel.Image = global::HealthSensorPlatform.Properties.Resources.bio_impedance_block;
+            this.picBioZChannel.Location = new System.Drawing.Point(0, 0);
+            this.picBioZChannel.Name = "picBioZChannel";
+            this.picBioZChannel.Size = new System.Drawing.Size(946, 522);
+            this.picBioZChannel.SizeMode = System.Windows.Forms.PictureBoxSizeMode.Zoom;
+            this.picBioZChannel.TabIndex = 1;
+            this.picBioZChannel.TabStop = false;
+            // 
+            // tpMAX30001BioZInputMux
+            // 
+            this.tpMAX30001BioZInputMux.Controls.Add(this.pnlBioZMux);
+            this.tpMAX30001BioZInputMux.Location = new System.Drawing.Point(4, 26);
+            this.tpMAX30001BioZInputMux.Name = "tpMAX30001BioZInputMux";
+            this.tpMAX30001BioZInputMux.Size = new System.Drawing.Size(953, 606);
+            this.tpMAX30001BioZInputMux.TabIndex = 15;
+            this.tpMAX30001BioZInputMux.Text = "BioZ MUX";
+            this.tpMAX30001BioZInputMux.UseVisualStyleBackColor = true;
+            // 
+            // pnlBioZMux
+            // 
+            this.pnlBioZMux.Controls.Add(this.label36);
+            this.pnlBioZMux.Controls.Add(this.linkLabelBioZLoad);
+            this.pnlBioZMux.Controls.Add(this.cboBioZCalEnVcal);
+            this.pnlBioZMux.Controls.Add(this.lblBmuxEnUlpLon);
+            this.pnlBioZMux.Controls.Add(this.cboBioZCalVMode);
+            this.pnlBioZMux.Controls.Add(this.cboBmuxEnUlpLon);
+            this.pnlBioZMux.Controls.Add(this.cboBioZDcloffImag);
+            this.pnlBioZMux.Controls.Add(this.lblBioZCalEnVcal);
+            this.pnlBioZMux.Controls.Add(this.label27);
+            this.pnlBioZMux.Controls.Add(this.lblBioZCalVMode);
+            this.pnlBioZMux.Controls.Add(this.cboBioZBmuxCalnSel);
+            this.pnlBioZMux.Controls.Add(this.lblBioZDcloffImag);
+            this.pnlBioZMux.Controls.Add(this.lblBioZBmuxCalnSel);
+            this.pnlBioZMux.Controls.Add(this.cboBioZCalVmag);
+            this.pnlBioZMux.Controls.Add(this.cboBioZBmuxCalpSel);
+            this.pnlBioZMux.Controls.Add(this.cboBioZCalFifty);
+            this.pnlBioZMux.Controls.Add(this.lblBioZBmuxCalpSel);
+            this.pnlBioZMux.Controls.Add(this.cboBioZCalThigh);
+            this.pnlBioZMux.Controls.Add(this.cboBioZRbiasn);
+            this.pnlBioZMux.Controls.Add(this.cboBioZCalFcal);
+            this.pnlBioZMux.Controls.Add(this.lblBioZRbiasn);
+            this.pnlBioZMux.Controls.Add(this.lblBioZCalFifty);
+            this.pnlBioZMux.Controls.Add(this.cboBioZRbiasp);
+            this.pnlBioZMux.Controls.Add(this.lblBioZCalThigh);
+            this.pnlBioZMux.Controls.Add(this.lblBioZRbiasp);
+            this.pnlBioZMux.Controls.Add(this.lblBioZCalFcal);
+            this.pnlBioZMux.Controls.Add(this.cboBioZRbiasv);
+            this.pnlBioZMux.Controls.Add(this.lblBioZCalVmag);
+            this.pnlBioZMux.Controls.Add(this.lblBioZRbiasv);
+            this.pnlBioZMux.Controls.Add(this.lblBioZBmuxOpenp);
+            this.pnlBioZMux.Controls.Add(this.cboBioZEnRbias);
+            this.pnlBioZMux.Controls.Add(this.lblBioZBmuxOpenn);
+            this.pnlBioZMux.Controls.Add(this.lblBioZEnRbias);
+            this.pnlBioZMux.Controls.Add(this.cboBioZBmuxOpenp);
+            this.pnlBioZMux.Controls.Add(this.lblBioZDcloffVth);
+            this.pnlBioZMux.Controls.Add(this.cboBioZBmuxOpenn);
+            this.pnlBioZMux.Controls.Add(this.cboBioZDcloffVth);
+            this.pnlBioZMux.Controls.Add(this.lblBioZEnDcloff);
+            this.pnlBioZMux.Controls.Add(this.cboBioZDcloffIpol);
+            this.pnlBioZMux.Controls.Add(this.cboBioZEnDcloff);
+            this.pnlBioZMux.Controls.Add(this.lblBioZDcloffIpol);
+            this.pnlBioZMux.Controls.Add(this.pictureBox2);
+            this.pnlBioZMux.Controls.Add(this.picLoff1);
+            this.pnlBioZMux.Controls.Add(this.picLoff2);
+            this.pnlBioZMux.Controls.Add(this.picLeadOn);
+            this.pnlBioZMux.Controls.Add(this.picBioZsw1);
+            this.pnlBioZMux.Controls.Add(this.picBioZsw2);
+            this.pnlBioZMux.Controls.Add(this.picLeadBias1);
+            this.pnlBioZMux.Controls.Add(this.picLeadBias2);
+            this.pnlBioZMux.Controls.Add(this.picBioZCal1);
+            this.pnlBioZMux.Controls.Add(this.picBioZCal2);
+            this.pnlBioZMux.Location = new System.Drawing.Point(1, 2);
+            this.pnlBioZMux.Margin = new System.Windows.Forms.Padding(2);
+            this.pnlBioZMux.Name = "pnlBioZMux";
+            this.pnlBioZMux.Size = new System.Drawing.Size(951, 493);
+            this.pnlBioZMux.TabIndex = 127;
+            // 
+            // label36
+            // 
+            this.label36.AutoSize = true;
+            this.label36.Location = new System.Drawing.Point(814, 478);
+            this.label36.Name = "label36";
+            this.label36.Size = new System.Drawing.Size(112, 15);
+            this.label36.TabIndex = 123;
+            this.label36.Text = "* Power-On Default";
+            // 
+            // linkLabelBioZLoad
+            // 
+            this.linkLabelBioZLoad.Font = new System.Drawing.Font("Arial", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+            this.linkLabelBioZLoad.LinkBehavior = System.Windows.Forms.LinkBehavior.NeverUnderline;
+            this.linkLabelBioZLoad.LinkColor = System.Drawing.Color.FromArgb(((int)(((byte)(0)))), ((int)(((byte)(178)))), ((int)(((byte)(169)))));
+            this.linkLabelBioZLoad.Location = new System.Drawing.Point(427, 385);
+            this.linkLabelBioZLoad.Name = "linkLabelBioZLoad";
+            this.linkLabelBioZLoad.Size = new System.Drawing.Size(74, 60);
+            this.linkLabelBioZLoad.TabIndex = 126;
+            this.linkLabelBioZLoad.TabStop = true;
+            this.linkLabelBioZLoad.Text = "Selectable Resistive Load";
+            this.linkLabelBioZLoad.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
+            this.linkLabelBioZLoad.VisitedLinkColor = System.Drawing.Color.FromArgb(((int)(((byte)(0)))), ((int)(((byte)(178)))), ((int)(((byte)(169)))));
+            this.linkLabelBioZLoad.LinkClicked += new System.Windows.Forms.LinkLabelLinkClickedEventHandler(this.linkLabelBioZLoad_LinkClicked);
+            // 
+            // cboBioZCalEnVcal
+            // 
+            this.cboBioZCalEnVcal.BackColor = System.Drawing.Color.White;
+            this.cboBioZCalEnVcal.DropDownHeight = 200;
+            this.cboBioZCalEnVcal.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
+            this.cboBioZCalEnVcal.DropDownWidth = 97;
+            this.cboBioZCalEnVcal.Location = new System.Drawing.Point(730, 259);
+            this.cboBioZCalEnVcal.Name = "cboBioZCalEnVcal";
+            this.cboBioZCalEnVcal.Size = new System.Drawing.Size(97, 20);
+            this.cboBioZCalEnVcal.TabIndex = 84;
+            this.cboBioZCalEnVcal.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
+            this.cboBioZCalEnVcal.TextAlignDropDownList = System.Windows.Forms.HorizontalAlignment.Left;
+            this.cboBioZCalEnVcal.SelectedIndexChanged += new System.EventHandler(this.cboBioZCalEnVcal_SelectedIndexChanged);
+            // 
+            // lblBmuxEnUlpLon
+            // 
+            this.lblBmuxEnUlpLon.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(240)))), ((int)(((byte)(240)))), ((int)(((byte)(240)))));
+            this.lblBmuxEnUlpLon.Location = new System.Drawing.Point(298, 326);
+            this.lblBmuxEnUlpLon.Name = "lblBmuxEnUlpLon";
+            this.lblBmuxEnUlpLon.Size = new System.Drawing.Size(93, 33);
+            this.lblBmuxEnUlpLon.TabIndex = 125;
+            this.lblBmuxEnUlpLon.Text = "Lead-On Check Enable";
+            // 
+            // cboBioZCalVMode
+            // 
+            this.cboBioZCalVMode.BackColor = System.Drawing.Color.White;
+            this.cboBioZCalVMode.DropDownHeight = 200;
+            this.cboBioZCalVMode.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
+            this.cboBioZCalVMode.DropDownWidth = 97;
+            this.cboBioZCalVMode.Location = new System.Drawing.Point(730, 298);
+            this.cboBioZCalVMode.Name = "cboBioZCalVMode";
+            this.cboBioZCalVMode.Size = new System.Drawing.Size(97, 20);
+            this.cboBioZCalVMode.TabIndex = 85;
+            this.cboBioZCalVMode.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
+            this.cboBioZCalVMode.TextAlignDropDownList = System.Windows.Forms.HorizontalAlignment.Left;
+            // 
+            // cboBmuxEnUlpLon
+            // 
+            this.cboBmuxEnUlpLon.BackColor = System.Drawing.Color.White;
+            this.cboBmuxEnUlpLon.DropDownHeight = 200;
+            this.cboBmuxEnUlpLon.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
+            this.cboBmuxEnUlpLon.DropDownWidth = 90;
+            this.cboBmuxEnUlpLon.Location = new System.Drawing.Point(302, 362);
+            this.cboBmuxEnUlpLon.Name = "cboBmuxEnUlpLon";
+            this.cboBmuxEnUlpLon.Size = new System.Drawing.Size(90, 20);
+            this.cboBmuxEnUlpLon.TabIndex = 124;
+            this.cboBmuxEnUlpLon.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
+            this.cboBmuxEnUlpLon.TextAlignDropDownList = System.Windows.Forms.HorizontalAlignment.Left;
+            this.cboBmuxEnUlpLon.SelectedIndexChanged += new System.EventHandler(this.cboBmuxEnUlpLon_SelectedIndexChanged);
+            // 
+            // cboBioZDcloffImag
+            // 
+            this.cboBioZDcloffImag.BackColor = System.Drawing.Color.White;
+            this.cboBioZDcloffImag.DropDownHeight = 200;
+            this.cboBioZDcloffImag.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
+            this.cboBioZDcloffImag.DropDownWidth = 129;
+            this.cboBioZDcloffImag.Location = new System.Drawing.Point(98, 380);
+            this.cboBioZDcloffImag.Name = "cboBioZDcloffImag";
+            this.cboBioZDcloffImag.Size = new System.Drawing.Size(129, 20);
+            this.cboBioZDcloffImag.TabIndex = 86;
+            this.cboBioZDcloffImag.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
+            this.cboBioZDcloffImag.TextAlignDropDownList = System.Windows.Forms.HorizontalAlignment.Left;
+            // 
+            // lblBioZCalEnVcal
+            // 
+            this.lblBioZCalEnVcal.AutoSize = true;
+            this.lblBioZCalEnVcal.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(240)))), ((int)(((byte)(240)))), ((int)(((byte)(240)))));
+            this.lblBioZCalEnVcal.Location = new System.Drawing.Point(727, 241);
+            this.lblBioZCalEnVcal.Name = "lblBioZCalEnVcal";
+            this.lblBioZCalEnVcal.Size = new System.Drawing.Size(109, 15);
+            this.lblBioZCalEnVcal.TabIndex = 89;
+            this.lblBioZCalEnVcal.Text = "Calibration Enable";
+            // 
+            // label27
+            // 
+            this.label27.AutoSize = true;
+            this.label27.Location = new System.Drawing.Point(50, 478);
+            this.label27.Name = "label27";
+            this.label27.Size = new System.Drawing.Size(361, 15);
+            this.label27.TabIndex = 122;
+            this.label27.Text = "(Options with grey background apply to both ECG and BioZ MUX.)";
+            // 
+            // lblBioZCalVMode
+            // 
+            this.lblBioZCalVMode.AutoSize = true;
+            this.lblBioZCalVMode.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(240)))), ((int)(((byte)(240)))), ((int)(((byte)(240)))));
+            this.lblBioZCalVMode.Location = new System.Drawing.Point(727, 280);
+            this.lblBioZCalVMode.Name = "lblBioZCalVMode";
+            this.lblBioZCalVMode.Size = new System.Drawing.Size(91, 15);
+            this.lblBioZCalVMode.TabIndex = 90;
+            this.lblBioZCalVMode.Text = "Mode Selection";
+            // 
+            // cboBioZBmuxCalnSel
+            // 
+            this.cboBioZBmuxCalnSel.BackColor = System.Drawing.Color.White;
+            this.cboBioZBmuxCalnSel.DropDownHeight = 200;
+            this.cboBioZBmuxCalnSel.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
+            this.cboBioZBmuxCalnSel.DropDownWidth = 95;
+            this.cboBioZBmuxCalnSel.Location = new System.Drawing.Point(730, 116);
+            this.cboBioZBmuxCalnSel.Name = "cboBioZBmuxCalnSel";
+            this.cboBioZBmuxCalnSel.Size = new System.Drawing.Size(95, 21);
+            this.cboBioZBmuxCalnSel.TabIndex = 121;
+            this.cboBioZBmuxCalnSel.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
+            this.cboBioZBmuxCalnSel.TextAlignDropDownList = System.Windows.Forms.HorizontalAlignment.Left;
+            this.cboBioZBmuxCalnSel.SelectedIndexChanged += new System.EventHandler(this.cboBioZBmuxCalnSel_SelectedIndexChanged);
+            // 
+            // lblBioZDcloffImag
+            // 
+            this.lblBioZDcloffImag.AutoSize = true;
+            this.lblBioZDcloffImag.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(240)))), ((int)(((byte)(240)))), ((int)(((byte)(240)))));
+            this.lblBioZDcloffImag.Location = new System.Drawing.Point(95, 362);
+            this.lblBioZDcloffImag.Name = "lblBioZDcloffImag";
+            this.lblBioZDcloffImag.Size = new System.Drawing.Size(108, 15);
+            this.lblBioZDcloffImag.TabIndex = 91;
+            this.lblBioZDcloffImag.Text = "Current Magnitude";
+            // 
+            // lblBioZBmuxCalnSel
+            // 
+            this.lblBioZBmuxCalnSel.AutoSize = true;
+            this.lblBioZBmuxCalnSel.BackColor = System.Drawing.Color.White;
+            this.lblBioZBmuxCalnSel.Location = new System.Drawing.Point(727, 97);
+            this.lblBioZBmuxCalnSel.Name = "lblBioZBmuxCalnSel";
+            this.lblBioZBmuxCalnSel.Size = new System.Drawing.Size(90, 15);
+            this.lblBioZBmuxCalnSel.TabIndex = 120;
+            this.lblBioZBmuxCalnSel.Text = "BIN Calibration";
+            // 
+            // cboBioZCalVmag
+            // 
+            this.cboBioZCalVmag.BackColor = System.Drawing.Color.White;
+            this.cboBioZCalVmag.DropDownHeight = 200;
+            this.cboBioZCalVmag.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
+            this.cboBioZCalVmag.DropDownWidth = 97;
+            this.cboBioZCalVmag.Location = new System.Drawing.Point(730, 339);
+            this.cboBioZCalVmag.Name = "cboBioZCalVmag";
+            this.cboBioZCalVmag.Size = new System.Drawing.Size(97, 21);
+            this.cboBioZCalVmag.TabIndex = 92;
+            this.cboBioZCalVmag.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
+            this.cboBioZCalVmag.TextAlignDropDownList = System.Windows.Forms.HorizontalAlignment.Left;
+            // 
+            // cboBioZBmuxCalpSel
+            // 
+            this.cboBioZBmuxCalpSel.BackColor = System.Drawing.Color.White;
+            this.cboBioZBmuxCalpSel.DropDownHeight = 200;
+            this.cboBioZBmuxCalpSel.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
+            this.cboBioZBmuxCalpSel.DropDownWidth = 95;
+            this.cboBioZBmuxCalpSel.Location = new System.Drawing.Point(730, 73);
+            this.cboBioZBmuxCalpSel.Name = "cboBioZBmuxCalpSel";
+            this.cboBioZBmuxCalpSel.Size = new System.Drawing.Size(95, 21);
+            this.cboBioZBmuxCalpSel.TabIndex = 119;
+            this.cboBioZBmuxCalpSel.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
+            this.cboBioZBmuxCalpSel.TextAlignDropDownList = System.Windows.Forms.HorizontalAlignment.Left;
+            this.cboBioZBmuxCalpSel.SelectedIndexChanged += new System.EventHandler(this.cboBioZBmuxCalpSel_SelectedIndexChanged);
+            // 
+            // cboBioZCalFifty
+            // 
+            this.cboBioZCalFifty.BackColor = System.Drawing.Color.White;
+            this.cboBioZCalFifty.DropDownHeight = 200;
+            this.cboBioZCalFifty.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
+            this.cboBioZCalFifty.DropDownWidth = 95;
+            this.cboBioZCalFifty.Location = new System.Drawing.Point(730, 421);
+            this.cboBioZCalFifty.Name = "cboBioZCalFifty";
+            this.cboBioZCalFifty.Size = new System.Drawing.Size(95, 21);
+            this.cboBioZCalFifty.TabIndex = 93;
+            this.cboBioZCalFifty.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
+            this.cboBioZCalFifty.TextAlignDropDownList = System.Windows.Forms.HorizontalAlignment.Left;
+            // 
+            // lblBioZBmuxCalpSel
+            // 
+            this.lblBioZBmuxCalpSel.AutoSize = true;
+            this.lblBioZBmuxCalpSel.BackColor = System.Drawing.Color.White;
+            this.lblBioZBmuxCalpSel.Location = new System.Drawing.Point(727, 54);
+            this.lblBioZBmuxCalpSel.Name = "lblBioZBmuxCalpSel";
+            this.lblBioZBmuxCalpSel.Size = new System.Drawing.Size(89, 15);
+            this.lblBioZBmuxCalpSel.TabIndex = 118;
+            this.lblBioZBmuxCalpSel.Text = "BIP Calibration";
+            // 
+            // cboBioZCalThigh
+            // 
+            this.cboBioZCalThigh.BackColor = System.Drawing.Color.White;
+            this.cboBioZCalThigh.DropDownHeight = 200;
+            this.cboBioZCalThigh.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
+            this.cboBioZCalThigh.DropDownWidth = 72;
+            this.cboBioZCalThigh.Location = new System.Drawing.Point(831, 421);
+            this.cboBioZCalThigh.Name = "cboBioZCalThigh";
+            this.cboBioZCalThigh.Size = new System.Drawing.Size(72, 21);
+            this.cboBioZCalThigh.TabIndex = 94;
+            this.cboBioZCalThigh.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
+            this.cboBioZCalThigh.TextAlignDropDownList = System.Windows.Forms.HorizontalAlignment.Left;
+            // 
+            // cboBioZRbiasn
+            // 
+            this.cboBioZRbiasn.BackColor = System.Drawing.Color.White;
+            this.cboBioZRbiasn.DropDownHeight = 200;
+            this.cboBioZRbiasn.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
+            this.cboBioZRbiasn.DropDownWidth = 116;
+            this.cboBioZRbiasn.Location = new System.Drawing.Point(554, 423);
+            this.cboBioZRbiasn.Name = "cboBioZRbiasn";
+            this.cboBioZRbiasn.Size = new System.Drawing.Size(116, 20);
+            this.cboBioZRbiasn.TabIndex = 117;
+            this.cboBioZRbiasn.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
+            this.cboBioZRbiasn.TextAlignDropDownList = System.Windows.Forms.HorizontalAlignment.Left;
+            this.cboBioZRbiasn.SelectedIndexChanged += new System.EventHandler(this.cboBioZRbiasn_SelectedIndexChanged);
+            // 
+            // cboBioZCalFcal
+            // 
+            this.cboBioZCalFcal.BackColor = System.Drawing.Color.White;
+            this.cboBioZCalFcal.DropDownHeight = 200;
+            this.cboBioZCalFcal.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
+            this.cboBioZCalFcal.DropDownWidth = 163;
+            this.cboBioZCalFcal.Location = new System.Drawing.Point(730, 379);
+            this.cboBioZCalFcal.Name = "cboBioZCalFcal";
+            this.cboBioZCalFcal.Size = new System.Drawing.Size(163, 21);
+            this.cboBioZCalFcal.TabIndex = 95;
+            this.cboBioZCalFcal.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
+            this.cboBioZCalFcal.TextAlignDropDownList = System.Windows.Forms.HorizontalAlignment.Left;
+            // 
+            // lblBioZRbiasn
+            // 
+            this.lblBioZRbiasn.AutoSize = true;
+            this.lblBioZRbiasn.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(240)))), ((int)(((byte)(240)))), ((int)(((byte)(240)))));
+            this.lblBioZRbiasn.Location = new System.Drawing.Point(551, 405);
+            this.lblBioZRbiasn.Name = "lblBioZRbiasn";
+            this.lblBioZRbiasn.Size = new System.Drawing.Size(133, 15);
+            this.lblBioZRbiasn.TabIndex = 116;
+            this.lblBioZRbiasn.Text = "Neg. Input Bias Enable";
+            // 
+            // lblBioZCalFifty
+            // 
+            this.lblBioZCalFifty.AutoSize = true;
+            this.lblBioZCalFifty.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(240)))), ((int)(((byte)(240)))), ((int)(((byte)(240)))));
+            this.lblBioZCalFifty.Location = new System.Drawing.Point(727, 403);
+            this.lblBioZCalFifty.Name = "lblBioZCalFifty";
+            this.lblBioZCalFifty.Size = new System.Drawing.Size(64, 15);
+            this.lblBioZCalFifty.TabIndex = 96;
+            this.lblBioZCalFifty.Text = "Duty Cycle";
+            // 
+            // cboBioZRbiasp
+            // 
+            this.cboBioZRbiasp.BackColor = System.Drawing.Color.White;
+            this.cboBioZRbiasp.DropDownHeight = 200;
+            this.cboBioZRbiasp.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
+            this.cboBioZRbiasp.DropDownWidth = 116;
+            this.cboBioZRbiasp.Location = new System.Drawing.Point(554, 380);
+            this.cboBioZRbiasp.Name = "cboBioZRbiasp";
+            this.cboBioZRbiasp.Size = new System.Drawing.Size(116, 20);
+            this.cboBioZRbiasp.TabIndex = 115;
+            this.cboBioZRbiasp.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
+            this.cboBioZRbiasp.TextAlignDropDownList = System.Windows.Forms.HorizontalAlignment.Left;
+            this.cboBioZRbiasp.SelectedIndexChanged += new System.EventHandler(this.cboBioZRbiasp_SelectedIndexChanged);
+            // 
+            // lblBioZCalThigh
+            // 
+            this.lblBioZCalThigh.AutoSize = true;
+            this.lblBioZCalThigh.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(240)))), ((int)(((byte)(240)))), ((int)(((byte)(240)))));
+            this.lblBioZCalThigh.Location = new System.Drawing.Point(828, 403);
+            this.lblBioZCalThigh.Name = "lblBioZCalThigh";
+            this.lblBioZCalThigh.Size = new System.Drawing.Size(64, 15);
+            this.lblBioZCalThigh.TabIndex = 97;
+            this.lblBioZCalThigh.Text = "Time High";
+            // 
+            // lblBioZRbiasp
+            // 
+            this.lblBioZRbiasp.AutoSize = true;
+            this.lblBioZRbiasp.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(240)))), ((int)(((byte)(240)))), ((int)(((byte)(240)))));
+            this.lblBioZRbiasp.Location = new System.Drawing.Point(552, 362);
+            this.lblBioZRbiasp.Name = "lblBioZRbiasp";
+            this.lblBioZRbiasp.Size = new System.Drawing.Size(147, 15);
+            this.lblBioZRbiasp.TabIndex = 114;
+            this.lblBioZRbiasp.Text = "Postive Input Bias Enable";
+            // 
+            // lblBioZCalFcal
+            // 
+            this.lblBioZCalFcal.AutoSize = true;
+            this.lblBioZCalFcal.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(240)))), ((int)(((byte)(240)))), ((int)(((byte)(240)))));
+            this.lblBioZCalFcal.Location = new System.Drawing.Point(727, 362);
+            this.lblBioZCalFcal.Name = "lblBioZCalFcal";
+            this.lblBioZCalFcal.Size = new System.Drawing.Size(64, 15);
+            this.lblBioZCalFcal.TabIndex = 98;
+            this.lblBioZCalFcal.Text = "Frequency";
+            // 
+            // cboBioZRbiasv
+            // 
+            this.cboBioZRbiasv.BackColor = System.Drawing.Color.White;
+            this.cboBioZRbiasv.DropDownHeight = 200;
+            this.cboBioZRbiasv.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
+            this.cboBioZRbiasv.DropDownWidth = 116;
+            this.cboBioZRbiasv.Location = new System.Drawing.Point(554, 339);
+            this.cboBioZRbiasv.Name = "cboBioZRbiasv";
+            this.cboBioZRbiasv.Size = new System.Drawing.Size(116, 20);
+            this.cboBioZRbiasv.TabIndex = 113;
+            this.cboBioZRbiasv.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
+            this.cboBioZRbiasv.TextAlignDropDownList = System.Windows.Forms.HorizontalAlignment.Left;
+            // 
+            // lblBioZCalVmag
+            // 
+            this.lblBioZCalVmag.AutoSize = true;
+            this.lblBioZCalVmag.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(240)))), ((int)(((byte)(240)))), ((int)(((byte)(240)))));
+            this.lblBioZCalVmag.Location = new System.Drawing.Point(727, 321);
+            this.lblBioZCalVmag.Name = "lblBioZCalVmag";
+            this.lblBioZCalVmag.Size = new System.Drawing.Size(47, 15);
+            this.lblBioZCalVmag.TabIndex = 99;
+            this.lblBioZCalVmag.Text = "Voltage";
+            // 
+            // lblBioZRbiasv
+            // 
+            this.lblBioZRbiasv.AutoSize = true;
+            this.lblBioZRbiasv.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(240)))), ((int)(((byte)(240)))), ((int)(((byte)(240)))));
+            this.lblBioZRbiasv.Location = new System.Drawing.Point(551, 321);
+            this.lblBioZRbiasv.Name = "lblBioZRbiasv";
+            this.lblBioZRbiasv.Size = new System.Drawing.Size(119, 15);
+            this.lblBioZRbiasv.TabIndex = 112;
+            this.lblBioZRbiasv.Text = "Resistive Bias Value";
+            // 
+            // lblBioZBmuxOpenp
+            // 
+            this.lblBioZBmuxOpenp.AutoSize = true;
+            this.lblBioZBmuxOpenp.BackColor = System.Drawing.Color.White;
+            this.lblBioZBmuxOpenp.Location = new System.Drawing.Point(420, 100);
+            this.lblBioZBmuxOpenp.Name = "lblBioZBmuxOpenp";
+            this.lblBioZBmuxOpenp.Size = new System.Drawing.Size(65, 15);
+            this.lblBioZBmuxOpenp.TabIndex = 100;
+            this.lblBioZBmuxOpenp.Text = "BIP Switch";
+            // 
+            // cboBioZEnRbias
+            // 
+            this.cboBioZEnRbias.BackColor = System.Drawing.Color.White;
+            this.cboBioZEnRbias.DropDownHeight = 200;
+            this.cboBioZEnRbias.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
+            this.cboBioZEnRbias.DropDownWidth = 87;
+            this.cboBioZEnRbias.Location = new System.Drawing.Point(553, 81);
+            this.cboBioZEnRbias.Name = "cboBioZEnRbias";
+            this.cboBioZEnRbias.Size = new System.Drawing.Size(87, 20);
+            this.cboBioZEnRbias.TabIndex = 111;
+            this.cboBioZEnRbias.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
+            this.cboBioZEnRbias.TextAlignDropDownList = System.Windows.Forms.HorizontalAlignment.Left;
+            this.cboBioZEnRbias.SelectedIndexChanged += new System.EventHandler(this.cboBioZEnRbias_SelectedIndexChanged);
+            // 
+            // lblBioZBmuxOpenn
+            // 
+            this.lblBioZBmuxOpenn.AutoSize = true;
+            this.lblBioZBmuxOpenn.BackColor = System.Drawing.Color.White;
+            this.lblBioZBmuxOpenn.ForeColor = System.Drawing.Color.Black;
+            this.lblBioZBmuxOpenn.Location = new System.Drawing.Point(420, 247);
+            this.lblBioZBmuxOpenn.Name = "lblBioZBmuxOpenn";
+            this.lblBioZBmuxOpenn.Size = new System.Drawing.Size(66, 15);
+            this.lblBioZBmuxOpenn.TabIndex = 101;
+            this.lblBioZBmuxOpenn.Text = "BIN Switch";
+            // 
+            // lblBioZEnRbias
+            // 
+            this.lblBioZEnRbias.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(240)))), ((int)(((byte)(240)))), ((int)(((byte)(240)))));
+            this.lblBioZEnRbias.Location = new System.Drawing.Point(551, 48);
+            this.lblBioZEnRbias.Name = "lblBioZEnRbias";
+            this.lblBioZEnRbias.Size = new System.Drawing.Size(104, 30);
+            this.lblBioZEnRbias.TabIndex = 110;
+            this.lblBioZEnRbias.Text = "Resistive Lead Bias Enable";
+            // 
+            // cboBioZBmuxOpenp
+            // 
+            this.cboBioZBmuxOpenp.BackColor = System.Drawing.Color.White;
+            this.cboBioZBmuxOpenp.DropDownHeight = 200;
+            this.cboBioZBmuxOpenp.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
+            this.cboBioZBmuxOpenp.DropDownWidth = 101;
+            this.cboBioZBmuxOpenp.Location = new System.Drawing.Point(420, 118);
+            this.cboBioZBmuxOpenp.Name = "cboBioZBmuxOpenp";
+            this.cboBioZBmuxOpenp.Size = new System.Drawing.Size(101, 21);
+            this.cboBioZBmuxOpenp.TabIndex = 102;
+            this.cboBioZBmuxOpenp.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
+            this.cboBioZBmuxOpenp.TextAlignDropDownList = System.Windows.Forms.HorizontalAlignment.Left;
+            this.cboBioZBmuxOpenp.SelectedIndexChanged += new System.EventHandler(this.cboBioZBmuxOpenp_SelectedIndexChanged);
+            // 
+            // lblBioZDcloffVth
+            // 
+            this.lblBioZDcloffVth.AutoSize = true;
+            this.lblBioZDcloffVth.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(240)))), ((int)(((byte)(240)))), ((int)(((byte)(240)))));
+            this.lblBioZDcloffVth.Location = new System.Drawing.Point(95, 405);
+            this.lblBioZDcloffVth.Name = "lblBioZDcloffVth";
+            this.lblBioZDcloffVth.Size = new System.Drawing.Size(106, 15);
+            this.lblBioZDcloffVth.TabIndex = 109;
+            this.lblBioZDcloffVth.Text = "Voltage Threshold";
+            // 
+            // cboBioZBmuxOpenn
+            // 
+            this.cboBioZBmuxOpenn.BackColor = System.Drawing.Color.White;
+            this.cboBioZBmuxOpenn.DropDownHeight = 200;
+            this.cboBioZBmuxOpenn.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
+            this.cboBioZBmuxOpenn.DropDownWidth = 101;
+            this.cboBioZBmuxOpenn.Location = new System.Drawing.Point(420, 264);
+            this.cboBioZBmuxOpenn.Name = "cboBioZBmuxOpenn";
+            this.cboBioZBmuxOpenn.Size = new System.Drawing.Size(101, 21);
+            this.cboBioZBmuxOpenn.TabIndex = 103;
+            this.cboBioZBmuxOpenn.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
+            this.cboBioZBmuxOpenn.TextAlignDropDownList = System.Windows.Forms.HorizontalAlignment.Left;
+            this.cboBioZBmuxOpenn.SelectedIndexChanged += new System.EventHandler(this.cboBioZBmuxOpenn_SelectedIndexChanged);
+            // 
+            // cboBioZDcloffVth
+            // 
+            this.cboBioZDcloffVth.BackColor = System.Drawing.Color.White;
+            this.cboBioZDcloffVth.DropDownHeight = 200;
+            this.cboBioZDcloffVth.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
+            this.cboBioZDcloffVth.DropDownWidth = 129;
+            this.cboBioZDcloffVth.Location = new System.Drawing.Point(98, 423);
+            this.cboBioZDcloffVth.Name = "cboBioZDcloffVth";
+            this.cboBioZDcloffVth.Size = new System.Drawing.Size(129, 20);
+            this.cboBioZDcloffVth.TabIndex = 108;
+            this.cboBioZDcloffVth.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
+            this.cboBioZDcloffVth.TextAlignDropDownList = System.Windows.Forms.HorizontalAlignment.Left;
+            // 
+            // lblBioZEnDcloff
+            // 
+            this.lblBioZEnDcloff.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(240)))), ((int)(((byte)(240)))), ((int)(((byte)(240)))));
+            this.lblBioZEnDcloff.Location = new System.Drawing.Point(95, 48);
+            this.lblBioZEnDcloff.Name = "lblBioZEnDcloff";
+            this.lblBioZEnDcloff.Size = new System.Drawing.Size(94, 30);
+            this.lblBioZEnDcloff.TabIndex = 104;
+            this.lblBioZEnDcloff.Text = "Lead-Off Detection";
+            // 
+            // cboBioZDcloffIpol
+            // 
+            this.cboBioZDcloffIpol.BackColor = System.Drawing.Color.White;
+            this.cboBioZDcloffIpol.DropDownHeight = 200;
+            this.cboBioZDcloffIpol.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
+            this.cboBioZDcloffIpol.DropDownWidth = 172;
+            this.cboBioZDcloffIpol.Location = new System.Drawing.Point(98, 339);
+            this.cboBioZDcloffIpol.Name = "cboBioZDcloffIpol";
+            this.cboBioZDcloffIpol.Size = new System.Drawing.Size(172, 20);
+            this.cboBioZDcloffIpol.TabIndex = 107;
+            this.cboBioZDcloffIpol.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
+            this.cboBioZDcloffIpol.TextAlignDropDownList = System.Windows.Forms.HorizontalAlignment.Left;
+            this.cboBioZDcloffIpol.SelectedIndexChanged += new System.EventHandler(this.cboBioZDcloffIpol_SelectedIndexChanged);
+            // 
+            // cboBioZEnDcloff
+            // 
+            this.cboBioZEnDcloff.BackColor = System.Drawing.Color.White;
+            this.cboBioZEnDcloff.DropDownHeight = 200;
+            this.cboBioZEnDcloff.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
+            this.cboBioZEnDcloff.DropDownWidth = 90;
+            this.cboBioZEnDcloff.Location = new System.Drawing.Point(98, 81);
+            this.cboBioZEnDcloff.Name = "cboBioZEnDcloff";
+            this.cboBioZEnDcloff.Size = new System.Drawing.Size(90, 20);
+            this.cboBioZEnDcloff.TabIndex = 105;
+            this.cboBioZEnDcloff.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
+            this.cboBioZEnDcloff.TextAlignDropDownList = System.Windows.Forms.HorizontalAlignment.Left;
+            this.cboBioZEnDcloff.SelectedIndexChanged += new System.EventHandler(this.cboBioZEnDcloff_SelectedIndexChanged);
+            // 
+            // lblBioZDcloffIpol
+            // 
+            this.lblBioZDcloffIpol.AutoSize = true;
+            this.lblBioZDcloffIpol.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(240)))), ((int)(((byte)(240)))), ((int)(((byte)(240)))));
+            this.lblBioZDcloffIpol.Location = new System.Drawing.Point(95, 321);
+            this.lblBioZDcloffIpol.Name = "lblBioZDcloffIpol";
+            this.lblBioZDcloffIpol.Size = new System.Drawing.Size(91, 15);
+            this.lblBioZDcloffIpol.TabIndex = 106;
+            this.lblBioZDcloffIpol.Text = "Current Polarity";
+            // 
+            // pictureBox2
+            // 
+            this.pictureBox2.Dock = System.Windows.Forms.DockStyle.Fill;
+            this.pictureBox2.Image = global::HealthSensorPlatform.Properties.Resources.bioz_input_mux1;
+            this.pictureBox2.Location = new System.Drawing.Point(0, 0);
+            this.pictureBox2.Margin = new System.Windows.Forms.Padding(0);
+            this.pictureBox2.Name = "pictureBox2";
+            this.pictureBox2.Size = new System.Drawing.Size(951, 493);
+            this.pictureBox2.SizeMode = System.Windows.Forms.PictureBoxSizeMode.Zoom;
+            this.pictureBox2.TabIndex = 83;
+            this.pictureBox2.TabStop = false;
+            // 
+            // picLoff1
+            // 
+            this.picLoff1.Dock = System.Windows.Forms.DockStyle.Fill;
+            this.picLoff1.Location = new System.Drawing.Point(0, 0);
+            this.picLoff1.Margin = new System.Windows.Forms.Padding(0);
+            this.picLoff1.Name = "picLoff1";
+            this.picLoff1.Size = new System.Drawing.Size(951, 493);
+            this.picLoff1.SizeMode = System.Windows.Forms.PictureBoxSizeMode.Zoom;
+            this.picLoff1.TabIndex = 127;
+            this.picLoff1.TabStop = false;
+            // 
+            // picLoff2
+            // 
+            this.picLoff2.Dock = System.Windows.Forms.DockStyle.Fill;
+            this.picLoff2.Location = new System.Drawing.Point(0, 0);
+            this.picLoff2.Margin = new System.Windows.Forms.Padding(0);
+            this.picLoff2.Name = "picLoff2";
+            this.picLoff2.Size = new System.Drawing.Size(951, 493);
+            this.picLoff2.SizeMode = System.Windows.Forms.PictureBoxSizeMode.Zoom;
+            this.picLoff2.TabIndex = 128;
+            this.picLoff2.TabStop = false;
+            // 
+            // picLeadOn
+            // 
+            this.picLeadOn.Dock = System.Windows.Forms.DockStyle.Fill;
+            this.picLeadOn.Location = new System.Drawing.Point(0, 0);
+            this.picLeadOn.Margin = new System.Windows.Forms.Padding(0);
+            this.picLeadOn.Name = "picLeadOn";
+            this.picLeadOn.Size = new System.Drawing.Size(951, 493);
+            this.picLeadOn.SizeMode = System.Windows.Forms.PictureBoxSizeMode.Zoom;
+            this.picLeadOn.TabIndex = 129;
+            this.picLeadOn.TabStop = false;
+            // 
+            // picBioZsw1
+            // 
+            this.picBioZsw1.Dock = System.Windows.Forms.DockStyle.Fill;
+            this.picBioZsw1.Location = new System.Drawing.Point(0, 0);
+            this.picBioZsw1.Margin = new System.Windows.Forms.Padding(0);
+            this.picBioZsw1.Name = "picBioZsw1";
+            this.picBioZsw1.Size = new System.Drawing.Size(951, 493);
+            this.picBioZsw1.SizeMode = System.Windows.Forms.PictureBoxSizeMode.Zoom;
+            this.picBioZsw1.TabIndex = 130;
+            this.picBioZsw1.TabStop = false;
+            // 
+            // picBioZsw2
+            // 
+            this.picBioZsw2.Dock = System.Windows.Forms.DockStyle.Fill;
+            this.picBioZsw2.Location = new System.Drawing.Point(0, 0);
+            this.picBioZsw2.Margin = new System.Windows.Forms.Padding(0);
+            this.picBioZsw2.Name = "picBioZsw2";
+            this.picBioZsw2.Size = new System.Drawing.Size(951, 493);
+            this.picBioZsw2.SizeMode = System.Windows.Forms.PictureBoxSizeMode.Zoom;
+            this.picBioZsw2.TabIndex = 131;
+            this.picBioZsw2.TabStop = false;
+            // 
+            // picLeadBias1
+            // 
+            this.picLeadBias1.Dock = System.Windows.Forms.DockStyle.Fill;
+            this.picLeadBias1.Location = new System.Drawing.Point(0, 0);
+            this.picLeadBias1.Margin = new System.Windows.Forms.Padding(0);
+            this.picLeadBias1.Name = "picLeadBias1";
+            this.picLeadBias1.Size = new System.Drawing.Size(951, 493);
+            this.picLeadBias1.SizeMode = System.Windows.Forms.PictureBoxSizeMode.Zoom;
+            this.picLeadBias1.TabIndex = 132;
+            this.picLeadBias1.TabStop = false;
+            // 
+            // picLeadBias2
+            // 
+            this.picLeadBias2.Dock = System.Windows.Forms.DockStyle.Fill;
+            this.picLeadBias2.Location = new System.Drawing.Point(0, 0);
+            this.picLeadBias2.Margin = new System.Windows.Forms.Padding(0);
+            this.picLeadBias2.Name = "picLeadBias2";
+            this.picLeadBias2.Size = new System.Drawing.Size(951, 493);
+            this.picLeadBias2.SizeMode = System.Windows.Forms.PictureBoxSizeMode.Zoom;
+            this.picLeadBias2.TabIndex = 133;
+            this.picLeadBias2.TabStop = false;
+            // 
+            // picBioZCal1
+            // 
+            this.picBioZCal1.Dock = System.Windows.Forms.DockStyle.Fill;
+            this.picBioZCal1.Location = new System.Drawing.Point(0, 0);
+            this.picBioZCal1.Margin = new System.Windows.Forms.Padding(0);
+            this.picBioZCal1.Name = "picBioZCal1";
+            this.picBioZCal1.Size = new System.Drawing.Size(951, 493);
+            this.picBioZCal1.SizeMode = System.Windows.Forms.PictureBoxSizeMode.Zoom;
+            this.picBioZCal1.TabIndex = 134;
+            this.picBioZCal1.TabStop = false;
+            // 
+            // picBioZCal2
+            // 
+            this.picBioZCal2.Dock = System.Windows.Forms.DockStyle.Fill;
+            this.picBioZCal2.Location = new System.Drawing.Point(0, 0);
+            this.picBioZCal2.Margin = new System.Windows.Forms.Padding(0);
+            this.picBioZCal2.Name = "picBioZCal2";
+            this.picBioZCal2.Size = new System.Drawing.Size(951, 493);
+            this.picBioZCal2.SizeMode = System.Windows.Forms.PictureBoxSizeMode.Zoom;
+            this.picBioZCal2.TabIndex = 135;
+            this.picBioZCal2.TabStop = false;
+            // 
+            // tpMAX30001BioZLoad
+            // 
+            this.tpMAX30001BioZLoad.Controls.Add(this.pnlBioZLoad);
+            this.tpMAX30001BioZLoad.Location = new System.Drawing.Point(4, 26);
+            this.tpMAX30001BioZLoad.Name = "tpMAX30001BioZLoad";
+            this.tpMAX30001BioZLoad.Size = new System.Drawing.Size(953, 606);
+            this.tpMAX30001BioZLoad.TabIndex = 18;
+            this.tpMAX30001BioZLoad.Text = "BioZ Load";
+            this.tpMAX30001BioZLoad.UseVisualStyleBackColor = true;
+            // 
+            // pnlBioZLoad
+            // 
+            this.pnlBioZLoad.Controls.Add(this.label37);
+            this.pnlBioZLoad.Controls.Add(this.lblBioZBmuxEnBist);
+            this.pnlBioZLoad.Controls.Add(this.cboBioZBmuxRnom);
+            this.pnlBioZLoad.Controls.Add(this.lblBioZBmuxRmod);
+            this.pnlBioZLoad.Controls.Add(this.lblBioZBmuxRnom);
+            this.pnlBioZLoad.Controls.Add(this.lblBioZBmuxFbist);
+            this.pnlBioZLoad.Controls.Add(this.cboBioZBmuxFbist);
+            this.pnlBioZLoad.Controls.Add(this.label33);
+            this.pnlBioZLoad.Controls.Add(this.cboBioZBmuxRmod);
+            this.pnlBioZLoad.Controls.Add(this.cboBioZBmuxEnBist);
+            this.pnlBioZLoad.Controls.Add(this.picBioZLoad);
+            this.pnlBioZLoad.Controls.Add(this.picBioZLloff1);
+            this.pnlBioZLoad.Controls.Add(this.picBioZLloff2);
+            this.pnlBioZLoad.Controls.Add(this.picBioZLlon);
+            this.pnlBioZLoad.Controls.Add(this.picBioZLsw1);
+            this.pnlBioZLoad.Controls.Add(this.picBioZLlb2);
+            this.pnlBioZLoad.Controls.Add(this.picBioZLcal2);
+            this.pnlBioZLoad.Controls.Add(this.picBioZLcal1);
+            this.pnlBioZLoad.Controls.Add(this.picBioZLlb1);
+            this.pnlBioZLoad.Controls.Add(this.picBioZLsw2);
+            this.pnlBioZLoad.Controls.Add(this.picBioZLresload);
+            this.pnlBioZLoad.Location = new System.Drawing.Point(2, 2);
+            this.pnlBioZLoad.Margin = new System.Windows.Forms.Padding(2);
+            this.pnlBioZLoad.Name = "pnlBioZLoad";
+            this.pnlBioZLoad.Size = new System.Drawing.Size(946, 535);
+            this.pnlBioZLoad.TabIndex = 110;
+            // 
+            // label37
+            // 
+            this.label37.AutoSize = true;
+            this.label37.Location = new System.Drawing.Point(826, 508);
+            this.label37.Name = "label37";
+            this.label37.Size = new System.Drawing.Size(112, 15);
+            this.label37.TabIndex = 109;
+            this.label37.Text = "* Power-On Default";
+            // 
+            // lblBioZBmuxEnBist
+            // 
+            this.lblBioZBmuxEnBist.AutoSize = true;
+            this.lblBioZBmuxEnBist.Location = new System.Drawing.Point(264, 361);
+            this.lblBioZBmuxEnBist.Name = "lblBioZBmuxEnBist";
+            this.lblBioZBmuxEnBist.Size = new System.Drawing.Size(114, 15);
+            this.lblBioZBmuxEnBist.TabIndex = 0;
+            this.lblBioZBmuxEnBist.Text = "RMOD BIST Enable";
+            // 
+            // cboBioZBmuxRnom
+            // 
+            this.cboBioZBmuxRnom.BackColor = System.Drawing.Color.White;
+            this.cboBioZBmuxRnom.DropDownHeight = 200;
+            this.cboBioZBmuxRnom.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
+            this.cboBioZBmuxRnom.DropDownWidth = 110;
+            this.cboBioZBmuxRnom.Location = new System.Drawing.Point(267, 427);
+            this.cboBioZBmuxRnom.Name = "cboBioZBmuxRnom";
+            this.cboBioZBmuxRnom.Size = new System.Drawing.Size(110, 21);
+            this.cboBioZBmuxRnom.TabIndex = 108;
+            this.cboBioZBmuxRnom.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
+            this.cboBioZBmuxRnom.TextAlignDropDownList = System.Windows.Forms.HorizontalAlignment.Left;
+            // 
+            // lblBioZBmuxRmod
+            // 
+            this.lblBioZBmuxRmod.AutoSize = true;
+            this.lblBioZBmuxRmod.Location = new System.Drawing.Point(505, 361);
+            this.lblBioZBmuxRmod.Name = "lblBioZBmuxRmod";
+            this.lblBioZBmuxRmod.Size = new System.Drawing.Size(130, 15);
+            this.lblBioZBmuxRmod.TabIndex = 1;
+            this.lblBioZBmuxRmod.Text = "Modulated Resistance";
+            // 
+            // lblBioZBmuxRnom
+            // 
+            this.lblBioZBmuxRnom.AutoSize = true;
+            this.lblBioZBmuxRnom.Location = new System.Drawing.Point(264, 409);
+            this.lblBioZBmuxRnom.Name = "lblBioZBmuxRnom";
+            this.lblBioZBmuxRnom.Size = new System.Drawing.Size(120, 15);
+            this.lblBioZBmuxRnom.TabIndex = 107;
+            this.lblBioZBmuxRnom.Text = "Nominal Resistance";
+            // 
+            // lblBioZBmuxFbist
+            // 
+            this.lblBioZBmuxFbist.AutoSize = true;
+            this.lblBioZBmuxFbist.Location = new System.Drawing.Point(505, 409);
+            this.lblBioZBmuxFbist.Name = "lblBioZBmuxFbist";
+            this.lblBioZBmuxFbist.Size = new System.Drawing.Size(64, 15);
+            this.lblBioZBmuxFbist.TabIndex = 2;
+            this.lblBioZBmuxFbist.Text = "Frequency";
+            // 
+            // cboBioZBmuxFbist
+            // 
+            this.cboBioZBmuxFbist.BackColor = System.Drawing.Color.White;
+            this.cboBioZBmuxFbist.DropDownHeight = 200;
+            this.cboBioZBmuxFbist.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
+            this.cboBioZBmuxFbist.DropDownWidth = 171;
+            this.cboBioZBmuxFbist.Location = new System.Drawing.Point(508, 427);
+            this.cboBioZBmuxFbist.Name = "cboBioZBmuxFbist";
+            this.cboBioZBmuxFbist.Size = new System.Drawing.Size(171, 21);
+            this.cboBioZBmuxFbist.TabIndex = 105;
+            this.cboBioZBmuxFbist.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
+            this.cboBioZBmuxFbist.TextAlignDropDownList = System.Windows.Forms.HorizontalAlignment.Left;
+            // 
+            // label33
+            // 
+            this.label33.Font = new System.Drawing.Font("Arial", 9F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+            this.label33.Location = new System.Drawing.Point(306, 469);
+            this.label33.Name = "label33";
+            this.label33.Size = new System.Drawing.Size(309, 19);
+            this.label33.TabIndex = 3;
+            this.label33.Text = "Modulated Resistance Built-In-Self-Test (RMOD BIST)";
+            // 
+            // cboBioZBmuxRmod
+            // 
+            this.cboBioZBmuxRmod.BackColor = System.Drawing.Color.White;
+            this.cboBioZBmuxRmod.DropDownHeight = 200;
+            this.cboBioZBmuxRmod.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
+            this.cboBioZBmuxRmod.DropDownWidth = 171;
+            this.cboBioZBmuxRmod.Location = new System.Drawing.Point(508, 379);
+            this.cboBioZBmuxRmod.Name = "cboBioZBmuxRmod";
+            this.cboBioZBmuxRmod.Size = new System.Drawing.Size(171, 21);
+            this.cboBioZBmuxRmod.TabIndex = 104;
+            this.cboBioZBmuxRmod.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
+            this.cboBioZBmuxRmod.TextAlignDropDownList = System.Windows.Forms.HorizontalAlignment.Left;
+            // 
+            // cboBioZBmuxEnBist
+            // 
+            this.cboBioZBmuxEnBist.BackColor = System.Drawing.Color.White;
+            this.cboBioZBmuxEnBist.DropDownHeight = 200;
+            this.cboBioZBmuxEnBist.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
+            this.cboBioZBmuxEnBist.DropDownWidth = 110;
+            this.cboBioZBmuxEnBist.Location = new System.Drawing.Point(267, 379);
+            this.cboBioZBmuxEnBist.Name = "cboBioZBmuxEnBist";
+            this.cboBioZBmuxEnBist.Size = new System.Drawing.Size(110, 21);
+            this.cboBioZBmuxEnBist.TabIndex = 103;
+            this.cboBioZBmuxEnBist.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
+            this.cboBioZBmuxEnBist.TextAlignDropDownList = System.Windows.Forms.HorizontalAlignment.Left;
+            this.cboBioZBmuxEnBist.SelectedIndexChanged += new System.EventHandler(this.cboBioZBmuxEnBist_SelectedIndexChanged);
+            // 
+            // picBioZLoad
+            // 
+            this.picBioZLoad.Dock = System.Windows.Forms.DockStyle.Fill;
+            this.picBioZLoad.Image = global::HealthSensorPlatform.Properties.Resources.bioz_loadrz;
+            this.picBioZLoad.Location = new System.Drawing.Point(0, 0);
+            this.picBioZLoad.Margin = new System.Windows.Forms.Padding(0);
+            this.picBioZLoad.Name = "picBioZLoad";
+            this.picBioZLoad.Size = new System.Drawing.Size(946, 535);
+            this.picBioZLoad.SizeMode = System.Windows.Forms.PictureBoxSizeMode.Zoom;
+            this.picBioZLoad.TabIndex = 106;
+            this.picBioZLoad.TabStop = false;
+            // 
+            // picBioZLloff1
+            // 
+            this.picBioZLloff1.Dock = System.Windows.Forms.DockStyle.Fill;
+            this.picBioZLloff1.Location = new System.Drawing.Point(0, 0);
+            this.picBioZLloff1.Margin = new System.Windows.Forms.Padding(0);
+            this.picBioZLloff1.Name = "picBioZLloff1";
+            this.picBioZLloff1.Size = new System.Drawing.Size(946, 535);
+            this.picBioZLloff1.SizeMode = System.Windows.Forms.PictureBoxSizeMode.Zoom;
+            this.picBioZLloff1.TabIndex = 110;
+            this.picBioZLloff1.TabStop = false;
+            // 
+            // picBioZLloff2
+            // 
+            this.picBioZLloff2.Dock = System.Windows.Forms.DockStyle.Fill;
+            this.picBioZLloff2.Location = new System.Drawing.Point(0, 0);
+            this.picBioZLloff2.Margin = new System.Windows.Forms.Padding(0);
+            this.picBioZLloff2.Name = "picBioZLloff2";
+            this.picBioZLloff2.Size = new System.Drawing.Size(946, 535);
+            this.picBioZLloff2.SizeMode = System.Windows.Forms.PictureBoxSizeMode.Zoom;
+            this.picBioZLloff2.TabIndex = 111;
+            this.picBioZLloff2.TabStop = false;
+            // 
+            // picBioZLlon
+            // 
+            this.picBioZLlon.Dock = System.Windows.Forms.DockStyle.Fill;
+            this.picBioZLlon.Location = new System.Drawing.Point(0, 0);
+            this.picBioZLlon.Margin = new System.Windows.Forms.Padding(0);
+            this.picBioZLlon.Name = "picBioZLlon";
+            this.picBioZLlon.Size = new System.Drawing.Size(946, 535);
+            this.picBioZLlon.SizeMode = System.Windows.Forms.PictureBoxSizeMode.Zoom;
+            this.picBioZLlon.TabIndex = 112;
+            this.picBioZLlon.TabStop = false;
+            // 
+            // picBioZLsw1
+            // 
+            this.picBioZLsw1.Dock = System.Windows.Forms.DockStyle.Fill;
+            this.picBioZLsw1.Location = new System.Drawing.Point(0, 0);
+            this.picBioZLsw1.Margin = new System.Windows.Forms.Padding(0);
+            this.picBioZLsw1.Name = "picBioZLsw1";
+            this.picBioZLsw1.Size = new System.Drawing.Size(946, 535);
+            this.picBioZLsw1.SizeMode = System.Windows.Forms.PictureBoxSizeMode.Zoom;
+            this.picBioZLsw1.TabIndex = 113;
+            this.picBioZLsw1.TabStop = false;
+            // 
+            // picBioZLlb2
+            // 
+            this.picBioZLlb2.Dock = System.Windows.Forms.DockStyle.Fill;
+            this.picBioZLlb2.Location = new System.Drawing.Point(0, 0);
+            this.picBioZLlb2.Margin = new System.Windows.Forms.Padding(0);
+            this.picBioZLlb2.Name = "picBioZLlb2";
+            this.picBioZLlb2.Size = new System.Drawing.Size(946, 535);
+            this.picBioZLlb2.SizeMode = System.Windows.Forms.PictureBoxSizeMode.Zoom;
+            this.picBioZLlb2.TabIndex = 117;
+            this.picBioZLlb2.TabStop = false;
+            // 
+            // picBioZLcal2
+            // 
+            this.picBioZLcal2.Dock = System.Windows.Forms.DockStyle.Fill;
+            this.picBioZLcal2.Location = new System.Drawing.Point(0, 0);
+            this.picBioZLcal2.Margin = new System.Windows.Forms.Padding(0);
+            this.picBioZLcal2.Name = "picBioZLcal2";
+            this.picBioZLcal2.Size = new System.Drawing.Size(946, 535);
+            this.picBioZLcal2.SizeMode = System.Windows.Forms.PictureBoxSizeMode.Zoom;
+            this.picBioZLcal2.TabIndex = 118;
+            this.picBioZLcal2.TabStop = false;
+            // 
+            // picBioZLcal1
+            // 
+            this.picBioZLcal1.Dock = System.Windows.Forms.DockStyle.Fill;
+            this.picBioZLcal1.Location = new System.Drawing.Point(0, 0);
+            this.picBioZLcal1.Margin = new System.Windows.Forms.Padding(0);
+            this.picBioZLcal1.Name = "picBioZLcal1";
+            this.picBioZLcal1.Size = new System.Drawing.Size(946, 535);
+            this.picBioZLcal1.SizeMode = System.Windows.Forms.PictureBoxSizeMode.Zoom;
+            this.picBioZLcal1.TabIndex = 116;
+            this.picBioZLcal1.TabStop = false;
+            // 
+            // picBioZLlb1
+            // 
+            this.picBioZLlb1.Dock = System.Windows.Forms.DockStyle.Fill;
+            this.picBioZLlb1.Location = new System.Drawing.Point(0, 0);
+            this.picBioZLlb1.Margin = new System.Windows.Forms.Padding(0);
+            this.picBioZLlb1.Name = "picBioZLlb1";
+            this.picBioZLlb1.Size = new System.Drawing.Size(946, 535);
+            this.picBioZLlb1.SizeMode = System.Windows.Forms.PictureBoxSizeMode.Zoom;
+            this.picBioZLlb1.TabIndex = 115;
+            this.picBioZLlb1.TabStop = false;
+            // 
+            // picBioZLsw2
+            // 
+            this.picBioZLsw2.Dock = System.Windows.Forms.DockStyle.Fill;
+            this.picBioZLsw2.Location = new System.Drawing.Point(0, 0);
+            this.picBioZLsw2.Margin = new System.Windows.Forms.Padding(0);
+            this.picBioZLsw2.Name = "picBioZLsw2";
+            this.picBioZLsw2.Size = new System.Drawing.Size(946, 535);
+            this.picBioZLsw2.SizeMode = System.Windows.Forms.PictureBoxSizeMode.Zoom;
+            this.picBioZLsw2.TabIndex = 114;
+            this.picBioZLsw2.TabStop = false;
+            // 
+            // picBioZLresload
+            // 
+            this.picBioZLresload.Dock = System.Windows.Forms.DockStyle.Fill;
+            this.picBioZLresload.Location = new System.Drawing.Point(0, 0);
+            this.picBioZLresload.Margin = new System.Windows.Forms.Padding(0);
+            this.picBioZLresload.Name = "picBioZLresload";
+            this.picBioZLresload.Size = new System.Drawing.Size(946, 535);
+            this.picBioZLresload.SizeMode = System.Windows.Forms.PictureBoxSizeMode.Zoom;
+            this.picBioZLresload.TabIndex = 119;
+            this.picBioZLresload.TabStop = false;
+            // 
+            // tpMAX30001Pace
+            // 
+            this.tpMAX30001Pace.Controls.Add(this.pnlPace);
+            this.tpMAX30001Pace.Location = new System.Drawing.Point(4, 26);
+            this.tpMAX30001Pace.Name = "tpMAX30001Pace";
+            this.tpMAX30001Pace.Size = new System.Drawing.Size(953, 606);
+            this.tpMAX30001Pace.TabIndex = 16;
+            this.tpMAX30001Pace.Text = "Pace Channel";
+            this.tpMAX30001Pace.UseVisualStyleBackColor = true;
+            // 
+            // pnlPace
+            // 
+            this.pnlPace.Controls.Add(this.label38);
+            this.pnlPace.Controls.Add(this.cboPaceAnalogHpf);
+            this.pnlPace.Controls.Add(this.label35);
+            this.pnlPace.Controls.Add(this.lblPaceAnalogHpf);
+            this.pnlPace.Controls.Add(this.cboPaceDetectorNegativeThreshold);
+            this.pnlPace.Controls.Add(this.lblPaceBufferBandwidth);
+            this.pnlPace.Controls.Add(this.cboPaceDetectorPostiveThreshold);
+            this.pnlPace.Controls.Add(this.lblPaceSignalSelection);
+            this.pnlPace.Controls.Add(this.cboPaceDifferentiatorMode);
+            this.pnlPace.Controls.Add(this.lblPaceInputPolarity);
+            this.pnlPace.Controls.Add(this.cboPaceChannelGain);
+            this.pnlPace.Controls.Add(this.lblPaceChannelGain);
+            this.pnlPace.Controls.Add(this.cboPaceInputPolarity);
+            this.pnlPace.Controls.Add(this.lblPaceDifferentiatorMode);
+            this.pnlPace.Controls.Add(this.cboPaceSignalSelection);
+            this.pnlPace.Controls.Add(this.lblPaceDetectorPostiveThreshold);
+            this.pnlPace.Controls.Add(this.cboPaceBufferBandwidth);
+            this.pnlPace.Controls.Add(this.lblPaceDetectorNegativeThreshold);
+            this.pnlPace.Controls.Add(this.picPaceChannel);
+            this.pnlPace.Location = new System.Drawing.Point(2, 2);
+            this.pnlPace.Margin = new System.Windows.Forms.Padding(2);
+            this.pnlPace.Name = "pnlPace";
+            this.pnlPace.Size = new System.Drawing.Size(946, 473);
+            this.pnlPace.TabIndex = 48;
+            // 
+            // label38
+            // 
+            this.label38.AutoSize = true;
+            this.label38.Location = new System.Drawing.Point(822, 288);
+            this.label38.Name = "label38";
+            this.label38.Size = new System.Drawing.Size(112, 15);
+            this.label38.TabIndex = 47;
+            this.label38.Text = "* Power-On Default";
+            // 
+            // cboPaceAnalogHpf
+            // 
+            this.cboPaceAnalogHpf.BackColor = System.Drawing.Color.White;
+            this.cboPaceAnalogHpf.DropDownHeight = 200;
+            this.cboPaceAnalogHpf.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
+            this.cboPaceAnalogHpf.DropDownWidth = 95;
+            this.cboPaceAnalogHpf.Location = new System.Drawing.Point(115, 396);
+            this.cboPaceAnalogHpf.Name = "cboPaceAnalogHpf";
+            this.cboPaceAnalogHpf.Size = new System.Drawing.Size(95, 21);
+            this.cboPaceAnalogHpf.TabIndex = 16;
+            this.cboPaceAnalogHpf.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
+            this.cboPaceAnalogHpf.TextAlignDropDownList = System.Windows.Forms.HorizontalAlignment.Left;
+            // 
+            // label35
+            // 
+            this.label35.Location = new System.Drawing.Point(71, 311);
+            this.label35.Name = "label35";
+            this.label35.Size = new System.Drawing.Size(50, 52);
+            this.label35.TabIndex = 32;
+            this.label35.Text = "BioZ Input MUX";
+            this.label35.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
+            // 
+            // lblPaceAnalogHpf
+            // 
+            this.lblPaceAnalogHpf.AutoSize = true;
+            this.lblPaceAnalogHpf.Location = new System.Drawing.Point(112, 378);
+            this.lblPaceAnalogHpf.Name = "lblPaceAnalogHpf";
+            this.lblPaceAnalogHpf.Size = new System.Drawing.Size(107, 15);
+            this.lblPaceAnalogHpf.TabIndex = 17;
+            this.lblPaceAnalogHpf.Text = "Analog HPF Cutoff";
+            // 
+            // cboPaceDetectorNegativeThreshold
+            // 
+            this.cboPaceDetectorNegativeThreshold.BackColor = System.Drawing.Color.White;
+            this.cboPaceDetectorNegativeThreshold.DropDownHeight = 200;
+            this.cboPaceDetectorNegativeThreshold.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
+            this.cboPaceDetectorNegativeThreshold.DropDownWidth = 132;
+            this.cboPaceDetectorNegativeThreshold.Location = new System.Drawing.Point(770, 250);
+            this.cboPaceDetectorNegativeThreshold.Name = "cboPaceDetectorNegativeThreshold";
+            this.cboPaceDetectorNegativeThreshold.Size = new System.Drawing.Size(132, 21);
+            this.cboPaceDetectorNegativeThreshold.TabIndex = 31;
+            this.cboPaceDetectorNegativeThreshold.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
+            this.cboPaceDetectorNegativeThreshold.TextAlignDropDownList = System.Windows.Forms.HorizontalAlignment.Left;
+            // 
+            // lblPaceBufferBandwidth
+            // 
+            this.lblPaceBufferBandwidth.AutoSize = true;
+            this.lblPaceBufferBandwidth.Location = new System.Drawing.Point(50, 126);
+            this.lblPaceBufferBandwidth.Name = "lblPaceBufferBandwidth";
+            this.lblPaceBufferBandwidth.Size = new System.Drawing.Size(100, 15);
+            this.lblPaceBufferBandwidth.TabIndex = 18;
+            this.lblPaceBufferBandwidth.Text = "Buffer Bandwidth";
+            // 
+            // cboPaceDetectorPostiveThreshold
+            // 
+            this.cboPaceDetectorPostiveThreshold.BackColor = System.Drawing.Color.White;
+            this.cboPaceDetectorPostiveThreshold.DropDownHeight = 200;
+            this.cboPaceDetectorPostiveThreshold.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
+            this.cboPaceDetectorPostiveThreshold.DropDownWidth = 132;
+            this.cboPaceDetectorPostiveThreshold.Location = new System.Drawing.Point(770, 203);
+            this.cboPaceDetectorPostiveThreshold.Name = "cboPaceDetectorPostiveThreshold";
+            this.cboPaceDetectorPostiveThreshold.Size = new System.Drawing.Size(132, 21);
+            this.cboPaceDetectorPostiveThreshold.TabIndex = 30;
+            this.cboPaceDetectorPostiveThreshold.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
+            this.cboPaceDetectorPostiveThreshold.TextAlignDropDownList = System.Windows.Forms.HorizontalAlignment.Left;
+            // 
+            // lblPaceSignalSelection
+            // 
+            this.lblPaceSignalSelection.AutoSize = true;
+            this.lblPaceSignalSelection.Location = new System.Drawing.Point(186, 126);
+            this.lblPaceSignalSelection.Name = "lblPaceSignalSelection";
+            this.lblPaceSignalSelection.Size = new System.Drawing.Size(96, 15);
+            this.lblPaceSignalSelection.TabIndex = 19;
+            this.lblPaceSignalSelection.Text = "Signal Selection";
+            // 
+            // cboPaceDifferentiatorMode
+            // 
+            this.cboPaceDifferentiatorMode.BackColor = System.Drawing.Color.White;
+            this.cboPaceDifferentiatorMode.DropDownHeight = 200;
+            this.cboPaceDifferentiatorMode.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
+            this.cboPaceDifferentiatorMode.DropDownWidth = 132;
+            this.cboPaceDifferentiatorMode.Location = new System.Drawing.Point(627, 250);
+            this.cboPaceDifferentiatorMode.Name = "cboPaceDifferentiatorMode";
+            this.cboPaceDifferentiatorMode.Size = new System.Drawing.Size(132, 21);
+            this.cboPaceDifferentiatorMode.TabIndex = 29;
+            this.cboPaceDifferentiatorMode.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
+            this.cboPaceDifferentiatorMode.TextAlignDropDownList = System.Windows.Forms.HorizontalAlignment.Left;
+            // 
+            // lblPaceInputPolarity
+            // 
+            this.lblPaceInputPolarity.AutoSize = true;
+            this.lblPaceInputPolarity.Location = new System.Drawing.Point(167, 227);
+            this.lblPaceInputPolarity.Name = "lblPaceInputPolarity";
+            this.lblPaceInputPolarity.Size = new System.Drawing.Size(77, 15);
+            this.lblPaceInputPolarity.TabIndex = 20;
+            this.lblPaceInputPolarity.Text = "Input Polarity";
+            // 
+            // cboPaceChannelGain
+            // 
+            this.cboPaceChannelGain.BackColor = System.Drawing.Color.White;
+            this.cboPaceChannelGain.DropDownHeight = 200;
+            this.cboPaceChannelGain.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
+            this.cboPaceChannelGain.DropDownWidth = 158;
+            this.cboPaceChannelGain.Location = new System.Drawing.Point(448, 203);
+            this.cboPaceChannelGain.Name = "cboPaceChannelGain";
+            this.cboPaceChannelGain.Size = new System.Drawing.Size(158, 21);
+            this.cboPaceChannelGain.TabIndex = 28;
+            this.cboPaceChannelGain.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
+            this.cboPaceChannelGain.TextAlignDropDownList = System.Windows.Forms.HorizontalAlignment.Left;
+            // 
+            // lblPaceChannelGain
+            // 
+            this.lblPaceChannelGain.AutoSize = true;
+            this.lblPaceChannelGain.Location = new System.Drawing.Point(446, 185);
+            this.lblPaceChannelGain.Name = "lblPaceChannelGain";
+            this.lblPaceChannelGain.Size = new System.Drawing.Size(195, 15);
+            this.lblPaceChannelGain.TabIndex = 21;
+            this.lblPaceChannelGain.Text = "Channel Gain (Normal / INA / PGA)";
+            // 
+            // cboPaceInputPolarity
+            // 
+            this.cboPaceInputPolarity.BackColor = System.Drawing.Color.White;
+            this.cboPaceInputPolarity.DropDownHeight = 200;
+            this.cboPaceInputPolarity.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
+            this.cboPaceInputPolarity.DropDownWidth = 107;
+            this.cboPaceInputPolarity.Location = new System.Drawing.Point(170, 246);
+            this.cboPaceInputPolarity.Name = "cboPaceInputPolarity";
+            this.cboPaceInputPolarity.Size = new System.Drawing.Size(107, 21);
+            this.cboPaceInputPolarity.TabIndex = 27;
+            this.cboPaceInputPolarity.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
+            this.cboPaceInputPolarity.TextAlignDropDownList = System.Windows.Forms.HorizontalAlignment.Left;
+            // 
+            // lblPaceDifferentiatorMode
+            // 
+            this.lblPaceDifferentiatorMode.AutoSize = true;
+            this.lblPaceDifferentiatorMode.Location = new System.Drawing.Point(623, 232);
+            this.lblPaceDifferentiatorMode.Name = "lblPaceDifferentiatorMode";
+            this.lblPaceDifferentiatorMode.Size = new System.Drawing.Size(110, 15);
+            this.lblPaceDifferentiatorMode.TabIndex = 22;
+            this.lblPaceDifferentiatorMode.Text = "Differentiator Mode";
+            // 
+            // cboPaceSignalSelection
+            // 
+            this.cboPaceSignalSelection.BackColor = System.Drawing.Color.White;
+            this.cboPaceSignalSelection.DropDownHeight = 200;
+            this.cboPaceSignalSelection.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
+            this.cboPaceSignalSelection.DropDownWidth = 95;
+            this.cboPaceSignalSelection.Location = new System.Drawing.Point(189, 144);
+            this.cboPaceSignalSelection.Name = "cboPaceSignalSelection";
+            this.cboPaceSignalSelection.Size = new System.Drawing.Size(95, 21);
+            this.cboPaceSignalSelection.TabIndex = 26;
+            this.cboPaceSignalSelection.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
+            this.cboPaceSignalSelection.TextAlignDropDownList = System.Windows.Forms.HorizontalAlignment.Left;
+            // 
+            // lblPaceDetectorPostiveThreshold
+            // 
+            this.lblPaceDetectorPostiveThreshold.AutoSize = true;
+            this.lblPaceDetectorPostiveThreshold.Location = new System.Drawing.Point(766, 185);
+            this.lblPaceDetectorPostiveThreshold.Name = "lblPaceDetectorPostiveThreshold";
+            this.lblPaceDetectorPostiveThreshold.Size = new System.Drawing.Size(155, 15);
+            this.lblPaceDetectorPostiveThreshold.TabIndex = 23;
+            this.lblPaceDetectorPostiveThreshold.Text = "Detector Postive Threshold";
+            // 
+            // cboPaceBufferBandwidth
+            // 
+            this.cboPaceBufferBandwidth.BackColor = System.Drawing.Color.White;
+            this.cboPaceBufferBandwidth.DropDownHeight = 200;
+            this.cboPaceBufferBandwidth.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
+            this.cboPaceBufferBandwidth.DropDownWidth = 123;
+            this.cboPaceBufferBandwidth.Location = new System.Drawing.Point(53, 144);
+            this.cboPaceBufferBandwidth.Name = "cboPaceBufferBandwidth";
+            this.cboPaceBufferBandwidth.Size = new System.Drawing.Size(123, 21);
+            this.cboPaceBufferBandwidth.TabIndex = 25;
+            this.cboPaceBufferBandwidth.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
+            this.cboPaceBufferBandwidth.TextAlignDropDownList = System.Windows.Forms.HorizontalAlignment.Left;
+            // 
+            // lblPaceDetectorNegativeThreshold
+            // 
+            this.lblPaceDetectorNegativeThreshold.AutoSize = true;
+            this.lblPaceDetectorNegativeThreshold.Location = new System.Drawing.Point(766, 232);
+            this.lblPaceDetectorNegativeThreshold.Name = "lblPaceDetectorNegativeThreshold";
+            this.lblPaceDetectorNegativeThreshold.Size = new System.Drawing.Size(163, 15);
+            this.lblPaceDetectorNegativeThreshold.TabIndex = 24;
+            this.lblPaceDetectorNegativeThreshold.Text = "Detector Negative Threshold";
+            // 
+            // picPaceChannel
+            // 
+            this.picPaceChannel.Dock = System.Windows.Forms.DockStyle.Fill;
+            this.picPaceChannel.Image = global::HealthSensorPlatform.Properties.Resources.pace_block_diagrams;
+            this.picPaceChannel.Location = new System.Drawing.Point(0, 0);
+            this.picPaceChannel.Name = "picPaceChannel";
+            this.picPaceChannel.Size = new System.Drawing.Size(946, 473);
+            this.picPaceChannel.SizeMode = System.Windows.Forms.PictureBoxSizeMode.Zoom;
+            this.picPaceChannel.TabIndex = 0;
+            this.picPaceChannel.TabStop = false;
+            // 
+            // tpMAX30001Plots
+            // 
+            this.tpMAX30001Plots.BackColor = System.Drawing.Color.White;
+            this.tpMAX30001Plots.Controls.Add(this.ecgView1);
+            this.tpMAX30001Plots.Location = new System.Drawing.Point(4, 26);
+            this.tpMAX30001Plots.Name = "tpMAX30001Plots";
+            this.tpMAX30001Plots.Size = new System.Drawing.Size(953, 606);
+            this.tpMAX30001Plots.TabIndex = 8;
+            this.tpMAX30001Plots.Text = "Plots";
+            // 
+            // ecgView1
+            // 
+            this.ecgView1.BioZMilliOhmRange = false;
+            this.ecgView1.Connected = false;
+            this.ecgView1.CurrentBioZ = 0;
+            this.ecgView1.Dock = System.Windows.Forms.DockStyle.Fill;
+            this.ecgView1.EnableBioZ = false;
+            this.ecgView1.EnableBioZOverUnderRange = true;
+            this.ecgView1.EnableDCLeadOff = true;
+            this.ecgView1.EnableECG = false;
+            this.ecgView1.EnableEcgDCLeadOff = false;
+            this.ecgView1.EnablePace = false;
+            this.ecgView1.EnableRToR = false;
+            this.ecgView1.FrequencyMasterField = 0;
+            this.ecgView1.GainBioZ = 20;
+            this.ecgView1.GainECG = 20;
+            this.ecgView1.HspSetting = null;
+            this.ecgView1.Location = new System.Drawing.Point(0, 0);
+            this.ecgView1.Margin = new System.Windows.Forms.Padding(4);
+            this.ecgView1.Name = "ecgView1";
+            this.ecgView1.SampleRateBioZ = 128D;
+            this.ecgView1.SampleRateEcg = 128D;
+            this.ecgView1.Size = new System.Drawing.Size(953, 606);
+            this.ecgView1.TabIndex = 0;
+            // 
+            // tpFlashLog
+            // 
+            this.tpFlashLog.Controls.Add(this.dataLoggingView1);
+            this.tpFlashLog.Location = new System.Drawing.Point(4, 26);
+            this.tpFlashLog.Name = "tpFlashLog";
+            this.tpFlashLog.Size = new System.Drawing.Size(953, 606);
+            this.tpFlashLog.TabIndex = 17;
+            this.tpFlashLog.Text = "Flash Log";
+            this.tpFlashLog.UseVisualStyleBackColor = true;
+            // 
+            // dataLoggingView1
+            // 
+            this.dataLoggingView1.BackColor = System.Drawing.Color.White;
+            this.dataLoggingView1.BioZArgs = null;
+            this.dataLoggingView1.Connected = false;
+            this.dataLoggingView1.Dock = System.Windows.Forms.DockStyle.Fill;
+            this.dataLoggingView1.EcgArgs = null;
+            this.dataLoggingView1.EnableAccelerometer = false;
+            this.dataLoggingView1.EnableBioz = false;
+            this.dataLoggingView1.EnableEcg = false;
+            this.dataLoggingView1.EnableOpticalHR = false;
+            this.dataLoggingView1.EnableOpticalMulti = false;
+            this.dataLoggingView1.EnableOpticalSpO2 = false;
+            this.dataLoggingView1.EnablePace = false;
+            this.dataLoggingView1.EnablePressure = false;
+            this.dataLoggingView1.EnableRToR = false;
+            this.dataLoggingView1.EnableTemperature1 = false;
+            this.dataLoggingView1.EnableTemperature2 = false;
+            this.dataLoggingView1.FMSTRArgs = null;
+            this.dataLoggingView1.HRModeArgs = null;
+            this.dataLoggingView1.Location = new System.Drawing.Point(0, 0);
+            this.dataLoggingView1.Margin = new System.Windows.Forms.Padding(4);
+            this.dataLoggingView1.MultiModeArgs = null;
+            this.dataLoggingView1.Name = "dataLoggingView1";
+            this.dataLoggingView1.PaceArgs = null;
+            this.dataLoggingView1.RToRArgs = null;
+            this.dataLoggingView1.Size = new System.Drawing.Size(953, 606);
+            this.dataLoggingView1.SpO2HRModeArgs = null;
+            this.dataLoggingView1.TabIndex = 0;
+            // 
+            // tpRegisters
+            // 
+            this.tpRegisters.Controls.Add(this.tableLayoutPanel1);
+            this.tpRegisters.Controls.Add(this.pnlRegMAX30205_U18);
+            this.tpRegisters.Controls.Add(this.pnlRegMAX14720);
+            this.tpRegisters.Controls.Add(this.pnlRegMAX30101);
+            this.tpRegisters.Controls.Add(this.pnlRegMAX30001);
+            this.tpRegisters.Controls.Add(this.pnlRegMAX30205);
+            this.tpRegisters.Controls.Add(this.pnlRegLIS2HD);
+            this.tpRegisters.Location = new System.Drawing.Point(4, 26);
+            this.tpRegisters.Name = "tpRegisters";
+            this.tpRegisters.Size = new System.Drawing.Size(953, 606);
+            this.tpRegisters.TabIndex = 11;
+            this.tpRegisters.Text = "Registers";
+            this.tpRegisters.UseVisualStyleBackColor = true;
+            // 
+            // tableLayoutPanel1
+            // 
+            this.tableLayoutPanel1.ColumnCount = 1;
+            this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 50F));
+            this.tableLayoutPanel1.Controls.Add(this.cboRegisterTabDevice, 0, 0);
+            this.tableLayoutPanel1.Dock = System.Windows.Forms.DockStyle.Top;
+            this.tableLayoutPanel1.Location = new System.Drawing.Point(0, 0);
+            this.tableLayoutPanel1.Name = "tableLayoutPanel1";
+            this.tableLayoutPanel1.RowCount = 1;
+            this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 50F));
+            this.tableLayoutPanel1.Size = new System.Drawing.Size(953, 42);
+            this.tableLayoutPanel1.TabIndex = 4;
+            // 
+            // cboRegisterTabDevice
+            // 
+            this.cboRegisterTabDevice.Anchor = System.Windows.Forms.AnchorStyles.Right;
+            this.cboRegisterTabDevice.BackColor = System.Drawing.Color.White;
+            this.cboRegisterTabDevice.DropDownHeight = 200;
+            this.cboRegisterTabDevice.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
+            this.cboRegisterTabDevice.DropDownWidth = 172;
+            this.cboRegisterTabDevice.Items.AddRange(new object[] {
+            "MAX30101",
+            "MAX30205 (Top)",
+            "MAX30205 (Bottom)",
+            "LIS2DH",
+            "MAX30001",
+            "MAX14720"});
+            this.cboRegisterTabDevice.Location = new System.Drawing.Point(778, 7);
+            this.cboRegisterTabDevice.Name = "cboRegisterTabDevice";
+            this.cboRegisterTabDevice.Size = new System.Drawing.Size(172, 28);
+            this.cboRegisterTabDevice.TabIndex = 1;
+            this.cboRegisterTabDevice.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
+            this.cboRegisterTabDevice.TextAlignDropDownList = System.Windows.Forms.HorizontalAlignment.Left;
+            this.cboRegisterTabDevice.SelectedIndexChanged += new System.EventHandler(this.cboRegisterTabDevice_SelectedIndexChanged);
+            // 
+            // pnlRegMAX30205_U18
+            // 
+            this.pnlRegMAX30205_U18.Controls.Add(this.rvMAX30205_U18);
+            this.pnlRegMAX30205_U18.Dock = System.Windows.Forms.DockStyle.Fill;
+            this.pnlRegMAX30205_U18.Location = new System.Drawing.Point(0, 0);
+            this.pnlRegMAX30205_U18.Name = "pnlRegMAX30205_U18";
+            this.pnlRegMAX30205_U18.Size = new System.Drawing.Size(953, 606);
+            this.pnlRegMAX30205_U18.TabIndex = 3;
+            // 
+            // rvMAX30205_U18
+            // 
+            this.rvMAX30205_U18.Connected = false;
+            this.rvMAX30205_U18.Dock = System.Windows.Forms.DockStyle.Fill;
+            this.rvMAX30205_U18.Location = new System.Drawing.Point(0, 0);
+            this.rvMAX30205_U18.Margin = new System.Windows.Forms.Padding(4);
+            this.rvMAX30205_U18.Name = "rvMAX30205_U18";
+            this.rvMAX30205_U18.Size = new System.Drawing.Size(953, 606);
+            this.rvMAX30205_U18.TabIndex = 0;
+            // 
+            // pnlRegMAX14720
+            // 
+            this.pnlRegMAX14720.Controls.Add(this.rvMAX14720);
+            this.pnlRegMAX14720.Dock = System.Windows.Forms.DockStyle.Fill;
+            this.pnlRegMAX14720.Location = new System.Drawing.Point(0, 0);
+            this.pnlRegMAX14720.Name = "pnlRegMAX14720";
+            this.pnlRegMAX14720.Size = new System.Drawing.Size(953, 606);
+            this.pnlRegMAX14720.TabIndex = 2;
+            // 
+            // rvMAX14720
+            // 
+            this.rvMAX14720.Connected = false;
+            this.rvMAX14720.Dock = System.Windows.Forms.DockStyle.Fill;
+            this.rvMAX14720.Location = new System.Drawing.Point(0, 0);
+            this.rvMAX14720.Margin = new System.Windows.Forms.Padding(4);
+            this.rvMAX14720.Name = "rvMAX14720";
+            this.rvMAX14720.Size = new System.Drawing.Size(953, 606);
+            this.rvMAX14720.TabIndex = 0;
+            // 
+            // pnlRegMAX30101
+            // 
+            this.pnlRegMAX30101.Controls.Add(this.rvMAX30101);
+            this.pnlRegMAX30101.Dock = System.Windows.Forms.DockStyle.Fill;
+            this.pnlRegMAX30101.Location = new System.Drawing.Point(0, 0);
+            this.pnlRegMAX30101.Name = "pnlRegMAX30101";
+            this.pnlRegMAX30101.Size = new System.Drawing.Size(953, 606);
+            this.pnlRegMAX30101.TabIndex = 0;
+            // 
+            // rvMAX30101
+            // 
+            this.rvMAX30101.Connected = false;
+            this.rvMAX30101.Dock = System.Windows.Forms.DockStyle.Fill;
+            this.rvMAX30101.Location = new System.Drawing.Point(0, 0);
+            this.rvMAX30101.Margin = new System.Windows.Forms.Padding(4);
+            this.rvMAX30101.Name = "rvMAX30101";
+            this.rvMAX30101.Size = new System.Drawing.Size(953, 606);
+            this.rvMAX30101.TabIndex = 1;
+            // 
+            // pnlRegMAX30001
+            // 
+            this.pnlRegMAX30001.Controls.Add(this.rvMAX30001);
+            this.pnlRegMAX30001.Dock = System.Windows.Forms.DockStyle.Fill;
+            this.pnlRegMAX30001.Location = new System.Drawing.Point(0, 0);
+            this.pnlRegMAX30001.Name = "pnlRegMAX30001";
+            this.pnlRegMAX30001.Size = new System.Drawing.Size(953, 606);
+            this.pnlRegMAX30001.TabIndex = 2;
+            // 
+            // rvMAX30001
+            // 
+            this.rvMAX30001.Connected = false;
+            this.rvMAX30001.Dock = System.Windows.Forms.DockStyle.Fill;
+            this.rvMAX30001.Location = new System.Drawing.Point(0, 0);
+            this.rvMAX30001.Margin = new System.Windows.Forms.Padding(4);
+            this.rvMAX30001.Name = "rvMAX30001";
+            this.rvMAX30001.Size = new System.Drawing.Size(953, 606);
+            this.rvMAX30001.TabIndex = 4;
+            // 
+            // pnlRegMAX30205
+            // 
+            this.pnlRegMAX30205.Controls.Add(this.rvMAX30205);
+            this.pnlRegMAX30205.Dock = System.Windows.Forms.DockStyle.Fill;
+            this.pnlRegMAX30205.Location = new System.Drawing.Point(0, 0);
+            this.pnlRegMAX30205.Name = "pnlRegMAX30205";
+            this.pnlRegMAX30205.Size = new System.Drawing.Size(953, 606);
+            this.pnlRegMAX30205.TabIndex = 1;
+            // 
+            // rvMAX30205
+            // 
+            this.rvMAX30205.Connected = false;
+            this.rvMAX30205.Dock = System.Windows.Forms.DockStyle.Fill;
+            this.rvMAX30205.Location = new System.Drawing.Point(0, 0);
+            this.rvMAX30205.Margin = new System.Windows.Forms.Padding(4);
+            this.rvMAX30205.Name = "rvMAX30205";
+            this.rvMAX30205.Size = new System.Drawing.Size(953, 606);
+            this.rvMAX30205.TabIndex = 3;
+            // 
+            // pnlRegLIS2HD
+            // 
+            this.pnlRegLIS2HD.Controls.Add(this.rvLIS2HD);
+            this.pnlRegLIS2HD.Dock = System.Windows.Forms.DockStyle.Fill;
+            this.pnlRegLIS2HD.Location = new System.Drawing.Point(0, 0);
+            this.pnlRegLIS2HD.Name = "pnlRegLIS2HD";
+            this.pnlRegLIS2HD.Size = new System.Drawing.Size(953, 606);
+            this.pnlRegLIS2HD.TabIndex = 2;
+            // 
+            // rvLIS2HD
+            // 
+            this.rvLIS2HD.Connected = false;
+            this.rvLIS2HD.Dock = System.Windows.Forms.DockStyle.Fill;
+            this.rvLIS2HD.Location = new System.Drawing.Point(0, 0);
+            this.rvLIS2HD.Margin = new System.Windows.Forms.Padding(4);
+            this.rvLIS2HD.Name = "rvLIS2HD";
+            this.rvLIS2HD.Size = new System.Drawing.Size(953, 606);
+            this.rvLIS2HD.TabIndex = 3;
+            // 
+            // tpPrimitives
+            // 
+            this.tpPrimitives.Controls.Add(this.primitivesView1);
+            this.tpPrimitives.Location = new System.Drawing.Point(4, 26);
+            this.tpPrimitives.Name = "tpPrimitives";
+            this.tpPrimitives.Padding = new System.Windows.Forms.Padding(3);
+            this.tpPrimitives.Size = new System.Drawing.Size(953, 606);
+            this.tpPrimitives.TabIndex = 0;
+            this.tpPrimitives.Text = "Advanced";
+            this.tpPrimitives.UseVisualStyleBackColor = true;
+            // 
+            // primitivesView1
+            // 
+            this.primitivesView1.BackColor = System.Drawing.Color.White;
+            this.primitivesView1.i2cDevice = null;
+            this.primitivesView1.lis2hd = null;
+            this.primitivesView1.Location = new System.Drawing.Point(8, 10);
+            this.primitivesView1.Margin = new System.Windows.Forms.Padding(4);
+            this.primitivesView1.max30001 = null;
+            this.primitivesView1.max30101 = null;
+            this.primitivesView1.max30205 = null;
+            this.primitivesView1.Name = "primitivesView1";
+            this.primitivesView1.rpcClient = null;
+            this.primitivesView1.Size = new System.Drawing.Size(1191, 607);
+            this.primitivesView1.spiDevice = null;
+            this.primitivesView1.TabIndex = 0;
+            // 
+            // label16
+            // 
+            this.label16.AutoSize = true;
+            this.label16.Font = new System.Drawing.Font("Arial", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+            this.label16.Location = new System.Drawing.Point(12, 43);
+            this.label16.Name = "label16";
+            this.label16.Size = new System.Drawing.Size(30, 15);
+            this.label16.TabIndex = 4;
+            this.label16.Text = "Red";
+            this.label16.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
+            // 
+            // label12
+            // 
+            this.label12.AutoSize = true;
+            this.label12.Font = new System.Drawing.Font("Arial", 9F);
+            this.label12.Location = new System.Drawing.Point(219, 29);
+            this.label12.Name = "label12";
+            this.label12.Size = new System.Drawing.Size(21, 15);
+            this.label12.TabIndex = 4;
+            this.label12.Text = "Hz";
+            this.label12.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
+            // 
+            // label13
+            // 
+            this.label13.AutoSize = true;
+            this.label13.Font = new System.Drawing.Font("Arial", 9F);
+            this.label13.Location = new System.Drawing.Point(219, 73);
+            this.label13.Name = "label13";
+            this.label13.Size = new System.Drawing.Size(21, 15);
+            this.label13.TabIndex = 4;
+            this.label13.Text = "µs";
+            this.label13.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
+            // 
+            // label14
+            // 
+            this.label14.AutoSize = true;
+            this.label14.Font = new System.Drawing.Font("Arial", 9F);
+            this.label14.Location = new System.Drawing.Point(219, 95);
+            this.label14.Name = "label14";
+            this.label14.Size = new System.Drawing.Size(21, 15);
+            this.label14.TabIndex = 4;
+            this.label14.Text = "nA";
+            this.label14.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
+            // 
+            // label15
+            // 
+            this.label15.AutoSize = true;
+            this.label15.Font = new System.Drawing.Font("Arial", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+            this.label15.Location = new System.Drawing.Point(11, 71);
+            this.label15.Name = "label15";
+            this.label15.Size = new System.Drawing.Size(76, 15);
+            this.label15.TabIndex = 4;
+            this.label15.Text = "Pulse Width:";
+            this.label15.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
+            // 
+            // label5
+            // 
+            this.label5.AutoSize = true;
+            this.label5.Font = new System.Drawing.Font("Arial", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+            this.label5.Location = new System.Drawing.Point(5, 107);
+            this.label5.Name = "label5";
+            this.label5.Size = new System.Drawing.Size(64, 15);
+            this.label5.TabIndex = 15;
+            this.label5.Text = "LED slot 4";
+            // 
+            // label9
+            // 
+            this.label9.AutoSize = true;
+            this.label9.Font = new System.Drawing.Font("Arial", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+            this.label9.Location = new System.Drawing.Point(11, 93);
+            this.label9.Name = "label9";
+            this.label9.Size = new System.Drawing.Size(129, 15);
+            this.label9.TabIndex = 25;
+            this.label9.Text = "ADC Full Scale Range";
+            this.label9.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
+            // 
+            // label10
+            // 
+            this.label10.AutoSize = true;
+            this.label10.Font = new System.Drawing.Font("Arial", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+            this.label10.Location = new System.Drawing.Point(11, 26);
+            this.label10.Name = "label10";
+            this.label10.Size = new System.Drawing.Size(82, 15);
+            this.label10.TabIndex = 4;
+            this.label10.Text = "Sample Rate:";
+            this.label10.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
+            // 
+            // label11
+            // 
+            this.label11.AutoSize = true;
+            this.label11.Font = new System.Drawing.Font("Arial", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+            this.label11.Location = new System.Drawing.Point(11, 48);
+            this.label11.Name = "label11";
+            this.label11.Size = new System.Drawing.Size(99, 15);
+            this.label11.TabIndex = 22;
+            this.label11.Text = "Sample Average:";
+            this.label11.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
+            // 
+            // label8
+            // 
+            this.label8.AutoSize = true;
+            this.label8.Font = new System.Drawing.Font("Arial", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+            this.label8.Location = new System.Drawing.Point(5, 32);
+            this.label8.Name = "label8";
+            this.label8.Size = new System.Drawing.Size(64, 15);
+            this.label8.TabIndex = 15;
+            this.label8.Text = "LED slot 1";
+            // 
+            // label4
+            // 
+            this.label4.AutoSize = true;
+            this.label4.Font = new System.Drawing.Font("Arial", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+            this.label4.Location = new System.Drawing.Point(177, 26);
+            this.label4.Name = "label4";
+            this.label4.Size = new System.Drawing.Size(19, 15);
+            this.label4.TabIndex = 19;
+            this.label4.Text = "---";
+            this.label4.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
+            // 
+            // label6
+            // 
+            this.label6.AutoSize = true;
+            this.label6.Font = new System.Drawing.Font("Arial", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+            this.label6.Location = new System.Drawing.Point(5, 83);
+            this.label6.Name = "label6";
+            this.label6.Size = new System.Drawing.Size(64, 15);
+            this.label6.TabIndex = 15;
+            this.label6.Text = "LED slot 3";
+            // 
+            // label7
+            // 
+            this.label7.AutoSize = true;
+            this.label7.Font = new System.Drawing.Font("Arial", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+            this.label7.Location = new System.Drawing.Point(5, 57);
+            this.label7.Name = "label7";
+            this.label7.Size = new System.Drawing.Size(64, 15);
+            this.label7.TabIndex = 15;
+            this.label7.Text = "LED slot 2";
+            // 
+            // label17
+            // 
+            this.label17.AutoSize = true;
+            this.label17.Font = new System.Drawing.Font("Arial", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+            this.label17.Location = new System.Drawing.Point(12, 87);
+            this.label17.Name = "label17";
+            this.label17.Size = new System.Drawing.Size(41, 15);
+            this.label17.TabIndex = 4;
+            this.label17.Text = "Green";
+            this.label17.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
+            // 
+            // label18
+            // 
+            this.label18.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
+            this.label18.AutoSize = true;
+            this.label18.Font = new System.Drawing.Font("Arial", 9F);
+            this.label18.Location = new System.Drawing.Point(208, 43);
+            this.label18.Name = "label18";
+            this.label18.Size = new System.Drawing.Size(25, 15);
+            this.label18.TabIndex = 4;
+            this.label18.Text = "mA";
+            this.label18.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
+            // 
+            // label19
+            // 
+            this.label19.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
+            this.label19.AutoSize = true;
+            this.label19.Font = new System.Drawing.Font("Arial", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+            this.label19.Location = new System.Drawing.Point(178, 24);
+            this.label19.Name = "label19";
+            this.label19.Size = new System.Drawing.Size(51, 15);
+            this.label19.TabIndex = 4;
+            this.label19.Text = "Average";
+            this.label19.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
+            // 
+            // label20
+            // 
+            this.label20.AutoSize = true;
+            this.label20.Font = new System.Drawing.Font("Arial", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+            this.label20.Location = new System.Drawing.Point(12, 24);
+            this.label20.Name = "label20";
+            this.label20.Size = new System.Drawing.Size(61, 15);
+            this.label20.TabIndex = 4;
+            this.label20.Text = "LED color";
+            this.label20.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
+            // 
+            // label22
+            // 
+            this.label22.AutoSize = true;
+            this.label22.Font = new System.Drawing.Font("Arial", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+            this.label22.Location = new System.Drawing.Point(12, 65);
+            this.label22.Name = "label22";
+            this.label22.Size = new System.Drawing.Size(72, 15);
+            this.label22.TabIndex = 4;
+            this.label22.Text = "IR (Infrared)";
+            this.label22.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
+            // 
+            // label3
+            // 
+            this.label3.AutoSize = true;
+            this.label3.Font = new System.Drawing.Font("Arial", 9F);
+            this.label3.Location = new System.Drawing.Point(208, 26);
+            this.label3.Name = "label3";
+            this.label3.Size = new System.Drawing.Size(25, 15);
+            this.label3.TabIndex = 18;
+            this.label3.Text = "mA";
+            this.label3.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
+            // 
+            // label2
+            // 
+            this.label2.AutoSize = true;
+            this.label2.Font = new System.Drawing.Font("Arial", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+            this.label2.Location = new System.Drawing.Point(12, 26);
+            this.label2.Name = "label2";
+            this.label2.Size = new System.Drawing.Size(62, 15);
+            this.label2.TabIndex = 4;
+            this.label2.Text = "PILOT_PA";
+            this.label2.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
+            // 
+            // label23
+            // 
+            this.label23.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
+            this.label23.AutoSize = true;
+            this.label23.Font = new System.Drawing.Font("Arial", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+            this.label23.Location = new System.Drawing.Point(178, 65);
+            this.label23.Name = "label23";
+            this.label23.Size = new System.Drawing.Size(19, 15);
+            this.label23.TabIndex = 16;
+            this.label23.Text = "---";
+            this.label23.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
+            // 
+            // label24
+            // 
+            this.label24.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
+            this.label24.AutoSize = true;
+            this.label24.Font = new System.Drawing.Font("Arial", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+            this.label24.Location = new System.Drawing.Point(178, 87);
+            this.label24.Name = "label24";
+            this.label24.Size = new System.Drawing.Size(19, 15);
+            this.label24.TabIndex = 19;
+            this.label24.Text = "---";
+            this.label24.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
+            // 
+            // chart1
+            // 
+            this.chart1.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) 
+            | System.Windows.Forms.AnchorStyles.Left) 
+            | System.Windows.Forms.AnchorStyles.Right)));
+            chartArea1.AxisY.Title = "Accelerometer X";
+            chartArea1.Name = "ChartArea4AccelX";
+            chartArea2.AlignWithChartArea = "ChartArea4AccelX";
+            chartArea2.AxisY.Title = "Accelerometer Y";
+            chartArea2.Name = "ChartArea5AccelY";
+            chartArea3.AlignWithChartArea = "ChartArea4AccelX";
+            chartArea3.AxisY.Title = "Accelerometer Z";
+            chartArea3.Name = "ChartArea6AccelZ";
+            this.chart1.ChartAreas.Add(chartArea1);
+            this.chart1.ChartAreas.Add(chartArea2);
+            this.chart1.ChartAreas.Add(chartArea3);
+            this.chart1.Location = new System.Drawing.Point(54, 35);
+            this.chart1.Name = "chart1";
+            series1.ChartArea = "ChartArea4AccelX";
+            series1.ChartType = System.Windows.Forms.DataVisualization.Charting.SeriesChartType.Line;
+            series1.Color = System.Drawing.Color.Cyan;
+            series1.MarkerSize = 1;
+            series1.Name = "SeriesAccelX";
+            series1.XValueType = System.Windows.Forms.DataVisualization.Charting.ChartValueType.UInt32;
+            series1.YValueType = System.Windows.Forms.DataVisualization.Charting.ChartValueType.Int32;
+            series2.ChartArea = "ChartArea5AccelY";
+            series2.ChartType = System.Windows.Forms.DataVisualization.Charting.SeriesChartType.Line;
+            series2.Color = System.Drawing.Color.Magenta;
+            series2.Name = "SeriesAccelY";
+            series2.XValueType = System.Windows.Forms.DataVisualization.Charting.ChartValueType.UInt32;
+            series2.YValueType = System.Windows.Forms.DataVisualization.Charting.ChartValueType.Int32;
+            series3.ChartArea = "ChartArea6AccelZ";
+            series3.ChartType = System.Windows.Forms.DataVisualization.Charting.SeriesChartType.Line;
+            series3.Color = System.Drawing.Color.Brown;
+            series3.Name = "SeriesAccelZ";
+            series3.XValueType = System.Windows.Forms.DataVisualization.Charting.ChartValueType.UInt32;
+            series3.YValueType = System.Windows.Forms.DataVisualization.Charting.ChartValueType.Int32;
+            this.chart1.Series.Add(series1);
+            this.chart1.Series.Add(series2);
+            this.chart1.Series.Add(series3);
+            this.chart1.Size = new System.Drawing.Size(343, 526);
+            this.chart1.TabIndex = 32;
+            this.chart1.Text = "chart1";
+            title1.Name = "Title1";
+            title1.Text = "Red";
+            title1.Visible = false;
+            this.chart1.Titles.Add(title1);
+            // 
+            // maximGroupBox2
+            // 
+            this.maximGroupBox2.BackgroundColor = System.Drawing.Color.White;
+            this.maximGroupBox2.Location = new System.Drawing.Point(3, 256);
+            this.maximGroupBox2.Name = "maximGroupBox2";
+            this.maximGroupBox2.Size = new System.Drawing.Size(248, 78);
+            this.maximGroupBox2.TabIndex = 37;
+            this.maximGroupBox2.TabStop = false;
+            this.maximGroupBox2.Text = "Proximity";
+            // 
+            // numericUpDown1
+            // 
+            this.numericUpDown1.Hexadecimal = true;
+            this.numericUpDown1.Location = new System.Drawing.Point(148, 52);
+            this.numericUpDown1.Maximum = new decimal(new int[] {
+            255,
+            0,
+            0,
+            0});
+            this.numericUpDown1.Name = "numericUpDown1";
+            this.numericUpDown1.Size = new System.Drawing.Size(55, 20);
+            this.numericUpDown1.TabIndex = 14;
+            this.numericUpDown1.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
+            this.numericUpDown1.Value = new decimal(new int[] {
+            255,
+            0,
+            0,
+            0});
+            // 
+            // comboBox1
+            // 
+            this.comboBox1.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
+            this.comboBox1.Font = new System.Drawing.Font("Arial", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+            this.comboBox1.FormattingEnabled = true;
+            this.comboBox1.Location = new System.Drawing.Point(90, 25);
+            this.comboBox1.MaxDropDownItems = 10;
+            this.comboBox1.Name = "comboBox1";
+            this.comboBox1.Size = new System.Drawing.Size(81, 23);
+            this.comboBox1.TabIndex = 0;
+            // 
+            // maximGroupBox3
+            // 
+            this.maximGroupBox3.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) 
+            | System.Windows.Forms.AnchorStyles.Left)));
+            this.maximGroupBox3.BackgroundColor = System.Drawing.Color.White;
+            this.maximGroupBox3.Location = new System.Drawing.Point(257, 11);
+            this.maximGroupBox3.Name = "maximGroupBox3";
+            this.maximGroupBox3.Size = new System.Drawing.Size(355, 577);
+            this.maximGroupBox3.TabIndex = 36;
+            this.maximGroupBox3.TabStop = false;
+            this.maximGroupBox3.Text = "Optical Measurements";
+            // 
+            // chart2
+            // 
+            this.chart2.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) 
+            | System.Windows.Forms.AnchorStyles.Left) 
+            | System.Windows.Forms.AnchorStyles.Right)));
+            chartArea4.AxisY.Title = "Red ADC Code";
+            chartArea4.Name = "ChartArea1Red";
+            chartArea5.AlignWithChartArea = "ChartArea1Red";
+            chartArea5.AxisY.Title = "IR ADC Code";
+            chartArea5.Name = "ChartArea2IR";
+            chartArea6.AlignWithChartArea = "ChartArea1Red";
+            chartArea6.AxisY.Title = "Green ADC Code";
+            chartArea6.Name = "ChartArea3Green";
+            this.chart2.ChartAreas.Add(chartArea4);
+            this.chart2.ChartAreas.Add(chartArea5);
+            this.chart2.ChartAreas.Add(chartArea6);
+            this.chart2.Location = new System.Drawing.Point(11, 35);
+            this.chart2.Name = "chart2";
+            series4.ChartArea = "ChartArea1Red";
+            series4.ChartType = System.Windows.Forms.DataVisualization.Charting.SeriesChartType.Line;
+            series4.Color = System.Drawing.Color.DarkRed;
+            series4.MarkerSize = 1;
+            series4.Name = "SeriesRed";
+            series4.XValueType = System.Windows.Forms.DataVisualization.Charting.ChartValueType.UInt32;
+            series4.YValueType = System.Windows.Forms.DataVisualization.Charting.ChartValueType.Int32;
+            series5.ChartArea = "ChartArea2IR";
+            series5.ChartType = System.Windows.Forms.DataVisualization.Charting.SeriesChartType.Line;
+            series5.Color = System.Drawing.Color.FromArgb(((int)(((byte)(110)))), ((int)(((byte)(37)))), ((int)(((byte)(133)))));
+            series5.Name = "SeriesIR";
+            series5.XValueType = System.Windows.Forms.DataVisualization.Charting.ChartValueType.UInt32;
+            series5.YValueType = System.Windows.Forms.DataVisualization.Charting.ChartValueType.Int32;
+            series6.ChartArea = "ChartArea3Green";
+            series6.ChartType = System.Windows.Forms.DataVisualization.Charting.SeriesChartType.Line;
+            series6.Color = System.Drawing.Color.Green;
+            series6.Name = "SeriesGreen";
+            series6.XValueType = System.Windows.Forms.DataVisualization.Charting.ChartValueType.UInt32;
+            series6.YValueType = System.Windows.Forms.DataVisualization.Charting.ChartValueType.Int32;
+            this.chart2.Series.Add(series4);
+            this.chart2.Series.Add(series5);
+            this.chart2.Series.Add(series6);
+            this.chart2.Size = new System.Drawing.Size(327, 526);
+            this.chart2.TabIndex = 31;
+            this.chart2.Text = "chartLED";
+            title2.Name = "Title1";
+            title2.Text = "Red";
+            title2.Visible = false;
+            this.chart2.Titles.Add(title2);
+            // 
+            // maximGroupBox4
+            // 
+            this.maximGroupBox4.BackgroundColor = System.Drawing.Color.White;
+            this.maximGroupBox4.Location = new System.Drawing.Point(3, 335);
+            this.maximGroupBox4.Name = "maximGroupBox4";
+            this.maximGroupBox4.Size = new System.Drawing.Size(248, 131);
+            this.maximGroupBox4.TabIndex = 34;
+            this.maximGroupBox4.TabStop = false;
+            this.maximGroupBox4.Text = "LED Mode: Timing Slots";
+            // 
+            // comboBox2
+            // 
+            this.comboBox2.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) 
+            | System.Windows.Forms.AnchorStyles.Right)));
+            this.comboBox2.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
+            this.comboBox2.Font = new System.Drawing.Font("Arial", 9F);
+            this.comboBox2.FormattingEnabled = true;
+            this.comboBox2.Items.AddRange(new object[] {
+            "0 Disabled",
+            "1 LED1 (RED)",
+            "2 LED2 (IR)",
+            "3 LED3 (Green)",
+            "4 LED4 (Green)",
+            "5 LED1 Pilot",
+            "6 LED2 Pilot",
+            "7 Reserved",
+            "0 Disabled",
+            "1 LED1 (RED)",
+            "2 LED2 (IR)",
+            "3 LED3 (Green)",
+            "4 LED4 (Green)",
+            "5 LED1 Pilot",
+            "6 LED2 Pilot",
+            "7 Reserved",
+            "0 Disabled",
+            "1 LED1 (RED)",
+            "2 LED2 (IR)",
+            "3 LED3 (Green)",
+            "4 LED4 (Green)",
+            "5 LED1 Pilot",
+            "6 LED2 Pilot",
+            "7 Reserved",
+            "0 Disabled",
+            "1 LED1 (RED)",
+            "2 LED2 (IR)",
+            "3 LED3 (Green)",
+            "4 LED4 (Green)",
+            "5 LED1 Pilot",
+            "6 LED2 Pilot",
+            "7 Reserved",
+            "0 Disabled",
+            "1 LED1 (RED)",
+            "2 LED2 (IR)",
+            "3 LED3 (Green)",
+            "4 LED4 (Green)",
+            "5 LED1 Pilot",
+            "6 LED2 Pilot",
+            "7 Reserved",
+            "0 Disabled",
+            "1 LED1 (RED)",
+            "2 LED2 (IR)",
+            "3 LED3 (Green)",
+            "4 LED4 (Green)",
+            "5 LED1 Pilot",
+            "6 LED2 Pilot",
+            "7 Reserved",
+            "0 Disabled",
+            "1 LED1 (RED)",
+            "2 LED2 (IR)",
+            "3 LED3 (Green)",
+            "4 LED4 (Green)",
+            "5 LED1 Pilot",
+            "6 LED2 Pilot",
+            "7 Reserved",
+            "0 Disabled",
+            "1 LED1 (RED)",
+            "2 LED2 (IR)",
+            "3 LED3 (Green)",
+            "4 LED4 (Green)",
+            "5 LED1 Pilot",
+            "6 LED2 Pilot",
+            "7 Reserved",
+            "0 Disabled",
+            "1 LED1 (RED)",
+            "2 LED2 (IR)",
+            "3 LED3 (Green)",
+            "4 LED4 (Green)",
+            "5 LED1 Pilot",
+            "6 LED2 Pilot",
+            "7 Reserved",
+            "0 Disabled",
+            "1 LED1 (RED)",
+            "2 LED2 (IR)",
+            "3 LED3 (Green)",
+            "4 LED4 (Green)",
+            "5 LED1 Pilot",
+            "6 LED2 Pilot",
+            "7 Reserved",
+            "0 Disabled",
+            "1 LED1 (RED)",
+            "2 LED2 (IR)",
+            "3 LED3 (Green)",
+            "4 LED4 (Green)",
+            "5 LED1 Pilot",
+            "6 LED2 Pilot",
+            "7 Reserved",
+            "0 Disabled",
+            "1 LED1 (RED)",
+            "2 LED2 (IR)",
+            "3 LED3 (Green)",
+            "4 LED4 (Green)",
+            "5 LED1 Pilot",
+            "6 LED2 Pilot",
+            "7 Reserved",
+            "0 Disabled",
+            "1 LED1 (RED)",
+            "2 LED2 (IR)",
+            "3 LED3 (Green)",
+            "4 LED4 (Green)",
+            "5 LED1 Pilot",
+            "6 LED2 Pilot",
+            "7 Reserved",
+            "0 Disabled",
+            "1 LED1 (RED)",
+            "2 LED2 (IR)",
+            "3 LED3 (Green)",
+            "4 LED4 (Green)",
+            "5 LED1 Pilot",
+            "6 LED2 Pilot",
+            "7 Reserved",
+            "0 Disabled",
+            "1 LED1 (RED)",
+            "2 LED2 (IR)",
+            "3 LED3 (Green)",
+            "4 LED4 (Green)",
+            "5 LED1 Pilot",
+            "6 LED2 Pilot",
+            "7 Reserved",
+            "0 Disabled",
+            "1 LED1 (RED)",
+            "2 LED2 (IR)",
+            "3 LED3 (Green)",
+            "4 LED4 (Green)",
+            "5 LED1 Pilot",
+            "6 LED2 Pilot",
+            "7 Reserved"});
+            this.comboBox2.Location = new System.Drawing.Point(80, 29);
+            this.comboBox2.Name = "comboBox2";
+            this.comboBox2.Size = new System.Drawing.Size(160, 23);
+            this.comboBox2.TabIndex = 14;
+            // 
+            // comboBox3
+            // 
+            this.comboBox3.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) 
+            | System.Windows.Forms.AnchorStyles.Right)));
+            this.comboBox3.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
+            this.comboBox3.Font = new System.Drawing.Font("Arial", 9F);
+            this.comboBox3.FormattingEnabled = true;
+            this.comboBox3.Items.AddRange(new object[] {
+            "0 Disabled",
+            "1 LED1 (RED)",
+            "2 LED2 (IR)",
+            "3 LED3 (Green)",
+            "4 LED4 (Green)",
+            "5 LED1 Pilot",
+            "6 LED2 Pilot",
+            "7 Reserved",
+            "0 Disabled",
+            "1 LED1 (RED)",
+            "2 LED2 (IR)",
+            "3 LED3 (Green)",
+            "4 LED4 (Green)",
+            "5 LED1 Pilot",
+            "6 LED2 Pilot",
+            "7 Reserved",
+            "0 Disabled",
+            "1 LED1 (RED)",
+            "2 LED2 (IR)",
+            "3 LED3 (Green)",
+            "4 LED4 (Green)",
+            "5 LED1 Pilot",
+            "6 LED2 Pilot",
+            "7 Reserved",
+            "0 Disabled",
+            "1 LED1 (RED)",
+            "2 LED2 (IR)",
+            "3 LED3 (Green)",
+            "4 LED4 (Green)",
+            "5 LED1 Pilot",
+            "6 LED2 Pilot",
+            "7 Reserved",
+            "0 Disabled",
+            "1 LED1 (RED)",
+            "2 LED2 (IR)",
+            "3 LED3 (Green)",
+            "4 LED4 (Green)",
+            "5 LED1 Pilot",
+            "6 LED2 Pilot",
+            "7 Reserved",
+            "0 Disabled",
+            "1 LED1 (RED)",
+            "2 LED2 (IR)",
+            "3 LED3 (Green)",
+            "4 LED4 (Green)",
+            "5 LED1 Pilot",
+            "6 LED2 Pilot",
+            "7 Reserved",
+            "0 Disabled",
+            "1 LED1 (RED)",
+            "2 LED2 (IR)",
+            "3 LED3 (Green)",
+            "4 LED4 (Green)",
+            "5 LED1 Pilot",
+            "6 LED2 Pilot",
+            "7 Reserved",
+            "0 Disabled",
+            "1 LED1 (RED)",
+            "2 LED2 (IR)",
+            "3 LED3 (Green)",
+            "4 LED4 (Green)",
+            "5 LED1 Pilot",
+            "6 LED2 Pilot",
+            "7 Reserved",
+            "0 Disabled",
+            "1 LED1 (RED)",
+            "2 LED2 (IR)",
+            "3 LED3 (Green)",
+            "4 LED4 (Green)",
+            "5 LED1 Pilot",
+            "6 LED2 Pilot",
+            "7 Reserved",
+            "0 Disabled",
+            "1 LED1 (RED)",
+            "2 LED2 (IR)",
+            "3 LED3 (Green)",
+            "4 LED4 (Green)",
+            "5 LED1 Pilot",
+            "6 LED2 Pilot",
+            "7 Reserved",
+            "0 Disabled",
+            "1 LED1 (RED)",
+            "2 LED2 (IR)",
+            "3 LED3 (Green)",
+            "4 LED4 (Green)",
+            "5 LED1 Pilot",
+            "6 LED2 Pilot",
+            "7 Reserved",
+            "0 Disabled",
+            "1 LED1 (RED)",
+            "2 LED2 (IR)",
+            "3 LED3 (Green)",
+            "4 LED4 (Green)",
+            "5 LED1 Pilot",
+            "6 LED2 Pilot",
+            "7 Reserved",
+            "0 Disabled",
+            "1 LED1 (RED)",
+            "2 LED2 (IR)",
+            "3 LED3 (Green)",
+            "4 LED4 (Green)",
+            "5 LED1 Pilot",
+            "6 LED2 Pilot",
+            "7 Reserved",
+            "0 Disabled",
+            "1 LED1 (RED)",
+            "2 LED2 (IR)",
+            "3 LED3 (Green)",
+            "4 LED4 (Green)",
+            "5 LED1 Pilot",
+            "6 LED2 Pilot",
+            "7 Reserved",
+            "0 Disabled",
+            "1 LED1 (RED)",
+            "2 LED2 (IR)",
+            "3 LED3 (Green)",
+            "4 LED4 (Green)",
+            "5 LED1 Pilot",
+            "6 LED2 Pilot",
+            "7 Reserved"});
+            this.comboBox3.Location = new System.Drawing.Point(80, 54);
+            this.comboBox3.Name = "comboBox3";
+            this.comboBox3.Size = new System.Drawing.Size(160, 23);
+            this.comboBox3.TabIndex = 14;
+            // 
+            // comboBox4
+            // 
+            this.comboBox4.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) 
+            | System.Windows.Forms.AnchorStyles.Right)));
+            this.comboBox4.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
+            this.comboBox4.Font = new System.Drawing.Font("Arial", 9F);
+            this.comboBox4.FormattingEnabled = true;
+            this.comboBox4.Items.AddRange(new object[] {
+            "0 Disabled",
+            "1 LED1 (RED)",
+            "2 LED2 (IR)",
+            "3 LED3 (Green)",
+            "4 LED4 (Green)",
+            "5 LED1 Pilot",
+            "6 LED2 Pilot",
+            "7 Reserved",
+            "0 Disabled",
+            "1 LED1 (RED)",
+            "2 LED2 (IR)",
+            "3 LED3 (Green)",
+            "4 LED4 (Green)",
+            "5 LED1 Pilot",
+            "6 LED2 Pilot",
+            "7 Reserved",
+            "0 Disabled",
+            "1 LED1 (RED)",
+            "2 LED2 (IR)",
+            "3 LED3 (Green)",
+            "4 LED4 (Green)",
+            "5 LED1 Pilot",
+            "6 LED2 Pilot",
+            "7 Reserved",
+            "0 Disabled",
+            "1 LED1 (RED)",
+            "2 LED2 (IR)",
+            "3 LED3 (Green)",
+            "4 LED4 (Green)",
+            "5 LED1 Pilot",
+            "6 LED2 Pilot",
+            "7 Reserved",
+            "0 Disabled",
+            "1 LED1 (RED)",
+            "2 LED2 (IR)",
+            "3 LED3 (Green)",
+            "4 LED4 (Green)",
+            "5 LED1 Pilot",
+            "6 LED2 Pilot",
+            "7 Reserved",
+            "0 Disabled",
+            "1 LED1 (RED)",
+            "2 LED2 (IR)",
+            "3 LED3 (Green)",
+            "4 LED4 (Green)",
+            "5 LED1 Pilot",
+            "6 LED2 Pilot",
+            "7 Reserved",
+            "0 Disabled",
+            "1 LED1 (RED)",
+            "2 LED2 (IR)",
+            "3 LED3 (Green)",
+            "4 LED4 (Green)",
+            "5 LED1 Pilot",
+            "6 LED2 Pilot",
+            "7 Reserved",
+            "0 Disabled",
+            "1 LED1 (RED)",
+            "2 LED2 (IR)",
+            "3 LED3 (Green)",
+            "4 LED4 (Green)",
+            "5 LED1 Pilot",
+            "6 LED2 Pilot",
+            "7 Reserved",
+            "0 Disabled",
+            "1 LED1 (RED)",
+            "2 LED2 (IR)",
+            "3 LED3 (Green)",
+            "4 LED4 (Green)",
+            "5 LED1 Pilot",
+            "6 LED2 Pilot",
+            "7 Reserved",
+            "0 Disabled",
+            "1 LED1 (RED)",
+            "2 LED2 (IR)",
+            "3 LED3 (Green)",
+            "4 LED4 (Green)",
+            "5 LED1 Pilot",
+            "6 LED2 Pilot",
+            "7 Reserved",
+            "0 Disabled",
+            "1 LED1 (RED)",
+            "2 LED2 (IR)",
+            "3 LED3 (Green)",
+            "4 LED4 (Green)",
+            "5 LED1 Pilot",
+            "6 LED2 Pilot",
+            "7 Reserved",
+            "0 Disabled",
+            "1 LED1 (RED)",
+            "2 LED2 (IR)",
+            "3 LED3 (Green)",
+            "4 LED4 (Green)",
+            "5 LED1 Pilot",
+            "6 LED2 Pilot",
+            "7 Reserved",
+            "0 Disabled",
+            "1 LED1 (RED)",
+            "2 LED2 (IR)",
+            "3 LED3 (Green)",
+            "4 LED4 (Green)",
+            "5 LED1 Pilot",
+            "6 LED2 Pilot",
+            "7 Reserved"});
+            this.comboBox4.Location = new System.Drawing.Point(80, 79);
+            this.comboBox4.Name = "comboBox4";
+            this.comboBox4.Size = new System.Drawing.Size(160, 23);
+            this.comboBox4.TabIndex = 14;
+            // 
+            // comboBox5
+            // 
+            this.comboBox5.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) 
+            | System.Windows.Forms.AnchorStyles.Right)));
+            this.comboBox5.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
+            this.comboBox5.Font = new System.Drawing.Font("Arial", 9F);
+            this.comboBox5.FormattingEnabled = true;
+            this.comboBox5.Items.AddRange(new object[] {
+            "0 Disabled",
+            "1 LED1 (RED)",
+            "2 LED2 (IR)",
+            "3 LED3 (Green)",
+            "4 LED4 (Green)",
+            "5 LED1 Pilot",
+            "6 LED2 Pilot",
+            "7 Reserved",
+            "0 Disabled",
+            "1 LED1 (RED)",
+            "2 LED2 (IR)",
+            "3 LED3 (Green)",
+            "4 LED4 (Green)",
+            "5 LED1 Pilot",
+            "6 LED2 Pilot",
+            "7 Reserved",
+            "0 Disabled",
+            "1 LED1 (RED)",
+            "2 LED2 (IR)",
+            "3 LED3 (Green)",
+            "4 LED4 (Green)",
+            "5 LED1 Pilot",
+            "6 LED2 Pilot",
+            "7 Reserved",
+            "0 Disabled",
+            "1 LED1 (RED)",
+            "2 LED2 (IR)",
+            "3 LED3 (Green)",
+            "4 LED4 (Green)",
+            "5 LED1 Pilot",
+            "6 LED2 Pilot",
+            "7 Reserved",
+            "0 Disabled",
+            "1 LED1 (RED)",
+            "2 LED2 (IR)",
+            "3 LED3 (Green)",
+            "4 LED4 (Green)",
+            "5 LED1 Pilot",
+            "6 LED2 Pilot",
+            "7 Reserved",
+            "0 Disabled",
+            "1 LED1 (RED)",
+            "2 LED2 (IR)",
+            "3 LED3 (Green)",
+            "4 LED4 (Green)",
+            "5 LED1 Pilot",
+            "6 LED2 Pilot",
+            "7 Reserved",
+            "0 Disabled",
+            "1 LED1 (RED)",
+            "2 LED2 (IR)",
+            "3 LED3 (Green)",
+            "4 LED4 (Green)",
+            "5 LED1 Pilot",
+            "6 LED2 Pilot",
+            "7 Reserved",
+            "0 Disabled",
+            "1 LED1 (RED)",
+            "2 LED2 (IR)",
+            "3 LED3 (Green)",
+            "4 LED4 (Green)",
+            "5 LED1 Pilot",
+            "6 LED2 Pilot",
+            "7 Reserved",
+            "0 Disabled",
+            "1 LED1 (RED)",
+            "2 LED2 (IR)",
+            "3 LED3 (Green)",
+            "4 LED4 (Green)",
+            "5 LED1 Pilot",
+            "6 LED2 Pilot",
+            "7 Reserved",
+            "0 Disabled",
+            "1 LED1 (RED)",
+            "2 LED2 (IR)",
+            "3 LED3 (Green)",
+            "4 LED4 (Green)",
+            "5 LED1 Pilot",
+            "6 LED2 Pilot",
+            "7 Reserved",
+            "0 Disabled",
+            "1 LED1 (RED)",
+            "2 LED2 (IR)",
+            "3 LED3 (Green)",
+            "4 LED4 (Green)",
+            "5 LED1 Pilot",
+            "6 LED2 Pilot",
+            "7 Reserved"});
+            this.comboBox5.Location = new System.Drawing.Point(80, 104);
+            this.comboBox5.Name = "comboBox5";
+            this.comboBox5.Size = new System.Drawing.Size(160, 23);
+            this.comboBox5.TabIndex = 14;
+            // 
+            // maximGroupBox5
+            // 
+            this.maximGroupBox5.BackgroundColor = System.Drawing.Color.White;
+            this.maximGroupBox5.Location = new System.Drawing.Point(3, 25);
+            this.maximGroupBox5.Name = "maximGroupBox5";
+            this.maximGroupBox5.Size = new System.Drawing.Size(248, 119);
+            this.maximGroupBox5.TabIndex = 35;
+            this.maximGroupBox5.TabStop = false;
+            this.maximGroupBox5.Text = "Settings";
+            // 
+            // comboBox6
+            // 
+            this.comboBox6.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
+            this.comboBox6.Font = new System.Drawing.Font("Arial", 9F);
+            this.comboBox6.FormattingEnabled = true;
+            this.comboBox6.Location = new System.Drawing.Point(145, 92);
+            this.comboBox6.MaxDropDownItems = 10;
+            this.comboBox6.Name = "comboBox6";
+            this.comboBox6.Size = new System.Drawing.Size(70, 23);
+            this.comboBox6.TabIndex = 20;
+            // 
+            // comboBox7
+            // 
+            this.comboBox7.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
+            this.comboBox7.Font = new System.Drawing.Font("Arial", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+            this.comboBox7.FormattingEnabled = true;
+            this.comboBox7.Location = new System.Drawing.Point(145, 48);
+            this.comboBox7.MaxDropDownItems = 10;
+            this.comboBox7.Name = "comboBox7";
+            this.comboBox7.Size = new System.Drawing.Size(70, 23);
+            this.comboBox7.TabIndex = 12;
+            // 
+            // comboBox8
+            // 
+            this.comboBox8.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
+            this.comboBox8.Font = new System.Drawing.Font("Arial", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+            this.comboBox8.FormattingEnabled = true;
+            this.comboBox8.Location = new System.Drawing.Point(145, 26);
+            this.comboBox8.MaxDropDownItems = 10;
+            this.comboBox8.Name = "comboBox8";
+            this.comboBox8.Size = new System.Drawing.Size(70, 23);
+            this.comboBox8.TabIndex = 0;
+            // 
+            // comboBox9
+            // 
+            this.comboBox9.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
+            this.comboBox9.Font = new System.Drawing.Font("Arial", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+            this.comboBox9.FormattingEnabled = true;
+            this.comboBox9.Location = new System.Drawing.Point(145, 70);
+            this.comboBox9.MaxDropDownItems = 10;
+            this.comboBox9.Name = "comboBox9";
+            this.comboBox9.Size = new System.Drawing.Size(70, 23);
+            this.comboBox9.TabIndex = 0;
+            // 
+            // maximGroupBox6
+            // 
+            this.maximGroupBox6.BackgroundColor = System.Drawing.Color.White;
+            this.maximGroupBox6.Location = new System.Drawing.Point(3, 145);
+            this.maximGroupBox6.Name = "maximGroupBox6";
+            this.maximGroupBox6.Size = new System.Drawing.Size(248, 110);
+            this.maximGroupBox6.TabIndex = 33;
+            this.maximGroupBox6.TabStop = false;
+            this.maximGroupBox6.Text = "LED Currents";
+            // 
+            // comboBox10
+            // 
+            this.comboBox10.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
+            this.comboBox10.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
+            this.comboBox10.Font = new System.Drawing.Font("Arial", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+            this.comboBox10.FormattingEnabled = true;
+            this.comboBox10.Location = new System.Drawing.Point(90, 64);
+            this.comboBox10.MaxDropDownItems = 10;
+            this.comboBox10.Name = "comboBox10";
+            this.comboBox10.Size = new System.Drawing.Size(81, 23);
+            this.comboBox10.TabIndex = 0;
+            // 
+            // comboBox11
+            // 
+            this.comboBox11.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
+            this.comboBox11.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
+            this.comboBox11.Font = new System.Drawing.Font("Arial", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+            this.comboBox11.FormattingEnabled = true;
+            this.comboBox11.Location = new System.Drawing.Point(90, 42);
+            this.comboBox11.MaxDropDownItems = 10;
+            this.comboBox11.Name = "comboBox11";
+            this.comboBox11.Size = new System.Drawing.Size(81, 23);
+            this.comboBox11.TabIndex = 0;
+            // 
+            // comboBox12
+            // 
+            this.comboBox12.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
+            this.comboBox12.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
+            this.comboBox12.Font = new System.Drawing.Font("Arial", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+            this.comboBox12.FormattingEnabled = true;
+            this.comboBox12.Location = new System.Drawing.Point(90, 86);
+            this.comboBox12.MaxDropDownItems = 10;
+            this.comboBox12.Name = "comboBox12";
+            this.comboBox12.Size = new System.Drawing.Size(81, 23);
+            this.comboBox12.TabIndex = 0;
+            // 
+            // maximGroupBox7
+            // 
+            this.maximGroupBox7.BackgroundColor = System.Drawing.Color.White;
+            this.maximGroupBox7.Location = new System.Drawing.Point(3, 467);
+            this.maximGroupBox7.Name = "maximGroupBox7";
+            this.maximGroupBox7.Size = new System.Drawing.Size(248, 53);
+            this.maximGroupBox7.TabIndex = 31;
+            this.maximGroupBox7.TabStop = false;
+            this.maximGroupBox7.Text = "Registers";
+            // 
+            // textBox1
+            // 
+            this.textBox1.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
+            this.textBox1.Location = new System.Drawing.Point(169, 25);
+            this.textBox1.Name = "textBox1";
+            this.textBox1.Size = new System.Drawing.Size(41, 20);
+            this.textBox1.TabIndex = 2;
+            this.textBox1.Text = "0xFF";
+            // 
+            // maximButton1
+            // 
+            this.maximButton1.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
+            this.maximButton1.Location = new System.Drawing.Point(215, 25);
+            this.maximButton1.Name = "maximButton1";
+            this.maximButton1.Size = new System.Drawing.Size(28, 23);
+            this.maximButton1.TabIndex = 1;
+            this.maximButton1.Text = "Wr";
+            this.maximButton1.UseVisualStyleBackColor = true;
+            // 
+            // maximButton2
+            // 
+            this.maximButton2.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
+            this.maximButton2.Location = new System.Drawing.Point(137, 25);
+            this.maximButton2.Name = "maximButton2";
+            this.maximButton2.Size = new System.Drawing.Size(26, 23);
+            this.maximButton2.TabIndex = 1;
+            this.maximButton2.Text = "Rd";
+            this.maximButton2.UseVisualStyleBackColor = true;
+            // 
+            // comboBox13
+            // 
+            this.comboBox13.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) 
+            | System.Windows.Forms.AnchorStyles.Right)));
+            this.comboBox13.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
+            this.comboBox13.Font = new System.Drawing.Font("Arial", 7.8F);
+            this.comboBox13.FormattingEnabled = true;
+            this.comboBox13.Location = new System.Drawing.Point(6, 23);
+            this.comboBox13.Name = "comboBox13";
+            this.comboBox13.Size = new System.Drawing.Size(126, 22);
+            this.comboBox13.TabIndex = 0;
+            // 
+            // maximButton3
+            // 
+            this.maximButton3.Location = new System.Drawing.Point(133, 523);
+            this.maximButton3.Name = "maximButton3";
+            this.maximButton3.Size = new System.Drawing.Size(118, 23);
+            this.maximButton3.TabIndex = 26;
+            this.maximButton3.Text = "Restore Defaults";
+            this.maximButton3.UseVisualStyleBackColor = true;
+            // 
+            // maximButton4
+            // 
+            this.maximButton4.Location = new System.Drawing.Point(7, 523);
+            this.maximButton4.Name = "maximButton4";
+            this.maximButton4.Size = new System.Drawing.Size(120, 23);
+            this.maximButton4.TabIndex = 13;
+            this.maximButton4.Text = "Start Monitor";
+            this.maximButton4.UseVisualStyleBackColor = true;
+            // 
+            // comboBox14
+            // 
+            this.comboBox14.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
+            this.comboBox14.Font = new System.Drawing.Font("Arial", 7.8F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+            this.comboBox14.FormattingEnabled = true;
+            this.comboBox14.Location = new System.Drawing.Point(147, 2);
+            this.comboBox14.MaxDropDownItems = 10;
+            this.comboBox14.Name = "comboBox14";
+            this.comboBox14.Size = new System.Drawing.Size(71, 22);
+            this.comboBox14.TabIndex = 20;
+            // 
+            // menuStrip1
+            // 
+            this.menuStrip1.Font = new System.Drawing.Font("Arial", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+            this.menuStrip1.ImageScalingSize = new System.Drawing.Size(20, 20);
+            this.menuStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
+            this.toolStripMenuItem1,
+            this.toolStripMenuItem2,
+            this.optionsToolStripMenuItem1,
+            this.loggingToolStripMenuItem,
+            this.helpToolStripMenuItem1});
+            this.menuStrip1.Location = new System.Drawing.Point(0, 0);
+            this.menuStrip1.Name = "menuStrip1";
+            this.menuStrip1.Padding = new System.Windows.Forms.Padding(5, 2, 0, 2);
+            this.menuStrip1.Size = new System.Drawing.Size(961, 24);
+            this.menuStrip1.TabIndex = 17;
+            this.menuStrip1.Text = "menuStrip1";
+            // 
+            // toolStripMenuItem3
+            // 
+            this.toolStripMenuItem3.Name = "toolStripMenuItem3";
+            this.toolStripMenuItem3.Size = new System.Drawing.Size(32, 19);
+            // 
+            // toolStripMenuItem4
+            // 
+            this.toolStripMenuItem4.Name = "toolStripMenuItem4";
+            this.toolStripMenuItem4.Size = new System.Drawing.Size(32, 19);
+            // 
+            // toolStripMenuItem5
+            // 
+            this.toolStripMenuItem5.Name = "toolStripMenuItem5";
+            this.toolStripMenuItem5.Size = new System.Drawing.Size(32, 19);
+            // 
+            // toolStripMenuItem6
+            // 
+            this.toolStripMenuItem6.Name = "toolStripMenuItem6";
+            this.toolStripMenuItem6.Size = new System.Drawing.Size(32, 19);
+            // 
+            // toolStripMenuItem7
+            // 
+            this.toolStripMenuItem7.Name = "toolStripMenuItem7";
+            this.toolStripMenuItem7.Size = new System.Drawing.Size(32, 19);
+            // 
+            // toolStripMenuItem8
+            // 
+            this.toolStripMenuItem8.Name = "toolStripMenuItem8";
+            this.toolStripMenuItem8.Size = new System.Drawing.Size(32, 19);
+            // 
+            // toolStripMenuItem9
+            // 
+            this.toolStripMenuItem9.Name = "toolStripMenuItem9";
+            this.toolStripMenuItem9.Size = new System.Drawing.Size(32, 19);
+            // 
+            // toolStripMenuItem10
+            // 
+            this.toolStripMenuItem10.Name = "toolStripMenuItem10";
+            this.toolStripMenuItem10.Size = new System.Drawing.Size(32, 19);
+            // 
+            // toolStripSeparator4
+            // 
+            this.toolStripSeparator4.Name = "toolStripSeparator4";
+            this.toolStripSeparator4.Size = new System.Drawing.Size(6, 6);
+            // 
+            // toolStripMenuItem11
+            // 
+            this.toolStripMenuItem11.Name = "toolStripMenuItem11";
+            this.toolStripMenuItem11.Size = new System.Drawing.Size(32, 19);
+            // 
+            // toolStripMenuItem12
+            // 
+            this.toolStripMenuItem12.Name = "toolStripMenuItem12";
+            this.toolStripMenuItem12.Size = new System.Drawing.Size(32, 19);
+            // 
+            // toolStripSeparator6
+            // 
+            this.toolStripSeparator6.Name = "toolStripSeparator6";
+            this.toolStripSeparator6.Size = new System.Drawing.Size(6, 6);
+            // 
+            // toolStripMenuItem13
+            // 
+            this.toolStripMenuItem13.Name = "toolStripMenuItem13";
+            this.toolStripMenuItem13.Size = new System.Drawing.Size(32, 19);
+            // 
+            // toolStripMenuItem14
+            // 
+            this.toolStripMenuItem14.Name = "toolStripMenuItem14";
+            this.toolStripMenuItem14.Size = new System.Drawing.Size(32, 19);
+            // 
+            // toolStripSeparator7
+            // 
+            this.toolStripSeparator7.Name = "toolStripSeparator7";
+            this.toolStripSeparator7.Size = new System.Drawing.Size(6, 6);
+            // 
+            // toolStripMenuItem15
+            // 
+            this.toolStripMenuItem15.Name = "toolStripMenuItem15";
+            this.toolStripMenuItem15.Size = new System.Drawing.Size(32, 19);
+            // 
+            // toolStripMenuItem16
+            // 
+            this.toolStripMenuItem16.Name = "toolStripMenuItem16";
+            this.toolStripMenuItem16.Size = new System.Drawing.Size(32, 19);
+            // 
+            // toolStripMenuItem17
+            // 
+            this.toolStripMenuItem17.Name = "toolStripMenuItem17";
+            this.toolStripMenuItem17.Size = new System.Drawing.Size(32, 19);
+            // 
+            // toolStripMenuItem18
+            // 
+            this.toolStripMenuItem18.Name = "toolStripMenuItem18";
+            this.toolStripMenuItem18.Size = new System.Drawing.Size(32, 19);
+            // 
+            // toolStripMenuItem19
+            // 
+            this.toolStripMenuItem19.Name = "toolStripMenuItem19";
+            this.toolStripMenuItem19.Size = new System.Drawing.Size(32, 19);
+            // 
+            // toolStripMenuItem20
+            // 
+            this.toolStripMenuItem20.Name = "toolStripMenuItem20";
+            this.toolStripMenuItem20.Size = new System.Drawing.Size(32, 19);
+            // 
+            // toolStripMenuItem21
+            // 
+            this.toolStripMenuItem21.Name = "toolStripMenuItem21";
+            this.toolStripMenuItem21.Size = new System.Drawing.Size(32, 19);
+            // 
+            // toolStripSeparator8
+            // 
+            this.toolStripSeparator8.Name = "toolStripSeparator8";
+            this.toolStripSeparator8.Size = new System.Drawing.Size(6, 6);
+            // 
+            // toolStripMenuItem22
+            // 
+            this.toolStripMenuItem22.Name = "toolStripMenuItem22";
+            this.toolStripMenuItem22.Size = new System.Drawing.Size(32, 19);
+            // 
+            // toolStripMenuItem23
+            // 
+            this.toolStripMenuItem23.Name = "toolStripMenuItem23";
+            this.toolStripMenuItem23.Size = new System.Drawing.Size(32, 19);
+            // 
+            // toolStripMenuItem24
+            // 
+            this.toolStripMenuItem24.Name = "toolStripMenuItem24";
+            this.toolStripMenuItem24.Size = new System.Drawing.Size(32, 19);
+            // 
+            // toolStripMenuItem25
+            // 
+            this.toolStripMenuItem25.Name = "toolStripMenuItem25";
+            this.toolStripMenuItem25.Size = new System.Drawing.Size(32, 19);
+            // 
+            // HspForm
+            // 
+            this.AutoScaleDimensions = new System.Drawing.SizeF(96F, 96F);
+            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi;
+            this.BackColor = System.Drawing.Color.White;
+            this.ClientSize = new System.Drawing.Size(961, 682);
+            this.Controls.Add(this.menuStrip1);
+            this.Controls.Add(this.maximTabControl1);
+            this.Controls.Add(this.ss_Status);
+            this.Font = new System.Drawing.Font("Arial", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+            this.ForeColor = System.Drawing.Color.Black;
+            this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon")));
+            this.Name = "HspForm";
+            this.SizeGripStyle = System.Windows.Forms.SizeGripStyle.Hide;
+            this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
+            this.Text = "MAXREFDES100 Health Sensor Platform";
+            this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.HspForm_FormClosing);
+            this.Load += new System.EventHandler(this.Form_Load);
+            this.ResizeEnd += new System.EventHandler(this.HspForm_ResizeEnd);
+            this.maximGroupBox1.ResumeLayout(false);
+            this.maximGroupBox1.PerformLayout();
+            this.maximTabControl1.ResumeLayout(false);
+            this.tpBlockDiagram.ResumeLayout(false);
+            this.tlbQuickStart.ResumeLayout(false);
+            this.tlbQuickStart.PerformLayout();
+            this.pnlBlockDiagram.ResumeLayout(false);
+            this.pnlBlockDiagram.PerformLayout();
+            ((System.ComponentModel.ISupportInitialize)(this.picBlockDiagram)).EndInit();
+            this.tpOpticalSensor.ResumeLayout(false);
+            this.tpTemperature.ResumeLayout(false);
+            this.tpMAX30001EcgChannel.ResumeLayout(false);
+            this.tpMAX30001EcgChannel.PerformLayout();
+            this.flowLayoutPanel1.ResumeLayout(false);
+            this.pnlEcgChannel.ResumeLayout(false);
+            this.pnlEcgChannel.PerformLayout();
+            ((System.ComponentModel.ISupportInitialize)(this.picEcgChannel)).EndInit();
+            this.grpRToR.ResumeLayout(false);
+            this.grpRToR.PerformLayout();
+            this.tpMAX30001InputMux.ResumeLayout(false);
+            this.pnlEcgMux.ResumeLayout(false);
+            this.pnlEcgMux.PerformLayout();
+            ((System.ComponentModel.ISupportInitialize)(this.picECGLeadConfig)).EndInit();
+            ((System.ComponentModel.ISupportInitialize)(this.picSw1)).EndInit();
+            ((System.ComponentModel.ISupportInitialize)(this.picSw2)).EndInit();
+            ((System.ComponentModel.ISupportInitialize)(this.pictureBox1)).EndInit();
+            ((System.ComponentModel.ISupportInitialize)(this.picSw3)).EndInit();
+            ((System.ComponentModel.ISupportInitialize)(this.picSw4)).EndInit();
+            ((System.ComponentModel.ISupportInitialize)(this.picSw5)).EndInit();
+            ((System.ComponentModel.ISupportInitialize)(this.picSw6)).EndInit();
+            ((System.ComponentModel.ISupportInitialize)(this.picSw7)).EndInit();
+            ((System.ComponentModel.ISupportInitialize)(this.picSw8)).EndInit();
+            ((System.ComponentModel.ISupportInitialize)(this.picSw9)).EndInit();
+            ((System.ComponentModel.ISupportInitialize)(this.picSw10)).EndInit();
+            ((System.ComponentModel.ISupportInitialize)(this.picSw11)).EndInit();
+            ((System.ComponentModel.ISupportInitialize)(this.picSw12)).EndInit();
+            ((System.ComponentModel.ISupportInitialize)(this.picSw13)).EndInit();
+            ((System.ComponentModel.ISupportInitialize)(this.picSw14)).EndInit();
+            this.pnlMAX30001Global.ResumeLayout(false);
+            this.grpChannelPlotEnable.ResumeLayout(false);
+            this.grpChannelPlotEnable.PerformLayout();
+            this.maximGroupBox8.ResumeLayout(false);
+            this.grpGlobalControls.ResumeLayout(false);
+            this.grpGlobalControls.PerformLayout();
+            this.tpBioZChannel.ResumeLayout(false);
+            this.pnlBioZChannel.ResumeLayout(false);
+            this.pnlBioZChannel.PerformLayout();
+            ((System.ComponentModel.ISupportInitialize)(this.picBioZChannel)).EndInit();
+            this.tpMAX30001BioZInputMux.ResumeLayout(false);
+            this.pnlBioZMux.ResumeLayout(false);
+            this.pnlBioZMux.PerformLayout();
+            ((System.ComponentModel.ISupportInitialize)(this.pictureBox2)).EndInit();
+            ((System.ComponentModel.ISupportInitialize)(this.picLoff1)).EndInit();
+            ((System.ComponentModel.ISupportInitialize)(this.picLoff2)).EndInit();
+            ((System.ComponentModel.ISupportInitialize)(this.picLeadOn)).EndInit();
+            ((System.ComponentModel.ISupportInitialize)(this.picBioZsw1)).EndInit();
+            ((System.ComponentModel.ISupportInitialize)(this.picBioZsw2)).EndInit();
+            ((System.ComponentModel.ISupportInitialize)(this.picLeadBias1)).EndInit();
+            ((System.ComponentModel.ISupportInitialize)(this.picLeadBias2)).EndInit();
+            ((System.ComponentModel.ISupportInitialize)(this.picBioZCal1)).EndInit();
+            ((System.ComponentModel.ISupportInitialize)(this.picBioZCal2)).EndInit();
+            this.tpMAX30001BioZLoad.ResumeLayout(false);
+            this.pnlBioZLoad.ResumeLayout(false);
+            this.pnlBioZLoad.PerformLayout();
+            ((System.ComponentModel.ISupportInitialize)(this.picBioZLoad)).EndInit();
+            ((System.ComponentModel.ISupportInitialize)(this.picBioZLloff1)).EndInit();
+            ((System.ComponentModel.ISupportInitialize)(this.picBioZLloff2)).EndInit();
+            ((System.ComponentModel.ISupportInitialize)(this.picBioZLlon)).EndInit();
+            ((System.ComponentModel.ISupportInitialize)(this.picBioZLsw1)).EndInit();
+            ((System.ComponentModel.ISupportInitialize)(this.picBioZLlb2)).EndInit();
+            ((System.ComponentModel.ISupportInitialize)(this.picBioZLcal2)).EndInit();
+            ((System.ComponentModel.ISupportInitialize)(this.picBioZLcal1)).EndInit();
+            ((System.ComponentModel.ISupportInitialize)(this.picBioZLlb1)).EndInit();
+            ((System.ComponentModel.ISupportInitialize)(this.picBioZLsw2)).EndInit();
+            ((System.ComponentModel.ISupportInitialize)(this.picBioZLresload)).EndInit();
+            this.tpMAX30001Pace.ResumeLayout(false);
+            this.pnlPace.ResumeLayout(false);
+            this.pnlPace.PerformLayout();
+            ((System.ComponentModel.ISupportInitialize)(this.picPaceChannel)).EndInit();
+            this.tpMAX30001Plots.ResumeLayout(false);
+            this.tpFlashLog.ResumeLayout(false);
+            this.tpRegisters.ResumeLayout(false);
+            this.tableLayoutPanel1.ResumeLayout(false);
+            this.pnlRegMAX30205_U18.ResumeLayout(false);
+            this.pnlRegMAX14720.ResumeLayout(false);
+            this.pnlRegMAX30101.ResumeLayout(false);
+            this.pnlRegMAX30001.ResumeLayout(false);
+            this.pnlRegMAX30205.ResumeLayout(false);
+            this.pnlRegLIS2HD.ResumeLayout(false);
+            this.tpPrimitives.ResumeLayout(false);
+            ((System.ComponentModel.ISupportInitialize)(this.chart1)).EndInit();
+            ((System.ComponentModel.ISupportInitialize)(this.numericUpDown1)).EndInit();
+            ((System.ComponentModel.ISupportInitialize)(this.chart2)).EndInit();
+            this.menuStrip1.ResumeLayout(false);
+            this.menuStrip1.PerformLayout();
+            this.ResumeLayout(false);
+            this.PerformLayout();
+
+        }
+
+        #endregion
+
+        private System.Windows.Forms.TextBox txt_Status;
+        private System.Windows.Forms.Label label1;
+        private MaximStyle.MaximButton btn_Clear;
+        private MaximStyle.MaximStatusStrip ss_Status;
+        private System.Windows.Forms.ToolStripMenuItem fileToolStripMenuItem;
+        private System.Windows.Forms.ToolStripMenuItem tsm_exit;
+        private System.Windows.Forms.ToolStripMenuItem deviceToolStripMenuItem;
+        private System.Windows.Forms.ToolStripMenuItem test1ToolStripMenuItem;
+        private System.Windows.Forms.ToolStripMenuItem optionsToolStripMenuItem;
+        private System.Windows.Forms.ToolStripMenuItem test2ToolStripMenuItem;
+        private System.Windows.Forms.ToolStripMenuItem helpToolStripMenuItem;
+        private System.Windows.Forms.ToolStripMenuItem technicalDocsToolStripMenuItem;
+        private System.Windows.Forms.ToolStripMenuItem tsm_EVKitDatasheet;
+        private System.Windows.Forms.ToolStripMenuItem tsm_ICDatasheet;
+        private System.Windows.Forms.ToolStripMenuItem tsm_about;
+        private MaximStyle.MaximGroupBox maximGroupBox1;
+        private MaximStyle.MaximTabControl maximTabControl1;
+        private System.Windows.Forms.TabPage tpPrimitives;
+        private System.Windows.Forms.Label label22;
+        private System.Windows.Forms.Label label23;
+        private System.Windows.Forms.Label label24;
+        private System.Windows.Forms.Label label2;
+        private System.Windows.Forms.Label label3;
+        private System.Windows.Forms.Label label12;
+        private System.Windows.Forms.Label label13;
+        private System.Windows.Forms.Label label14;
+        private System.Windows.Forms.Label label15;
+        private System.Windows.Forms.Label label8;
+        private System.Windows.Forms.Label label4;
+        private System.Windows.Forms.Label label6;
+        private System.Windows.Forms.Label label7;
+        private System.Windows.Forms.Label label17;
+        private System.Windows.Forms.Label label18;
+        private System.Windows.Forms.Label label19;
+        private System.Windows.Forms.Label label20;
+        private System.Windows.Forms.Label label16;
+        private System.Windows.Forms.Label label5;
+        private System.Windows.Forms.Label label9;
+        private System.Windows.Forms.Label label10;
+        private System.Windows.Forms.Label label11;
+        private System.Windows.Forms.ToolStripMenuItem toolStripMenuItem1;
+        private System.Windows.Forms.ToolStripMenuItem toolStripMenuItem2;
+        private System.Windows.Forms.ToolStripMenuItem optionsToolStripMenuItem1;
+        private System.Windows.Forms.ToolStripMenuItem helpToolStripMenuItem1;
+        private System.Windows.Forms.DataVisualization.Charting.Chart chart1;
+        private MaximStyle.MaximGroupBox maximGroupBox2;
+        private System.Windows.Forms.NumericUpDown numericUpDown1;
+        private System.Windows.Forms.ComboBox comboBox1;
+        private MaximStyle.MaximGroupBox maximGroupBox3;
+        private System.Windows.Forms.DataVisualization.Charting.Chart chart2;
+        private MaximStyle.MaximGroupBox maximGroupBox4;
+        private System.Windows.Forms.ComboBox comboBox2;
+        private System.Windows.Forms.ComboBox comboBox3;
+        private System.Windows.Forms.ComboBox comboBox4;
+        private System.Windows.Forms.ComboBox comboBox5;
+        private MaximStyle.MaximGroupBox maximGroupBox5;
+        private System.Windows.Forms.ComboBox comboBox6;
+        private System.Windows.Forms.ComboBox comboBox7;
+        private System.Windows.Forms.ComboBox comboBox8;
+        private System.Windows.Forms.ComboBox comboBox9;
+        private MaximStyle.MaximGroupBox maximGroupBox6;
+        private System.Windows.Forms.ComboBox comboBox10;
+        private System.Windows.Forms.ComboBox comboBox11;
+        private System.Windows.Forms.ComboBox comboBox12;
+        private MaximStyle.MaximGroupBox maximGroupBox7;
+        private System.Windows.Forms.TextBox textBox1;
+        private MaximStyle.MaximButton maximButton1;
+        private MaximStyle.MaximButton maximButton2;
+        private System.Windows.Forms.ComboBox comboBox13;
+        private MaximStyle.MaximButton maximButton3;
+        private MaximStyle.MaximButton maximButton4;
+        private System.Windows.Forms.ComboBox comboBox14;
+        private System.Windows.Forms.TabPage tpOpticalSensor;
+        private CustomControls.PrimitivesView primitivesView1;
+        private System.Windows.Forms.ToolStripMenuItem aboutToolStripMenuItem;
+        private System.Windows.Forms.TabPage tpMAX30001EcgChannel;
+        private System.Windows.Forms.TabPage tpMAX30001Plots;
+        private System.Windows.Forms.TabPage tpRegisters;
+        private System.Windows.Forms.TabPage tpTemperature;
+        private CustomControls.TemperatureView temperatureView1;
+        private MaximStyle.MaximComboBox cboDhpf;
+        private MaximStyle.MaximComboBox cboDlpf;
+        private MaximStyle.MaximComboBox cboSampleRate;
+        private MaximStyle.MaximComboBox cboChannelGain;
+        private MaximStyle.MaximComboBox cboFast;
+        private System.Windows.Forms.Label lblDhpf;
+        private System.Windows.Forms.Label lblDlpf;
+        private System.Windows.Forms.Label lblSampleRate;
+        private System.Windows.Forms.Label lblChannelGain;
+        private System.Windows.Forms.Label lblFast;
+        private System.Windows.Forms.Panel pnlRegMAX30101;
+        private System.Windows.Forms.Panel pnlRegMAX30205;
+        private System.Windows.Forms.Panel pnlRegLIS2HD;
+        private System.Windows.Forms.Panel pnlRegMAX30001;
+        private Maxim.CustomControls.RegisterView rvMAX30101;
+        private Maxim.CustomControls.RegisterView rvMAX30205;
+        private Maxim.CustomControls.RegisterView rvLIS2HD;
+        private System.Windows.Forms.Panel pnlRegMAX14720;
+        private Maxim.CustomControls.RegisterView rvMAX14720;
+        private Maxim.CustomControls.RegisterView rvMAX30001;
+        private System.Windows.Forms.ToolStripMenuItem exitToolStripMenuItem;
+        private Maxim.CustomControls.RegisterView rvMAX30205_U18;
+        private System.Windows.Forms.ToolStripMenuItem connectionToolStripMenuItem;
+        private MaximStyle.MaximComboBox cboFastTh;
+        private System.Windows.Forms.Label lblFastTh;
+        private System.Windows.Forms.Label label28;
+        private System.Windows.Forms.TabPage tpMAX30001InputMux;
+        private MaximStyle.MaximComboBox cboEmuxOpenn;
+        private MaximStyle.MaximComboBox cboEmuxOpenp;
+        private System.Windows.Forms.Label lblEmuxOpenn;
+        private System.Windows.Forms.Label lblEmuxOpenp;
+        private System.Windows.Forms.Label lblCalVmag;
+        private System.Windows.Forms.Label lblCalFreq;
+        private System.Windows.Forms.Label lblCalTHigh;
+        private System.Windows.Forms.Label lblCalFifty;
+        private MaximStyle.MaximComboBox cboCalFcal;
+        private MaximStyle.MaximComboBox cboCalThigh;
+        private MaximStyle.MaximComboBox cboCalFifty;
+        private MaximStyle.MaximComboBox cboCalVmag;
+        private System.Windows.Forms.Label lblDcloffImag;
+        private System.Windows.Forms.Label lblCalVMode;
+        private System.Windows.Forms.Label lblCalEnVcal;
+        private System.Windows.Forms.Label lblEmuxPol;
+        private MaximStyle.MaximComboBox cboEmuxPol;
+        private MaximStyle.MaximComboBox cboDcloffImag;
+        private MaximStyle.MaximComboBox cboCalVmode;
+        private MaximStyle.MaximComboBox cboCalEnVcal;
+        private System.Windows.Forms.PictureBox picECGLeadConfig;
+        private System.Windows.Forms.Label lblDcloffVth;
+        private MaximStyle.MaximComboBox cboDcloffVth;
+        private MaximStyle.MaximComboBox cboDcloffIpol;
+        private System.Windows.Forms.Label lblDcloffIpol;
+        private MaximStyle.MaximComboBox cboEnDcloff;
+        private System.Windows.Forms.Label lblEnDcloff;
+        private MaximStyle.MaximGroupBox grpGlobalControls;
+        private MaximStyle.MaximComboBox cboMasterClock;
+        private System.Windows.Forms.Label label31;
+        private MaximStyle.MaximGroupBox maximGroupBox8;
+        private MaximStyle.MaximButton maximButton5;
+        private MaximStyle.MaximComboBox maximComboBox9;
+        private MaximStyle.MaximComboBox cboRbiasn;
+        private System.Windows.Forms.Label lblRbiasn;
+        private MaximStyle.MaximComboBox cboRbiasp;
+        private System.Windows.Forms.Label lblRbiasp;
+        private MaximStyle.MaximComboBox cboRbiasv;
+        private System.Windows.Forms.Label lblRbiasv;
+        private MaximStyle.MaximComboBox cboEnRbias;
+        private System.Windows.Forms.Label lblEnRbias;
+        private System.Windows.Forms.LinkLabel linkLabel1;
+        private System.Windows.Forms.Panel pnlMAX30001Global;
+        private System.Windows.Forms.ToolTip toolTip1;
+        private System.Windows.Forms.ToolStripMenuItem registerNamesToolStripMenuItem;
+        private MaximStyle.MaximGroupBox grpRToR;
+        private MaximStyle.MaximComboBox cboRRWndw;
+        private System.Windows.Forms.Label lblRRWndw;
+        private MaximStyle.MaximComboBox cboEnRToR;
+        private System.Windows.Forms.Label lblEnRToR;
+        private MaximStyle.MaximComboBox cboRRGain;
+        private System.Windows.Forms.Label lblRRGain;
+        private MaximStyle.MaximComboBox cboRRPtsf;
+        private System.Windows.Forms.Label lblRRPtsf;
+        private MaximStyle.MaximComboBox cboRRPavg;
+        private System.Windows.Forms.Label lblRRPavg;
+        private MaximStyle.MaximComboBox cboRRRhsf;
+        private System.Windows.Forms.Label lblRRRhsf;
+        private MaximStyle.MaximComboBox cboRRRavg;
+        private System.Windows.Forms.Label lblRRRavg;
+        private MaximStyle.MaximComboBox cboRRHoff;
+        private System.Windows.Forms.Label lblRRHoff;
+        private MaximStyle.MaximComboBox cboEmuxCalNSel;
+        private System.Windows.Forms.Label lblEmuxCalNSel;
+        private MaximStyle.MaximComboBox cboEmuxCalPSel;
+        private System.Windows.Forms.Label lblEmuxCalPSel;
+        private CustomControls.EcgView ecgView1;
+        private System.Windows.Forms.ToolStripMenuItem disconnectToolStripMenuItem;
+        private System.Windows.Forms.TabPage tpBioZChannel;
+        private System.Windows.Forms.TabPage tpMAX30001BioZInputMux;
+        private System.Windows.Forms.TabPage tpMAX30001Pace;
+        private System.Windows.Forms.TabPage tpFlashLog;
+        private System.Windows.Forms.PictureBox picBioZChannel;
+        private System.Windows.Forms.Label lblBioZExternalResistorBiasEnable;
+        private System.Windows.Forms.Label lblBioZCurrentGeneratorMonitor;
+        private System.Windows.Forms.Label lblBioZCurrentGeneratorMode;
+        private System.Windows.Forms.Label lblBioZModulationPhaseOffset;
+        private System.Windows.Forms.Label lblBioZCurrentGeneratorMagnitude;
+        private System.Windows.Forms.Label lblBioZACLeadOffUnderRangeThreshold;
+        private System.Windows.Forms.Label lblBioZACLeadOffOverRangeThreshold;
+        private System.Windows.Forms.Label lblBioZDigitalLeadOffDetectionEnable;
+        private System.Windows.Forms.Label lblBioZDigitalHpf;
+        private System.Windows.Forms.Label lblBioZDigitalLpf;
+        private System.Windows.Forms.Label lblBioZSampleRate;
+        private System.Windows.Forms.Label lblBioZChannelGain;
+        private System.Windows.Forms.LinkLabel linkLabel2;
+        private System.Windows.Forms.Label lblBioZAnalogHpf;
+        private MaximStyle.MaximComboBox cboBioZCurrentGeneratorMode;
+        private MaximStyle.MaximComboBox cboBioZCurrentGeneratorMonitor;
+        private MaximStyle.MaximComboBox cboBioZExternalResistorBiasEnable;
+        private MaximStyle.MaximComboBox cboBioZDigitalLeadOffDetectionEnable;
+        private MaximStyle.MaximComboBox cboBioZACLeadOffUnderRangeThreshold;
+        private MaximStyle.MaximComboBox cboBioZACLeadOffOverRangeThreshold;
+        private MaximStyle.MaximComboBox cboBioZDigitalHpf;
+        private MaximStyle.MaximComboBox cboBioZDigitalLpf;
+        private MaximStyle.MaximComboBox cboBioZSampleRate;
+        private MaximStyle.MaximComboBox cboBioZChannelGain;
+        private MaximStyle.MaximComboBox cboBioZModulationPhaseOffset;
+        private MaximStyle.MaximComboBox cboBioZCurrentGeneratorMagnitude;
+        private MaximStyle.MaximComboBox cboBioZAnalogHpf;
+        private System.Windows.Forms.Label label21;
+        private System.Windows.Forms.PictureBox picPaceChannel;
+        private System.Windows.Forms.Label lblPaceSignalSelection;
+        private System.Windows.Forms.Label lblPaceBufferBandwidth;
+        private System.Windows.Forms.Label lblPaceAnalogHpf;
+        private MaximStyle.MaximComboBox cboPaceAnalogHpf;
+        private MaximStyle.MaximComboBox cboPaceDetectorNegativeThreshold;
+        private MaximStyle.MaximComboBox cboPaceDetectorPostiveThreshold;
+        private MaximStyle.MaximComboBox cboPaceDifferentiatorMode;
+        private MaximStyle.MaximComboBox cboPaceChannelGain;
+        private MaximStyle.MaximComboBox cboPaceInputPolarity;
+        private MaximStyle.MaximComboBox cboPaceSignalSelection;
+        private MaximStyle.MaximComboBox cboPaceBufferBandwidth;
+        private System.Windows.Forms.Label lblPaceDetectorNegativeThreshold;
+        private System.Windows.Forms.Label lblPaceDetectorPostiveThreshold;
+        private System.Windows.Forms.Label lblPaceDifferentiatorMode;
+        private System.Windows.Forms.Label lblPaceChannelGain;
+        private System.Windows.Forms.Label lblPaceInputPolarity;
+        private System.Windows.Forms.Label label35;
+        private MaximStyle.MaximCheckBox chkEnRtor;
+        private MaximStyle.MaximCheckBox chkEnPace;
+        private MaximStyle.MaximCheckBox chkEnBioZ;
+        private MaximStyle.MaximCheckBox chkEnECG;
+        private MaximStyle.MaximGroupBox grpChannelPlotEnable;
+        private MaximStyle.MaximComboBox cboBioZCurrentGeneratorFrequency;
+        private System.Windows.Forms.Label lblBioZCurrentGeneratorFrequency;
+        private MaximStyle.MaximComboBox cboBioZBmuxCalnSel;
+        private System.Windows.Forms.Label lblBioZBmuxCalnSel;
+        private MaximStyle.MaximComboBox cboBioZBmuxCalpSel;
+        private System.Windows.Forms.Label lblBioZBmuxCalpSel;
+        private MaximStyle.MaximComboBox cboBioZRbiasn;
+        private System.Windows.Forms.Label lblBioZRbiasn;
+        private MaximStyle.MaximComboBox cboBioZRbiasp;
+        private System.Windows.Forms.Label lblBioZRbiasp;
+        private MaximStyle.MaximComboBox cboBioZRbiasv;
+        private System.Windows.Forms.Label lblBioZRbiasv;
+        private MaximStyle.MaximComboBox cboBioZEnRbias;
+        private System.Windows.Forms.Label lblBioZEnRbias;
+        private System.Windows.Forms.Label lblBioZDcloffVth;
+        private MaximStyle.MaximComboBox cboBioZDcloffVth;
+        private MaximStyle.MaximComboBox cboBioZDcloffIpol;
+        private System.Windows.Forms.Label lblBioZDcloffIpol;
+        private MaximStyle.MaximComboBox cboBioZEnDcloff;
+        private System.Windows.Forms.Label lblBioZEnDcloff;
+        private MaximStyle.MaximComboBox cboBioZBmuxOpenn;
+        private MaximStyle.MaximComboBox cboBioZBmuxOpenp;
+        private System.Windows.Forms.Label lblBioZBmuxOpenn;
+        private System.Windows.Forms.Label lblBioZBmuxOpenp;
+        private System.Windows.Forms.Label lblBioZCalVmag;
+        private System.Windows.Forms.Label lblBioZCalFcal;
+        private System.Windows.Forms.Label lblBioZCalThigh;
+        private System.Windows.Forms.Label lblBioZCalFifty;
+        private MaximStyle.MaximComboBox cboBioZCalFcal;
+        private MaximStyle.MaximComboBox cboBioZCalThigh;
+        private MaximStyle.MaximComboBox cboBioZCalFifty;
+        private MaximStyle.MaximComboBox cboBioZCalVmag;
+        private System.Windows.Forms.Label lblBioZDcloffImag;
+        private System.Windows.Forms.Label lblBioZCalVMode;
+        private System.Windows.Forms.Label lblBioZCalEnVcal;
+        private MaximStyle.MaximComboBox cboBioZDcloffImag;
+        private MaximStyle.MaximComboBox cboBioZCalVMode;
+        private MaximStyle.MaximComboBox cboBioZCalEnVcal;
+        private System.Windows.Forms.PictureBox pictureBox2;
+        private System.Windows.Forms.Label label25;
+        private System.Windows.Forms.Label label26;
+        private System.Windows.Forms.Label label27;
+        private System.Windows.Forms.TabPage tpMAX30001BioZLoad;
+        private System.Windows.Forms.Label lblBioZBmuxFbist;
+        private System.Windows.Forms.Label lblBioZBmuxRmod;
+        private System.Windows.Forms.Label lblBioZBmuxEnBist;
+        private System.Windows.Forms.Label label33;
+        private MaximStyle.MaximComboBox cboBioZBmuxFbist;
+        private MaximStyle.MaximComboBox cboBioZBmuxRmod;
+        private MaximStyle.MaximComboBox cboBioZBmuxEnBist;
+        private System.Windows.Forms.PictureBox picBioZLoad;
+        private MaximStyle.MaximComboBox cboBioZBmuxRnom;
+        private System.Windows.Forms.Label lblBioZBmuxRnom;
+        private System.Windows.Forms.ToolStripMenuItem showAdvancedTabToolStripMenuItem;
+        private CustomControls.DataLoggingView dataLoggingView1;
+        private MaximStyle.MaximComboBox cboEmuxEnUlpLon;
+        private System.Windows.Forms.Label label30;
+        private System.Windows.Forms.Label label32;
+        private System.Windows.Forms.Label label34;
+        private System.Windows.Forms.Label label36;
+        private System.Windows.Forms.Label label37;
+        private System.Windows.Forms.Label label38;
+        private System.Windows.Forms.ToolStripMenuItem onlineDocumentationToolStripMenuItem;
+        private System.Windows.Forms.Label lblEmuxEnUlpLon;
+        private System.Windows.Forms.Label lblBmuxEnUlpLon;
+        private MaximStyle.MaximComboBox cboBmuxEnUlpLon;
+        private System.Windows.Forms.ToolStripMenuItem bioZMilliohmScaleToolStripMenuItem;
+        private System.Windows.Forms.Panel pnlRegMAX30205_U18;
+        private System.Windows.Forms.TableLayoutPanel tableLayoutPanel1;
+        private MaximStyle.MaximComboBox cboRegisterTabDevice;
+        private CustomControls.OpticalView opticalView1;
+        private System.Windows.Forms.ToolStripMenuItem saveRegisterSettingsToolStripMenuItem;
+        private System.Windows.Forms.ToolStripMenuItem loadRegisterSettingsToolStripMenuItem;
+        private System.Windows.Forms.TabPage tpBlockDiagram;
+        private System.Windows.Forms.PictureBox picBlockDiagram;
+        private System.Windows.Forms.LinkLabel linkBioZLoad;
+        private System.Windows.Forms.LinkLabel linkBioZMux;
+        private System.Windows.Forms.LinkLabel linkBioZChannel;
+        private System.Windows.Forms.LinkLabel linkPaceChannel;
+        private System.Windows.Forms.LinkLabel linkEcgMux;
+        private System.Windows.Forms.LinkLabel linkEcgChannel;
+        private System.Windows.Forms.LinkLabel linkOpticalSensor;
+        private System.Windows.Forms.LinkLabel linkTempSensor;
+        private System.Windows.Forms.Label label29;
+        private System.Windows.Forms.ToolStripSeparator toolStripSeparator1;
+        private System.Windows.Forms.ToolStripSeparator toolStripSeparator2;
+        private System.Windows.Forms.LinkLabel linkLabelBioZLoad;
+        private System.Windows.Forms.ToolStripMenuItem loggingToolStripMenuItem;
+        private System.Windows.Forms.ToolStripMenuItem eCGBioZFileLogToolStripMenuItem;
+        private System.Windows.Forms.ToolStripMenuItem eCGFileLogToolStripMenuItem;
+        private System.Windows.Forms.ToolStripMenuItem rToRFileLogToolStripMenuItem;
+        private System.Windows.Forms.ToolStripMenuItem paceFileLogToolStripMenuItem;
+        private System.Windows.Forms.ToolStripMenuItem bioZFileLogToolStripMenuItem;
+        private System.Windows.Forms.ToolStripSeparator toolStripSeparator5;
+        private System.Windows.Forms.ToolStripMenuItem opticalAccelerometerFileLogToolStripMenuItem;
+        private System.Windows.Forms.ToolStripMenuItem registerExportToolStripMenuItem;
+        private System.Windows.Forms.ToolStripMenuItem loadAllRegisterSettingsToolStripMenuItem;
+        private System.Windows.Forms.ToolStripSeparator toolStripSeparator3;
+        private System.Windows.Forms.Panel pnlBlockDiagram;
+        private System.Windows.Forms.Panel pnlEcgChannel;
+        private System.Windows.Forms.PictureBox picEcgChannel;
+        private System.Windows.Forms.FlowLayoutPanel flowLayoutPanel1;
+        private System.Windows.Forms.Panel pnlEcgMux;
+        private System.Windows.Forms.Panel pnlBioZChannel;
+        private System.Windows.Forms.Panel pnlBioZMux;
+        private System.Windows.Forms.Panel pnlBioZLoad;
+        private System.Windows.Forms.Panel pnlPace;
+        private System.Windows.Forms.Label label39;
+        private System.Windows.Forms.Panel panel1;
+        private System.Windows.Forms.PictureBox picSw1;
+        private System.Windows.Forms.PictureBox picSw2;
+        private System.Windows.Forms.PictureBox pictureBox1;
+        private System.Windows.Forms.PictureBox picSw3;
+        private System.Windows.Forms.PictureBox picSw4;
+        private System.Windows.Forms.PictureBox picSw5;
+        private System.Windows.Forms.PictureBox picSw6;
+        private System.Windows.Forms.PictureBox picSw7;
+        private System.Windows.Forms.PictureBox picSw8;
+        private System.Windows.Forms.PictureBox picSw9;
+        private System.Windows.Forms.PictureBox picSw10;
+        private System.Windows.Forms.PictureBox picSw11;
+        private System.Windows.Forms.PictureBox picSw12;
+        private System.Windows.Forms.PictureBox picSw13;
+        private System.Windows.Forms.PictureBox picSw14;
+        private System.Windows.Forms.PictureBox picLoff1;
+        private System.Windows.Forms.PictureBox picLoff2;
+        private System.Windows.Forms.PictureBox picLeadOn;
+        private System.Windows.Forms.PictureBox picBioZsw1;
+        private System.Windows.Forms.PictureBox picBioZsw2;
+        private System.Windows.Forms.PictureBox picLeadBias1;
+        private System.Windows.Forms.PictureBox picLeadBias2;
+        private System.Windows.Forms.PictureBox picBioZCal1;
+        private System.Windows.Forms.PictureBox picBioZCal2;
+        private System.Windows.Forms.PictureBox picBioZLloff1;
+        private System.Windows.Forms.PictureBox picBioZLloff2;
+        private System.Windows.Forms.PictureBox picBioZLlon;
+        private System.Windows.Forms.PictureBox picBioZLsw1;
+        private System.Windows.Forms.PictureBox picBioZLlb2;
+        private System.Windows.Forms.PictureBox picBioZLcal2;
+        private System.Windows.Forms.PictureBox picBioZLcal1;
+        private System.Windows.Forms.PictureBox picBioZLlb1;
+        private System.Windows.Forms.PictureBox picBioZLsw2;
+        private System.Windows.Forms.PictureBox picBioZLresload;
+        private System.Windows.Forms.MenuStrip menuStrip1;
+        private System.Windows.Forms.ToolStripMenuItem toolStripMenuItem3;
+        private System.Windows.Forms.ToolStripMenuItem toolStripMenuItem4;
+        private System.Windows.Forms.ToolStripMenuItem toolStripMenuItem5;
+        private System.Windows.Forms.ToolStripMenuItem toolStripMenuItem6;
+        private System.Windows.Forms.ToolStripMenuItem toolStripMenuItem7;
+        private System.Windows.Forms.ToolStripMenuItem toolStripMenuItem8;
+        private System.Windows.Forms.ToolStripMenuItem toolStripMenuItem9;
+        private System.Windows.Forms.ToolStripMenuItem toolStripMenuItem10;
+        private System.Windows.Forms.ToolStripSeparator toolStripSeparator4;
+        private System.Windows.Forms.ToolStripMenuItem toolStripMenuItem11;
+        private System.Windows.Forms.ToolStripMenuItem toolStripMenuItem12;
+        private System.Windows.Forms.ToolStripSeparator toolStripSeparator6;
+        private System.Windows.Forms.ToolStripMenuItem toolStripMenuItem13;
+        private System.Windows.Forms.ToolStripMenuItem toolStripMenuItem14;
+        private System.Windows.Forms.ToolStripSeparator toolStripSeparator7;
+        private System.Windows.Forms.ToolStripMenuItem toolStripMenuItem15;
+        private System.Windows.Forms.ToolStripMenuItem toolStripMenuItem16;
+        private System.Windows.Forms.ToolStripMenuItem toolStripMenuItem17;
+        private System.Windows.Forms.ToolStripMenuItem toolStripMenuItem18;
+        private System.Windows.Forms.ToolStripMenuItem toolStripMenuItem19;
+        private System.Windows.Forms.ToolStripMenuItem toolStripMenuItem20;
+        private System.Windows.Forms.ToolStripMenuItem toolStripMenuItem21;
+        private System.Windows.Forms.ToolStripSeparator toolStripSeparator8;
+        private System.Windows.Forms.ToolStripMenuItem toolStripMenuItem22;
+        private System.Windows.Forms.ToolStripMenuItem toolStripMenuItem23;
+        private System.Windows.Forms.ToolStripMenuItem toolStripMenuItem24;
+        private System.Windows.Forms.ToolStripMenuItem toolStripMenuItem25;
+        private System.Windows.Forms.TableLayoutPanel tlbQuickStart;
+        private System.Windows.Forms.Label label40;
+        private System.Windows.Forms.LinkLabel linkLabelQuickOpticalSpO2;
+        private System.Windows.Forms.LinkLabel linkLabelQuickTemperature;
+        private System.Windows.Forms.LinkLabel linkLabelQuickBioimpedance;
+        private System.Windows.Forms.LinkLabel linkLabelQuickEcg;
+        private System.Windows.Forms.Label label41;
+        private System.Windows.Forms.LinkLabel linkLabelQuickRespiration;
+    }
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HspGuiSourceV301/HSPGui/Form1.cs	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,1902 @@
+/*******************************************************************************
+* Copyright (C) 2016 Maxim Integrated Products, Inc., All rights Reserved.
+* 
+* This software is protected by copyright laws of the United States and
+* of foreign countries. This material may also be protected by patent laws
+* and technology transfer regulations of the United States and of foreign
+* countries. This software is furnished under a license agreement and/or a
+* nondisclosure agreement and may only be used or reproduced in accordance
+* with the terms of those agreements. Dissemination of this information to
+* any party or parties not specified in the license agreement and/or
+* nondisclosure agreement is expressly prohibited.
+*
+* The above copyright notice and this permission notice shall be included
+* in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+* OTHER DEALINGS IN THE SOFTWARE.
+*
+* Except as contained in this notice, the name of Maxim Integrated
+* Products, Inc. shall not be used except as stated in the Maxim Integrated
+* Products, Inc. Branding Policy.
+*
+* The mere transfer of this software does not imply any licenses
+* of trade secrets, proprietary technology, copyrights, patents,
+* trademarks, maskwork rights, or any other form of intellectual
+* property whatsoever. Maxim Integrated Products, Inc. retains all
+* ownership rights.
+*******************************************************************************
+*/
+
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Data;
+using System.Drawing;
+using System.Linq;
+using System.Text;
+
+using System.Windows.Forms;
+using Microsoft.Win32;
+using Microsoft.Win32.SafeHandles;
+using System.Globalization;
+using System.Threading;
+using System.Management;
+using System.Diagnostics;
+using System.IO;
+using System.Collections.Specialized;
+
+using HealthSensorPlatform.DeviceDescriptions;
+using HealthSensorPlatform.CustomControls;
+using HealthSensorPlatform.View;
+using HealthSensorPlatform.Presenter;
+using HealthSensorPlatform.Model;
+
+using MAX30205EVKit.Presenter;
+
+using Maxim.MAX30101GUI;
+using Maxim.Utility;
+
+using MaximStyle;
+
+namespace HealthSensorPlatform
+{
+
+    public partial class HspForm : Form, IFormView, IHspSetting
+    {
+        /* Constants */
+        //Software Version
+        internal const int MAJORVERSION = 3;
+        internal const int MINORVERSION = 0;
+        internal const int PATCHVERSION = 1;
+        const string VersionSuffix = "";
+
+        const string PartNumber = "MAXREFDES100";
+
+        const string readVersionCommand = "/System/ReadVer\r\n";
+        const string readFlashIDCommand = "/S25FS512/ReadId\r\n";
+        const string firmwareKey = "HSP FW Version"; 
+
+        /* Fields */
+        SplashScreen splashScreen = new SplashScreen();
+        FormConnection connectionDialog = new FormConnection();
+        string port;
+        bool connected = false;
+        bool internalUpdate = false; // Used to prevent events from triggering
+        bool streaming = false; // Disable GUI features while streaming is enabled
+
+        static ManagementEventWatcher watcher; 
+
+        /* // TODO: Do not remember what this is for, can remove
+        MaximStyle.MaximNumericUpDown[] ud_cmd = new MaximStyle.MaximNumericUpDown[3];
+        MaximStyle.MaximNumericUpDown[] ud_data = new MaximStyle.MaximNumericUpDown[8];
+        Panel[] p_cmd = new Panel[3];
+        Panel[] p_data = new Panel[8];
+        */
+
+        IDeviceView[] deviceViews;
+        Maxim.CustomControls.RegisterView[] registerViews;
+        TabPage[] max30001TabPages;
+
+        RPCSupport.RPCClient rpcClient;
+        RPCSupport.Devices.I2cDevice i2cDevice;
+        RPCSupport.Devices.SpiDevice spiDevice;
+        RPCSupport.Devices.MAX30101 max30101;
+        RPCSupport.Devices.MAX30205 max30205;
+        RPCSupport.Devices.LIS2HD lis2hd;
+        RPCSupport.Devices.MAX30001 max30001;
+        RPCSupport.DataLogging.DataLogging logging;
+
+        ListDictionary registerViewDict;
+
+        //FileLogPresenter fileLogPresenter;
+        RawFileLogPresenter rawFileLogPresenter;
+        OpticalFileLogPresenter opticalFileLogPresenter;
+        TemperaturePresenter temperaturePresenter;
+
+        Model.MAX30001Model max30001Model;
+
+        public event EventHandler<EnableEventArgs> FileLogEnable;
+        public event EventHandler<EnableEventArgs> OpticalFileLogEnable;
+        public event EventHandler<EventArgs> RegisterExport;
+        public event EventHandler<EventArgs> RegisterImport;
+
+        public event EventHandler<EventArgs> Connected;
+
+        /* Constructor */
+        /// <summary>
+        /// 
+        /// </summary>
+        public HspForm()
+        {
+            InitializeComponent();
+
+            InitSplashScreen();
+
+            //initialize text in status bar
+            ss_Status.Items[0].Text = "";
+            ss_Status.Items[1].Text = "";
+
+            deviceViews = new IDeviceView[] { 
+                opticalView1, 
+                temperatureView1,
+                ecgView1,
+                dataLoggingView1,
+                rvLIS2HD,
+                rvMAX14720,
+                rvMAX30001,
+                rvMAX30101,
+                rvMAX30205,
+                rvMAX30205_U18
+            };
+
+            registerViews = new Maxim.CustomControls.RegisterView[] {
+                rvMAX30101,
+                rvMAX30205,
+                rvMAX30205_U18,
+                rvLIS2HD,
+                rvMAX30001,
+                rvMAX14720
+            };
+
+            max30001TabPages = new TabPage[] { tpMAX30001BioZInputMux, tpBioZChannel, tpMAX30001BioZLoad, tpMAX30001Pace };
+
+            registerViewDict = new ListDictionary();
+
+            InitRpcClient();
+
+            InitRpcDevices();
+            PrimitivesViewInit();
+            RegistersTabInit();
+            LoggingViewInit();
+            TemperatureViewInit();
+            OpticalViewInit();
+
+            BlockDiagramsInit();
+            ECGPlotsViewInit();
+
+            InitalizeUSBDetection();
+
+            FileLoggingInit();
+
+            RegisterExportInit();
+
+            SetupSwitchPictureBoxes();
+        }
+
+        private void SetupSwitchPictureBoxes()
+        {
+            //ECGMux Tab
+            picECGLeadConfig.Controls.Add(picSw1);
+            picSw1.Controls.Add(picSw2);
+            picSw2.Controls.Add(picSw3);
+            picSw3.Controls.Add(picSw4);
+            picSw4.Controls.Add(picSw5);
+            picSw5.Controls.Add(picSw6);
+            picSw6.Controls.Add(picSw7);
+            picSw7.Controls.Add(picSw8);
+            picSw8.Controls.Add(picSw9);
+            picSw9.Controls.Add(picSw10);
+            picSw10.Controls.Add(picSw11);
+            picSw11.Controls.Add(picSw12);
+            picSw12.Controls.Add(picSw13);
+            picSw13.Controls.Add(picSw14);
+
+            //BioZMux Tab
+            pictureBox2.Controls.Add(picLoff1);
+            picLoff1.Controls.Add(picLoff2);
+            picLoff2.Controls.Add(picLeadOn);
+            picLeadOn.Controls.Add(picBioZsw1);
+            picBioZsw1.Controls.Add(picBioZsw2);
+            picBioZsw2.Controls.Add(picLeadBias1);
+            picLeadBias1.Controls.Add(picLeadBias2);
+            picLeadBias2.Controls.Add(picBioZCal1);
+            picBioZCal1.Controls.Add(picBioZCal2);
+
+            //BioZLoad Tab
+            picBioZLoad.Controls.Add(picBioZLresload); 
+            picBioZLresload.Controls.Add(picBioZLloff1);
+            picBioZLloff1.Controls.Add(picBioZLloff2);
+            picBioZLloff2.Controls.Add(picBioZLlon);
+            picBioZLlon.Controls.Add(picBioZLsw1);
+            picBioZLsw1.Controls.Add(picBioZLsw2);
+            picBioZLsw2.Controls.Add(picBioZLlb1);
+            picBioZLlb1.Controls.Add(picBioZLlb2);
+            picBioZLlb2.Controls.Add(picBioZLcal1);
+            picBioZLcal1.Controls.Add(picBioZLcal2);
+
+
+        }
+
+        /* Delegates */
+        delegate void guiDisconnectedCallBack();
+
+        public void MessageInfo(string message)
+        {
+            ss_Status.MessagesLabel.Text = message;
+        }
+
+        public void MessageBoxShow(string message)
+        {
+            MessageBox.Show(message);
+        }
+
+        public void MessageBoxShow(string message, string title)
+        {
+            MessageBox.Show(message, title);
+        }
+
+
+        /// <summary>
+        /// http://stackoverflow.com/questions/286184/how-to-capture-a-serial-port-that-disappears-because-the-usb-cable-gets-unplugge
+        /// </summary>
+        private void InitalizeUSBDetection()
+        {
+            WqlEventQuery query;
+            ManagementScope scope;
+
+            scope = new ManagementScope("root\\CIMV2");
+            scope.Options.EnablePrivileges = true;
+
+            query = new WqlEventQuery();
+            query.EventClassName = "__InstanceDeletionEvent"; // "__InstanceCreationEvent" can be used for insertion
+            query.WithinInterval = new TimeSpan(0, 0, 3);
+            query.Condition = @"TargetInstance ISA 'Win32_USBControllerdevice'";
+            watcher = new ManagementEventWatcher(scope, query);
+            watcher.EventArrived += new EventArrivedEventHandler(USBRemovedHandler);
+            watcher.Start();
+        }
+        
+        /// <summary>
+        /// http://stackoverflow.com/questions/286184/how-to-capture-a-serial-port-that-disappears-because-the-usb-cable-gets-unplugge
+        /// </summary>
+        /// <param name="sender"></param>
+        /// <param name="e"></param>
+        private void USBRemovedHandler(object sender, EventArrivedEventArgs e)
+        {
+            PropertyData targetInstanceData = e.NewEvent.Properties["TargetInstance"];
+
+            if (targetInstanceData != null)
+            {
+                ManagementBaseObject targetInstanceObject = (ManagementBaseObject)targetInstanceData.Value;
+                if (targetInstanceData != null)
+                {
+                    string dependent = targetInstanceObject.Properties["Dependent"].Value.ToString();
+                    string deviceId = dependent.Substring(dependent.IndexOf("DeviceID=") + 10);
+
+                    if (deviceId.StartsWith("USB\\\\VID_0B6A&PID_003C")  // FW 1.5
+                        || deviceId.StartsWith("USB\\\\VID_1F00&PID_2012\\\\0123456789")
+                        || deviceId.StartsWith("USB\\\\VID_0B6A&PID_0100")) // FW 2.0 mbed
+                    {
+                        // device is disconnected
+                        guiDisconnected();
+                        try
+                        {
+                            rpcClient.Disconnect();
+                        }
+                        catch (System.IO.IOException)
+                        {
+
+                        }
+                        catch (NullReferenceException)
+                        {
+                            // Disconnecting when it doesn't exist
+                            // Occurs when you pull the USB while on the com port selection window
+                        }
+                    }
+                }
+
+            }
+            
+        }
+
+        private void InitSplashScreen()
+        {
+            splashScreen.maximSplashScreen1.CopyrightString = "©2016 Maxim Integrated Products, Inc.";
+            splashScreen.maximSplashScreen1.VersionString = "Version " + MAJORVERSION.ToString() + "." + MINORVERSION.ToString() + "." + PATCHVERSION.ToString() + VersionSuffix;
+            splashScreen.maximSplashScreen1.ApplicationName = this.Text;
+            //splashScreen.maximSplashScreen1.Checked = Properties.Settings.Default.DisableSplash;
+        }
+
+        void comPortConnect()
+        {
+            bool tryPreviousComPort = true;
+
+            connectionDialog.Reset();
+            connectionDialog.ScanPorts();
+
+            while (true)
+            {
+                // Try to connect to the previous port, if we have not tried before 
+                // and it the port string is not an empty string ("")
+                if (tryPreviousComPort == true
+                    && String.Compare(Properties.Settings.Default.ComPort, "") != 0)
+                {
+                    tryPreviousComPort = false;
+                }
+                else
+                {
+                    connectionDialog.ShowDialog();
+                }
+
+                // Break out of loop if user canceled
+                if (connectionDialog.Canceled == true)
+                {
+                    guiDisconnected();
+                    break;
+                }
+
+                // Get the port from the dialog form, returns default property
+                // for first use
+                port = connectionDialog.Port;
+                if (String.Compare(port, "") == 0)
+                    continue;
+
+
+                // Connect to port
+                try
+                {
+                    rpcClient.Connect(port);
+                    if (rpcClient.IsConnected() == true)
+                    {
+                        guiConnected();
+                        break;
+                    }
+                    else // Connected to COM port, but cannot query STM32_HV
+                    {
+                        MessageBox.Show("Device not found on selected port", "Connection Issue");
+                        guiDisconnected();
+                    }
+                }
+                catch (TimeoutException)
+                {
+                    guiDisconnected();
+                    rpcClient.Disconnect();
+                    MessageBox.Show("Unable to communicate with device, communication timed out.\nVerified selected port is correct.",
+                        "Connection Issue");
+                }
+                catch (System.IO.IOException)
+                {
+                    guiDisconnected();
+                    MessageBox.Show("Select a valid COM port. Unable to connect with device.\n\nVerify the " + PartNumber + " board is plugged in and turned on. Turn on by pressing the button on the board for 3 seconds until the red LED starts blinking.",
+                        "Connection Issue");
+                }
+                catch (UnauthorizedAccessException)
+                {
+                    // Port does not exist
+                }
+            }
+        }
+
+        bool checkFirmware()
+        {
+            string reply;
+
+            reply = rpcClient.RawRpcCall(readVersionCommand, true);
+
+            return reply.StartsWith(firmwareKey);
+        }
+
+        void guiConnected()
+        {
+            ss_Status.Items[1].Text = rpcClient.Version();//rpcClient.RawRpcCall(readVersionCommand, true); // TODO this should be moved into the RPCSupport as a virtual system device
+            ss_Status.Items[2].Text = "Hardware Connected (" + port + ")";
+
+            connected = true;
+
+            //connectionToolStripMenuItem.Enabled = false;
+            //disconnectToolStripMenuItem.Enabled = true;
+
+            connectionToolStripMenuItem.Checked = true;
+            disconnectToolStripMenuItem.Checked = false;
+
+            // Enable Communication for each Device View
+            foreach (IDeviceView device in deviceViews)
+            {
+                device.Connected = true;
+            }
+
+            // TODO Ask F/W team if this is needed
+            rpcClient.MAX30001.WriteReg(0x02, 0x3);
+            rpcClient.MAX30001.WriteReg(0x03, 0x3);
+
+            max30001Model = new Model.MAX30001Model(max30001);
+            partIDInit();
+
+            dataLoggingView1.Enabled = checkFlashID();
+
+            // Read device registers
+            UpdateRegisters();
+
+            if (Connected != null)
+                Connected(this, new EventArgs());
+        }
+
+
+        void guiDisconnected()
+        {
+            if (this.ss_Status.InvokeRequired)
+            {
+                guiDisconnectedCallBack d = new guiDisconnectedCallBack(guiDisconnected);
+                this.Invoke(d);
+            }
+            else
+            {
+                ss_Status.Items[1].Text = "";
+                ss_Status.Items[2].Text = "Hardware Not Connected";
+                //UpdateConnection(null, false);;
+                connected = false;
+
+                //connectionToolStripMenuItem.Enabled = true;
+                //disconnectToolStripMenuItem.Enabled = false;
+
+                connectionToolStripMenuItem.Checked = false;
+                disconnectToolStripMenuItem.Checked = true;
+
+                foreach (IDeviceView device in deviceViews)
+                {
+                    device.Connected = false;
+                }
+            }
+        }
+
+        void InitRpcClient()
+        {
+            rpcClient = new RPCSupport.RPCClient(RPCSupport.RPCClient.ePipeline.eSerialWrap);
+            rpcClient.InitPipeline();
+        }
+
+        void InitRpcDevices()
+        {
+            i2cDevice = rpcClient.Init_I2cDevice();
+            spiDevice = rpcClient.Init_SpiDevice();
+            max30101 = rpcClient.Init_MAX30101(0xAE);
+            max30205 = rpcClient.Init_MAX30205(0x32);
+            lis2hd = rpcClient.Init_LIS2HD(0x50);
+            max30001 = rpcClient.Init_MAX30001();
+            logging = rpcClient.Init_Logging();
+        }
+
+        private void Form_Load(object sender, EventArgs e)
+        {
+          if (splashScreen.SplashDisabled() == false)
+                splashScreen.ShowDialog();
+            
+            while (splashScreen.Visible == true)
+                Thread.Sleep(100);
+
+            comPortConnect();
+        }
+
+        void PrimitivesViewInit()
+        {
+            primitivesView1.rpcClient = rpcClient;
+            primitivesView1.i2cDevice = i2cDevice;
+            primitivesView1.spiDevice = spiDevice;
+            primitivesView1.max30101 = max30101;
+            primitivesView1.max30205 = max30205;
+            primitivesView1.max30001 = max30001;
+            primitivesView1.lis2hd = lis2hd;
+
+            maximTabControl1.HideTab("tpPrimitives");
+        }
+
+        void OpticalViewInit()
+        {
+            opticalView1.RPCClient = rpcClient;
+            //opticalView1.StreamingStartStop += new OpticalView.StreamingStartStopEventHandler(opticalView_StreamingStartStop);
+            opticalView1.StreamingStartStop += new EventHandler<StreamingStartStopEventArgs>(opticalView_StreamingStartStop);
+            dataLoggingView1.LoggingParametersChanged += new DataLoggingView.LoggingParametersHandler(dataLoggingFlashReadEventHandler);
+
+            MaximSKAlgorithmClass algorithm = new MaximSKAlgorithmClass();
+            OpticalAlgorithmPresenter presenter = new OpticalAlgorithmPresenter(rpcClient, algorithm, opticalView1);
+        }
+
+        void ECGPlotsViewInit()
+        {
+            ecgView1.RPCClient = rpcClient;
+
+            //cboEnRToR.SelectedIndexChanged += new EventHandler(cboStreaming_SelectedIndexChanged);
+            //cboECGChannelEnable.SelectedIndexChanged += new EventHandler(cboStreaming_SelectedIndexChanged);
+
+            ecgView1.GetEcgInitArgsPointer = new CustomControls.EcgView.GetEcgInitArgs(getEcgArgs); 
+            ecgView1.GetRToRInitArgsPointer = new CustomControls.EcgView.GetRToRInitArgs(getRToRArgs);
+            ecgView1.GetBioZInitArgsPointer = new CustomControls.EcgView.GetBioZInitArgs(getBioZArgs);
+            ecgView1.GetPaceInitArgsPointer = new CustomControls.EcgView.GetPaceInitArgs(getPaceArgs);
+
+            ecgView1.StreamingStartStop += new EventHandler<StreamingStartStopEventArgs>(ecgView_StreamingStartStop);
+
+            ecgView1.HspSetting = this;
+
+            StreamPresenter streamPresenter = new StreamPresenter(rpcClient, ecgView1, this);
+        }
+
+        void LoggingViewInit()
+        {
+            dataLoggingView1.RPCClient = rpcClient;
+
+            dataLoggingView1.GetEcgInitArgsPointer = new CustomControls.DataLoggingView.GetEcgInitArgs(getEcgArgs);
+            dataLoggingView1.GetRToRInitArgsPointer = new CustomControls.DataLoggingView.GetRToRInitArgs(getRToRArgs);
+            dataLoggingView1.GetBioZInitArgsPointer = new CustomControls.DataLoggingView.GetBioZInitArgs(getBioZArgs);
+            dataLoggingView1.GetPaceInitArgsPointer = new CustomControls.DataLoggingView.GetPaceInitArgs(getPaceArgs);
+            dataLoggingView1.GetFMSTRInitArgsPointer = new CustomControls.DataLoggingView.GetFMSTRInitArgs(getFMSTRArgs);
+            dataLoggingView1.GetHRModeInitArgsPointer = new CustomControls.DataLoggingView.GetHRModeInitArgs(opticalView1.GetHRModeArgs);
+            dataLoggingView1.GetSpO2HRModeInitArgsPointer = new CustomControls.DataLoggingView.GetSpO2HRModeInitArgs(opticalView1.GetSpO2HRModeArgs);
+            dataLoggingView1.GetMultiModeInitArgsPointer = new CustomControls.DataLoggingView.GetMultiModeInitArgs(opticalView1.GetMultiModeArgs);
+
+            Model.DataLogModel dataLogModel = new Model.DataLogModel(rpcClient);
+            DataLogPresenter dataLogPresenter = new DataLogPresenter(this, ecgView1, opticalView1, dataLogModel, dataLoggingView1, new RawFileLogView(), new RawFileLogView(), new RawFileLogView(), 
+                new RawFileLogView(), new RawFileLogView(), new RawFileLogView(), new RawFileLogView(), new RawFileLogView(), new RawFileLogView());
+        }
+
+        void FileLoggingInit()
+        {
+            IRawFileLogView ecgFileLog = new RawFileLogView();
+            IRawFileLogView bioZFileLog = new RawFileLogView();
+
+            //fileLogPresenter = new FileLogPresenter(ecgFileLog, bioZFileLog, this, rpcClient, ecgView1);
+            //ecgView1.EcgLog = ecgFileLog;
+            //ecgView1.BioZLog = bioZFileLog;
+
+            IRawFileLogView ecgRawFileLog = new RawFileLogView();
+            IRawFileLogView paceRawFileLog = new RawFileLogView();
+            IRawFileLogView rToRFileLog = new RawFileLogView();
+            IRawFileLogView bioZRawFileLog = new RawFileLogView();
+            rawFileLogPresenter = new RawFileLogPresenter(ecgRawFileLog, bioZRawFileLog, rToRFileLog, paceRawFileLog, this, rpcClient, ecgView1, dataLoggingView1);
+
+            IRawFileLogView opticalFileLog = new RawFileLogView();
+            IRawFileLogView accelFileLog = new RawFileLogView();
+
+            opticalFileLogPresenter = new OpticalFileLogPresenter(rpcClient, this, opticalView1, opticalFileLog, accelFileLog);
+
+        }
+
+        void RegisterExportInit()
+        {
+            RegisterExportPresenter registerExportPresenter;
+            RegisterExportForm exportForm = new RegisterExportForm();
+            List<Maxim.CustomControls.RegisterView> registerViewList = new List<Maxim.CustomControls.RegisterView>(); 
+
+            registerViewList.AddRange(registerViews);
+
+            registerExportPresenter = new RegisterExportPresenter(this, exportForm, registerViewList);
+        }
+        
+        private void txt_Status_TextChanged(object sender, EventArgs e)
+        {
+            //Scroll to the bottom of the textbox when text is added
+            txt_Status.SelectionStart = txt_Status.Text.Length;
+            txt_Status.ScrollToCaret();
+            txt_Status.Refresh();
+        }
+
+        private void btn_Clear_Click(object sender, EventArgs e)
+        {
+            //clear the status box
+            txt_Status.Text = "";
+        }
+
+        private void rvLIS2HDInit()
+        {
+            Maxim.CustomControls.LIS2DHInfo lis2DHInfo = new Maxim.CustomControls.LIS2DHInfo();
+            Maxim.CustomControls.DeviceController controller = new Maxim.CustomControls.DeviceController();
+            controller.SetRegisterInfo(lis2DHInfo);
+            controller.SetInterface(rpcClient);
+            rvLIS2HD.SetController(controller);
+            //rvLIS2HD.ReadAll();
+            rvLIS2HD.DisplayRegisters();
+            rvLIS2HD.DeviceName = "LIS2DH";
+
+
+            //registerInfoData[0] = lis2DHInfo.Info;
+        }
+
+        private void rvMAX30101Init()
+        {
+            Maxim.CustomControls.MAX30101Info max30101Info = new Maxim.CustomControls.MAX30101Info();
+            Maxim.CustomControls.DeviceController controller = new Maxim.CustomControls.DeviceController();
+            controller.SetRegisterInfo(max30101Info);
+            controller.SetInterface(rpcClient);
+            rvMAX30101.SetController(controller);
+            //rvMAX30101.ReadAll();
+            rvMAX30101.DisplayRegisters();
+            rvMAX30101.DeviceName = "MAX30101";
+
+
+            //registerInfoData[1] = max30101Info.Info;
+        }
+
+        private void rvMAX30205Init()
+        {
+            Maxim.CustomControls.MAX30205Info max30205Info = new Maxim.CustomControls.MAX30205Info(0x92);
+            Maxim.CustomControls.DeviceController controller = new Maxim.CustomControls.DeviceController();
+            controller.SetRegisterInfo(max30205Info);
+            controller.SetInterface(rpcClient);
+            rvMAX30205.SetController(controller);
+            //rvMAX30205.ReadAll();
+            rvMAX30205.DisplayRegisters();
+            rvMAX30205.DeviceName = "MAX30205 (Top)";
+
+
+            //registerInfoData[2] = max30205Info.Info;
+        }
+
+        private void rvMAX30205_U18Init()
+        {
+            Maxim.CustomControls.MAX30205Info max30205Info = new Maxim.CustomControls.MAX30205Info();
+            Maxim.CustomControls.DeviceController controller = new Maxim.CustomControls.DeviceController();
+            controller.SetRegisterInfo(max30205Info);
+            controller.SetInterface(rpcClient);
+            rvMAX30205_U18.SetController(controller);
+            //rvMAX30205_U18.ReadAll();
+            rvMAX30205_U18.DisplayRegisters();
+            rvMAX30205_U18.DeviceName = "MAX30205 (Bottom)";
+
+
+            //registerInfoData[3] = max30205Info.Info;
+        }
+
+        private void rvMAX30001Init()
+        {
+            Maxim.CustomControls.MAX30001Info max30001Info = new Maxim.CustomControls.MAX30001Info();
+            Maxim.CustomControls.DeviceController controller = new Maxim.CustomControls.DeviceController();
+            controller.SetRegisterInfo(max30001Info);
+            controller.SetInterface(rpcClient);
+            rvMAX30001.SetController(controller);
+            //rvMAX30001.ReadAll();
+            rvMAX30001.DisplayRegisters();
+            rvMAX30001.DeviceName = "MAX30001";
+
+
+            //registerInfoData[4] = max30001Info.Info;
+        }
+
+        private void rvMAX30003Init()
+        {
+            Maxim.CustomControls.MAX30003Info max30003Info = new Maxim.CustomControls.MAX30003Info();
+            Maxim.CustomControls.DeviceController controller = new Maxim.CustomControls.DeviceController();
+            controller.SetRegisterInfo(max30003Info);
+            controller.SetInterface(rpcClient);
+            rvMAX30001.SetController(controller);
+            //rvMAX30001.ReadAll();
+            rvMAX30001.DisplayRegisters();
+            rvMAX30001.DeviceName = "MAX30003";
+        }
+
+        private void rvMAX14720Init()
+        {
+            Maxim.CustomControls.MAX14720Info max14720Info = new Maxim.CustomControls.MAX14720Info();
+            Maxim.CustomControls.DeviceController controller = new Maxim.CustomControls.DeviceController();
+            controller.SetRegisterInfo(max14720Info);
+            controller.SetInterface(rpcClient);
+            rvMAX14720.SetController(controller);
+            //rvMAX14720.ReadAll();
+            rvMAX14720.DisplayRegisters();
+            rvMAX14720.DeviceName = "MAX14720";
+
+            //registerInfoData[5] = max14720Info.Info;
+        }
+
+        private void partIDInit()
+        {
+            //rvMAX30001.Clear();
+            tabPageEnable(null, false);
+            switch (max30001Model.PartID)
+            {
+                case Model.MAX30001Model.Part.MAX30003:
+                    // General GUI
+                    bioZMilliohmScaleToolStripMenuItem.Enabled = false;
+                    registerNamesToolStripMenuItem.Text = "Show MAX30003 Register Names";
+                    paceFileLogToolStripMenuItem.Enabled = false;
+                    bioZFileLogToolStripMenuItem.Enabled = false;
+
+                    // Block Diagram
+                    picBlockDiagram.Image = global::HealthSensorPlatform.Properties.Resources.system_block_diagram_max30003;
+                    linkBioZChannel.Visible = false;
+                    linkBioZMux.Visible = false;
+                    linkBioZLoad.Visible = false;
+                    linkPaceChannel.Visible = false;
+                    linkLabelQuickBioimpedance.Visible = false;
+                    linkLabelQuickRespiration.Visible = false;
+
+                    // Global Panel
+                    chkEnBioZ.Enabled = false;
+                    chkEnPace.Enabled = false;
+                    grpGlobalControls.Text = "MAX30003 Global Controls";
+
+                    // Tabs - not working 
+                    tabPageEnable(null, true);
+
+                    // Plots
+                    ecgView1.BioZFunction(false);
+
+                    // Data Logging Tab
+                    dataLoggingView1.PaceFunction(false);
+                    dataLoggingView1.BioZFunction(false);
+
+                    //Register Tabs
+                    for(int i = 0; i < cboRegisterTabDevice.Items.Count; i++)
+                    {
+                        if ((string)cboRegisterTabDevice.Items[i] == "MAX30001")
+                        {
+                            cboRegisterTabDevice.Items[i] = "MAX30003";
+                        }
+
+                    }
+                    rvMAX30003Init();
+
+                    break;
+                case Model.MAX30001Model.Part.MAX30001:
+                    // Defaults
+                    // General GUI
+                    bioZMilliohmScaleToolStripMenuItem.Enabled = true;
+                    registerNamesToolStripMenuItem.Text = "Show MAX30001 Register Names";
+                    paceFileLogToolStripMenuItem.Enabled = true;
+                    bioZFileLogToolStripMenuItem.Enabled = true;
+
+                    // Block Diagram
+                    picBlockDiagram.Image = global::HealthSensorPlatform.Properties.Resources.system_block_diagram;
+                    linkBioZChannel.Visible = true;
+                    linkBioZMux.Visible = true;
+                    linkBioZLoad.Visible = true;
+                    linkPaceChannel.Visible = true;
+                    linkLabelQuickBioimpedance.Visible = true;
+                    linkLabelQuickRespiration.Visible = true;
+
+                    // Global Panel
+                    grpGlobalControls.Text = "MAX30001 Global Controls";
+                    chkEnBioZ.Enabled = true;
+                    chkEnECG.Enabled = true;
+                    chkEnPace.Enabled = true;
+                    chkEnRtor.Enabled = true;
+
+                    // Tabs - not working
+                    tabPageEnable(null, true);
+
+                    // Plots
+                    ecgView1.BioZFunction(true);
+
+                    // Data Logging Tab
+                    dataLoggingView1.PaceFunction(true);
+                    dataLoggingView1.BioZFunction(true);
+
+                    //Register Tabs
+                    for (int i = 0; i < cboRegisterTabDevice.Items.Count; i++)
+                    {
+                        if ((string)cboRegisterTabDevice.Items[i] == "MAX30003")
+                        {
+                            cboRegisterTabDevice.Items[i] = "MAX30001";
+                        }
+
+                    }
+                    rvMAX30001Init();
+                    break;
+            }
+        }
+
+        private bool checkFlashID()
+        {
+            string reply;
+
+            reply = rpcClient.RawRpcCall(readFlashIDCommand, true);
+
+            return (reply.StartsWith("00010219"));
+        }
+
+        private void tabPageEnable(TabPage exception, bool enable)
+        {
+            if (enable)
+            {
+                if (max30001Model.PartID == MAX30001Model.Part.MAX30003)
+                {
+                    foreach (TabPage tp in maximTabControl1.TabPages)
+                    {
+                        if (!max30001TabPages.Contains(tp))
+                            tp.Enabled = true;
+                    }
+                }
+                else
+                {
+                    foreach (TabPage tp in maximTabControl1.TabPages)
+                    {
+                        tp.Enabled = true;
+                    }
+                }
+            }
+            else
+            {
+                foreach (TabPage tp in maximTabControl1.TabPages)
+                {
+                    if (tp != exception)
+                        tp.Enabled = false;
+                }
+            }
+
+            maximTabControl1.Invalidate();
+        }
+
+        private void aboutToolStripMenuItem_Click(object sender, EventArgs e)
+        {
+            splashScreen = new SplashScreen(120);
+            InitSplashScreen();
+            splashScreen.Show();
+            splashScreen.ShowOKButton();
+        }
+
+        private void exitToolStripMenuItem_Click(object sender, EventArgs e)
+        {
+            Application.Exit();
+        }
+
+        private void maximTabControl1_SelectedIndexChanged(object sender, EventArgs e)
+        {
+
+            temperatureView1.TimerState(false);
+            //ecgView1.Stream = false; // Disconnect plotting event for flash log data loading
+
+            if (maximTabControl1.SelectedTab == tpBlockDiagram)
+            {
+                updateBlockDiagramLayout();
+            }
+            else if (maximTabControl1.SelectedTab == tpTemperature)
+            {
+                if (connected)
+                {
+                    // TODO
+                    /*
+                    temperatureView1.TimerState(true);
+                    temperatureView1.UpdateRegisters();
+                    temperatureView1.ReadTemperature();
+                    */
+                    temperatureView1.TimerState(true);
+                    temperaturePresenter.OnReadAll(this, new EventArgs());
+                }
+            }
+            else if (maximTabControl1.SelectedTab == tpMAX30001EcgChannel)
+            {
+                if (connected)
+                { 
+                    ECGChannelUpdateRegisters(); // and R to R
+                    ECGGlobalUpdateRegisters();
+                }
+
+                pnlMAX30001Global.Parent = tpMAX30001EcgChannel;
+            }
+            else if (maximTabControl1.SelectedTab == tpMAX30001InputMux)
+            {
+                if (connected)
+                {
+                    ECGInputMuxUpdateRegisters();
+                    ECGGlobalUpdateRegisters();
+                }
+
+                pnlMAX30001Global.Parent = tpMAX30001InputMux;
+            }
+            else if (maximTabControl1.SelectedTab == tpMAX30001Plots)
+            {
+                pnlMAX30001Global.Parent = tpMAX30001Plots;
+                //ecgView1.Stream = true;
+                //pnlMAX30001Global.BringToFront();
+                if (connected)
+                {
+                    ECGGlobalUpdateRegisters();
+                }
+            }
+            else if (maximTabControl1.SelectedTab == tpBioZChannel)
+            {
+                if (connected)
+                {
+                    BioZChannelUpdateRegisters();
+                    ECGGlobalUpdateRegisters();
+                }
+                pnlMAX30001Global.Parent = tpBioZChannel;
+            }
+            else if (maximTabControl1.SelectedTab == tpMAX30001BioZInputMux)
+            {
+                if (connected)
+                {
+                    BioZInputMuxUpdateRegisters();
+                    ECGGlobalUpdateRegisters();
+                }
+                pnlMAX30001Global.Parent = tpMAX30001BioZInputMux;
+            }
+            else if (maximTabControl1.SelectedTab == tpMAX30001BioZLoad)
+            {
+                if (connected)
+                {
+                    BioZLoadUpdateRegisters();
+                    ECGGlobalUpdateRegisters();
+                }
+                UpdateBioZLoadSwitches(); 
+                pnlMAX30001Global.Parent = tpMAX30001BioZLoad;
+            }
+            else if (maximTabControl1.SelectedTab == tpMAX30001Pace)
+            {
+                if (connected)
+                {
+                    PaceChannelUpdateRegisters();
+                    ECGGlobalUpdateRegisters();
+                }
+                pnlMAX30001Global.Parent = tpMAX30001Pace;
+            }
+            else if (maximTabControl1.SelectedTab == tpFlashLog)
+            {
+                if (connected)
+                {
+                    dataLoggingView1.UpdateArgs();
+                }
+            }
+            else if (maximTabControl1.SelectedTab == tpRegisters)
+            {
+                if (connected)
+                {
+                    ((Maxim.CustomControls.RegisterView)registerViewDict[(string)(cboRegisterTabDevice.SelectedItem)]).ReadAll(); 
+                }
+            }
+
+            if (maximTabControl1.SelectedTab != null) // Support dynamic adding/removing of tabs
+                pnlMAX30001Global.Location = new Point(0, maximTabControl1.SelectedTab.Size.Height - pnlMAX30001Global.Size.Height);
+
+            ss_Status.MessagesLabel.Text = ""; // Clear any message from previous tabs
+        }
+
+        /// <summary>
+        /// Read all registers, used for first connect
+        /// </summary>
+        public void UpdateRegisters()
+        {
+            ECGChannelUpdateRegisters();
+            ECGInputMuxUpdateRegisters();
+            ECGGlobalUpdateRegisters();
+            BioZChannelUpdateRegisters();
+            BioZInputMuxUpdateRegisters();
+            BioZLoadUpdateRegisters();
+            PaceChannelUpdateRegisters();
+
+            //rvLIS2HD.ReadAll();
+            //rvMAX14720.ReadAll();
+            //rvMAX30001.ReadAll();
+            //rvMAX30101.ReadAll();
+            //rvMAX30205.ReadAll();
+            //rvMAX30205_U18.ReadAll();
+        }
+
+        #region Temperature Tab
+        private void TemperatureViewInit()
+        {
+            MAX30205Model max30205_1 = new MAX30205Model(rpcClient.I2cDevice, 0x92);
+            MAX30205Model max30205_2 = new MAX30205Model(rpcClient.I2cDevice, 0x90);
+
+            temperaturePresenter = new MAX30205EVKit.Presenter.TemperaturePresenter(new MAX30205Model[] { max30205_1, max30205_2 }, temperatureView1, temperatureView1);
+            //temperatureView1.max30205_1 = max30205;
+            //temperatureView1.i2cDevice = i2cDevice;
+        }
+        #endregion
+
+        #region Register Tab
+        private void RegistersTabInit()
+        {
+            pnlRegMAX30101.Visible = true;
+            pnlRegMAX30101.Visible = false;
+            pnlRegMAX30205.Visible = false;
+            pnlRegMAX14720.Visible = false;
+
+            rvLIS2HDInit();
+            rvMAX30001Init();
+            rvMAX30101Init();
+            rvMAX30205Init();
+            rvMAX30205_U18Init();
+            rvMAX14720Init();
+            registerViewDict.Add(rvLIS2HD.DeviceName, rvLIS2HD);
+            registerViewDict.Add(rvMAX30001.DeviceName, rvMAX30001);
+            registerViewDict.Add("MAX30003", rvMAX30001);
+            registerViewDict.Add(rvMAX30101.DeviceName, rvMAX30101);
+            registerViewDict.Add(rvMAX30205.DeviceName, rvMAX30205);
+            registerViewDict.Add(rvMAX30205_U18.DeviceName, rvMAX30205_U18);
+            registerViewDict.Add(rvMAX14720.DeviceName, rvMAX14720);
+
+            cboRegisterTabDevice.Items.Clear();
+            foreach (Maxim.CustomControls.RegisterView rv in registerViews)
+                cboRegisterTabDevice.Items.Add(rv.DeviceName);
+
+            cboRegisterTabDevice.SelectedIndex = 0;
+
+            // Update status message when write is complete. Clear status message when entering the register data cell
+            foreach (Maxim.CustomControls.RegisterView rv in registerViews)
+            {
+                rv.CellBeginEdit += new Maxim.CustomControls.RegisterView.CellBeginEditHandler(registerView_CellBeginEdit);
+                rv.RegisterWriteComplete += new Maxim.CustomControls.RegisterView.RegisterWriteCompleteHandler(registerView_WriteComplete);
+            }
+
+        }
+
+        private void cboRegisterTabDevice_SelectedIndexChanged(object sender, EventArgs e)
+        {
+            MaximStyle.MaximComboBox cbo = (MaximStyle.MaximComboBox)sender;
+
+            if (cbo.Text.CompareTo(rvMAX30001.DeviceName) == 0)
+            {
+                pnlRegMAX30001.Visible = true;
+                pnlRegMAX30101.Visible = false;
+                pnlRegMAX30205.Visible = false;
+                pnlRegMAX30205_U18.Visible = false;
+                pnlRegLIS2HD.Visible = false;
+                pnlRegMAX14720.Visible = false;
+                rvMAX30001.ReadAll();
+            }
+            else if (cbo.Text.CompareTo(rvMAX30101.DeviceName) == 0)
+            {
+                pnlRegMAX30001.Visible = false;
+                pnlRegMAX30101.Visible = true;
+                pnlRegMAX30205.Visible = false;
+                pnlRegMAX30205_U18.Visible = false;
+                pnlRegLIS2HD.Visible = false;
+                pnlRegMAX14720.Visible = false;
+                rvMAX30101.ReadAll();
+            }
+            else if (cbo.Text.CompareTo(rvMAX30205.DeviceName) == 0)
+            {
+                pnlRegMAX30001.Visible = false;
+                pnlRegMAX30101.Visible = false;
+                pnlRegMAX30205.Visible = true;
+                pnlRegMAX30205_U18.Visible = false;
+                pnlRegLIS2HD.Visible = false;
+                pnlRegMAX14720.Visible = false;
+                rvMAX30205.ReadAll();
+            }
+            else if (cbo.Text.CompareTo(rvMAX30205_U18.DeviceName) == 0)
+            {
+                pnlRegMAX30001.Visible = false;
+                pnlRegMAX30101.Visible = false;
+                pnlRegMAX30205.Visible = true;
+                pnlRegMAX30205_U18.Visible = true;
+                pnlRegLIS2HD.Visible = false;
+                pnlRegMAX14720.Visible = false;
+                rvMAX30205_U18.ReadAll();
+            }
+            else if (cbo.Text.CompareTo(rvLIS2HD.DeviceName) == 0)
+            {
+                pnlRegMAX30001.Visible = false;
+                pnlRegMAX30101.Visible = false;
+                pnlRegMAX30205.Visible = false;
+                pnlRegMAX30205_U18.Visible = false;
+                pnlRegLIS2HD.Visible = true;
+                pnlRegMAX14720.Visible = false;
+                rvLIS2HD.ReadAll();
+            }
+            else if (cbo.Text.CompareTo(rvMAX14720.DeviceName) == 0)
+            {
+                pnlRegMAX30001.Visible = false;
+                pnlRegMAX30101.Visible = false;
+                pnlRegMAX30205.Visible = false;
+                pnlRegMAX30205_U18.Visible = false;
+                pnlRegLIS2HD.Visible = false;
+                pnlRegMAX14720.Visible = true;
+                rvMAX14720.ReadAll();
+            }
+        }
+        #endregion
+
+        #region Optical Tab
+        private void opticalView_StreamingStartStop(object sender, StreamingStartStopEventArgs e)
+        {
+            /* Disable user selection to Tabs when Streaming is enabled */
+            streaming = e.state;
+            if (e.state == true)
+            {
+                tabPageEnable(tpOpticalSensor, false);
+            }
+            else
+            {
+                tabPageEnable(tpOpticalSensor, true);
+            }
+            maximTabControl1.Invalidate(); // Redraw the tabs
+        }
+        #endregion
+
+        #region Block Diagrams
+        private void BlockDiagramsInit()
+        {
+            initalizeECGConfigFields(); 
+            initalizeECGInputMuxFields();
+            initalizeRToRFields();
+            initalizeECGGlobalControls();
+            initalizeBioZConfigFields();
+            initalizeBioZInputMuxFields();
+            initalizeBioZLoadFields();
+            initalizePaceChannelFields();
+
+            // Set ECG Gain setting for chart Y-scale purposes
+            cboChannelGain.SelectedIndexChanged += new EventHandler(cboChannelGain_SelectedIndexChanged);
+
+            //cboECGChannelEnable.SelectedIndex = 0; // Default is disabled
+
+            initalizeToolTipEvents(ecgChannelField);
+            initalizeToolTipEvents(rToRField);
+            initalizeToolTipEvents(ecgInputMuxField);
+            initalizeToolTipEvents(ecgGlobalField);
+            initalizeToolTipEvents(bioZChannelField);
+            initalizeToolTipEvents(bioZInputMuxField);
+            initalizeToolTipEvents(bioZLoadField);
+            initalizeToolTipEvents(paceChannelField);
+
+            // Force panel load for location placement in case of window resize
+            // on a tab where the panel is not shown otherwise it will show in a strange location
+            pnlMAX30001Global.Parent = tpMAX30001EcgChannel;
+        }
+
+        #endregion
+
+        #region Streaming
+        private void ecgView_StreamingStartStop(object sender, StreamingStartStopEventArgs e)
+        {
+            streaming = e.state;
+            /* Disable user selection to Tabs when Streaming is enabled */
+            if (e.state == true)
+            {
+                tabPageEnable(tpMAX30001Plots, false);
+
+                grpChannelPlotEnable.Enabled = false;
+                grpGlobalControls.Enabled = false;
+                menuStrip1.Enabled = false;
+            }
+            else
+            {
+                if (connected)
+                {
+                    // Rewrite enable bits for global controls to allow GUI to maintain consistent state
+                    foreach (RegisterField field in channelEnableField)
+                    {
+                        MaximCheckBox chk = (MaximStyle.MaximCheckBox)field.Control;
+
+                        if (chk.Checked)
+                            writeCheckBox(chk);
+                    }
+
+                    if (cboEnRbias.SelectedIndex != 0)
+                        writeComboBox(cboEnRbias);
+                    else if (cboBioZEnRbias.SelectedIndex != 0)
+                        writeComboBox(cboBioZEnRbias);
+
+                    if (cboEnDcloff.SelectedIndex != 0)
+                        writeComboBox(cboEnDcloff);
+                    else if (cboBioZEnDcloff.SelectedIndex != 0)
+                        writeComboBox(cboBioZEnDcloff);
+
+                    if (cboBioZDigitalLeadOffDetectionEnable.SelectedIndex != 0)
+                        writeComboBox(cboBioZDigitalLeadOffDetectionEnable);
+
+                    if (cboEmuxEnUlpLon.SelectedIndex != 0)
+                        writeComboBox(cboEmuxEnUlpLon);
+                    else if (cboBmuxEnUlpLon.SelectedIndex != 0)
+                        writeComboBox(cboBmuxEnUlpLon);
+
+                }
+                
+                tabPageEnable(tpMAX30001Plots, true);
+
+                grpChannelPlotEnable.Enabled = true;
+                grpGlobalControls.Enabled = true;
+                menuStrip1.Enabled = true;
+            }
+
+            maximTabControl1.Invalidate(); // Redraw the tabs
+        }
+        #endregion
+
+        #region Data Logging
+        // When Data Logging reads the flash, update the values on the other tabs to match what is in the flash
+        // The data logging tab will generate an event and run this method
+        private void dataLoggingFlashReadEventHandler(object sender, EventArgs e)
+        {
+            DataLoggingView dlView = (DataLoggingView)sender;
+
+            if (dlView.EnableOpticalHR)
+            {
+                opticalView1.SetHRModeArgs(dlView.HRModeArgs);
+            }
+            else if (dlView.EnableOpticalSpO2)
+            {
+                opticalView1.SetSpO2HRModeArgs(dlView.SpO2HRModeArgs);
+            }
+            else if (dlView.EnableOpticalMulti)
+            {
+                opticalView1.SetMultiModeArgs(dlView.MultiModeArgs);
+            }
+
+            if (dlView.EnableEcg)
+            {
+                setEcgArgs(dlView.EcgArgs);
+            }
+
+            if (dlView.EnableBioz)
+            {
+                setBioZArgs(dlView.BioZArgs);
+            }
+
+            if (dlView.EnableRToR)
+            {
+                setRToRArgs(dlView.RToRArgs);
+            }
+
+            if (dlView.EnablePace)
+            {
+                setPaceArgs(dlView.PaceArgs);
+            }
+        }
+        #endregion
+
+        private void connectionToolStripMenuItem_Click(object sender, EventArgs e)
+        {
+            if (connectionToolStripMenuItem.Checked)
+            {
+                connectionToolStripMenuItem.Checked = true;
+                return;
+            }
+
+            if (!connected)
+            {
+                comPortConnect();
+            }
+        }
+
+        private void disconnectToolStripMenuItem_Click(object sender, EventArgs e)
+        {
+            if (disconnectToolStripMenuItem.Checked)
+            {
+                disconnectToolStripMenuItem.Checked = true;
+                return;
+            }
+
+            if (connected)
+            {
+                guiDisconnected();
+                rpcClient.Disconnect();
+            }
+        }
+
+        /// <summary>
+        /// Stop streaming before exiting HSP
+        /// </summary>
+        /// <param name="sender"></param>
+        /// <param name="e"></param>
+        private void HspForm_FormClosing(object sender, FormClosingEventArgs e)
+        {
+            try
+            {
+                if (connected)
+                {
+                    opticalView1.Close(); // Stop streaming
+                    ecgView1.Close();
+                }
+            }
+            catch (Exception)
+            {
+                // We are exiting the GUI, we can ignore all exceptions
+                // Adding this for the case where the user unplugs HSP and quickly tries to close
+                // before the operating system reports USB removed
+                // Occurs while streaming ECG because we re-write the interrupt registers on stream stop
+                return;
+            }
+        }
+
+        private void linkLabel1_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
+        {
+            maximTabControl1.SelectedTab = tpMAX30001InputMux;
+        }
+
+        private void linkLabel2_Click(object sender, EventArgs e)
+        {
+            maximTabControl1.SelectedTab = tpMAX30001BioZInputMux;
+        }
+
+        private void linkLabelBioZLoad_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
+        {
+            maximTabControl1.SelectedTab = tpMAX30001BioZLoad;
+        }
+
+        private void linkLabelQuickOpticalSpO2_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
+        {
+            if (connected)
+            {
+                opticalView1.OpticalSensorDefaults();
+                maximTabControl1.SelectedTab = tpOpticalSensor;
+            }
+        }
+
+        private void linkLabelQuickTemperature_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
+        {
+            if (connected)
+            {
+                temperaturePresenter.WriteRegister(0, 1, 0);
+                temperaturePresenter.WriteRegister(1, 1, 0);
+                maximTabControl1.SelectedTab = tpTemperature;
+            }
+        }
+
+        private void linkLabelQuickEcg_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
+        {
+            if (connected)
+            {
+                // SW_RST
+                max30001Model.Write(0x08, 1);
+                max30001Model.Write(0x08, 0);
+                // CNFG_GEN
+                max30001Model.Write(0x10, 0x080017);
+                // CNFG_EMUX
+                max30001Model.Write(0x14, 0x000000);
+                // CNFG_RTOR1
+                max30001Model.Write(0x1d, 0x3FA300);
+
+                ECGChannelUpdateRegisters();
+                ECGInputMuxUpdateRegisters();
+
+                maximTabControl1.SelectedTab = tpMAX30001Plots;
+            }
+        }
+
+        private void linkLabelQuickBioimpedance_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
+        {
+            if (connected)
+            {
+                // SW_RST
+                max30001Model.Write(0x08, 1);
+                max30001Model.Write(0x08, 0);
+                // CNFG_GEN
+                max30001Model.Write(0x10, 0x040027);
+                // CNFG_BMUX
+                max30001Model.Write(0x17, 0x000040);
+                // CNFG_BIOZ
+                max30001Model.Write(0x18, 0x601430);
+
+                ECGChannelUpdateRegisters();
+                ECGInputMuxUpdateRegisters();
+                BioZChannelUpdateRegisters();
+                BioZInputMuxUpdateRegisters();
+
+                bioZMilliohmScaleToolStripMenuItem.Checked = false;
+                ecgView1.BioZMilliOhmRange = false;
+
+                maximTabControl1.SelectedTab = tpMAX30001Plots;
+            }
+        }
+
+        private void linkLabelQuickRespiration_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
+        {
+            if (connected)
+            {
+                // SW_RST
+                max30001Model.Write(0x08, 1);
+                max30001Model.Write(0x08, 0);
+                // CNFG_GEN
+                max30001Model.Write(0x10, 0x040027);
+                // CNFG_BMUX
+                max30001Model.Write(0x17, 0x000040);
+                // CNFG_BIOZ
+                max30001Model.Write(0x18, 0x201050);
+
+                ECGChannelUpdateRegisters();
+                ECGInputMuxUpdateRegisters();
+                BioZChannelUpdateRegisters();
+                BioZInputMuxUpdateRegisters();
+
+                bioZMilliohmScaleToolStripMenuItem.Checked = true;
+                ecgView1.BioZMilliOhmRange = true;
+
+                maximTabControl1.SelectedTab = tpMAX30001Plots;
+            }
+        }
+
+        private void btnSwRst_Click(object sender, EventArgs e)
+        {
+            if (!connected)
+                return;
+
+            max30001.WriteReg(0x08, 0x01);
+            max30001.WriteReg(0x08, 0x00);
+
+            UpdateRegisters();
+        }
+
+        private void btnSynch_Click(object sender, EventArgs e)
+        {
+            if (!connected)
+                return;
+
+            max30001.WriteReg(0x09, 0x01);
+            max30001.WriteReg(0x09, 0x00);
+        }
+
+        private void btnFifoRst_Click(object sender, EventArgs e)
+        {
+            if (!connected)
+                return;
+
+            max30001.WriteReg(0x0A, 0x01);
+            max30001.WriteReg(0x0A, 0x00);
+        }
+
+        private void registerNamesToolStripMenuItem_Click(object sender, EventArgs e)
+        {
+            List<RegisterField>[] fields = new List<RegisterField>[]{ ecgChannelField, ecgInputMuxField, ecgGlobalField, rToRField,  bioZChannelField, bioZInputMuxField, bioZLoadField, paceChannelField };
+            ToolStripMenuItem tsi = (ToolStripMenuItem)sender;
+
+            if (tsi.Checked == true)
+            {
+                // Combo Boxes
+                foreach (List<RegisterField> listRegisterField in fields)
+                {
+                    foreach(RegisterField rf in listRegisterField)
+                    {
+                        if (rf.Label != null)
+                            rf.Label.Text = rf.Name;
+                    }
+                }
+
+                // Check Boxes
+                foreach (RegisterField rf in channelEnableField)
+                {
+                    rf.LabelDescription = rf.Control.Text;
+                    rf.Control.Text = rf.Name;
+                }
+
+                string calHighRegName = "CAL_THIGH";
+                cboCalFifty.Items[0] = calHighRegName;
+                cboBioZCalFifty.Items[0] = calHighRegName;
+                if (cboCalFifty.SelectedIndex == 0)
+                {
+                    cboCalFifty.SelectedIndex = ecgCalFiftyField.ReadField();
+                    cboBioZCalFifty.SelectedIndex = biozCalFiftyField.ReadField();
+                }
+
+            }
+            else
+            {
+                // Combo Boxes
+                foreach (List<RegisterField> listRegisterField in fields)
+                {
+                    foreach (RegisterField rf in listRegisterField)
+                    {
+                        if (rf.Label != null)
+                            rf.Label.Text = rf.LabelDescription;
+                    }
+                }
+                
+                // Check Boxes
+                foreach (RegisterField rf in channelEnableField)
+                {
+                    rf.Control.Text = rf.LabelDescription;
+                }
+
+                string calHighRegName = "Time High";
+                cboCalFifty.Items[0] = calHighRegName;
+                cboBioZCalFifty.Items[0] = calHighRegName;
+                if (cboCalFifty.SelectedIndex == 0)
+                {
+                    cboCalFifty.SelectedIndex = ecgCalFiftyField.ReadField();
+                    cboBioZCalFifty.SelectedIndex = biozCalFiftyField.ReadField();
+                }
+            }
+        }
+
+        /// <summary>
+        /// Prevent tab changes while streaming
+        /// </summary>
+        /// <param name="sender"></param>
+        /// <param name="e"></param>
+        private void maximTabControl1_Selecting(object sender, TabControlCancelEventArgs e)
+        {
+            if (streaming && connected)
+                e.Cancel = true;
+        }
+
+        private void showAdvancedTabToolStripMenuItem_Click(object sender, EventArgs e)
+        {
+            if (showAdvancedTabToolStripMenuItem.Checked)
+            {
+                maximTabControl1.UnhideTab("tpPrimitives");
+            }
+            else
+            {
+                maximTabControl1.HideTab("tpPrimitives");
+            }
+        }
+
+        private void registerView_CellBeginEdit(object sender, DataGridViewCellCancelEventArgs e)
+        {
+            ss_Status.MessagesLabel.Text = "";
+        }
+
+        private void registerView_WriteComplete(object sender, Maxim.CustomControls.RegisterView.RegisterArgs e)
+        {
+            ss_Status.MessagesLabel.Text = "Write Reg " + e.Register.ToString("X2") + "h Complete";
+        }
+
+        private void bioZMilliohmScaleToolStripMenuItem_Click(object sender, EventArgs e)
+        {
+            // Set the BioZ chart to be in units of milliohms or ohms
+            ecgView1.BioZMilliOhmRange = bioZMilliohmScaleToolStripMenuItem.Checked;
+        }
+
+        public void LogFileItem(StreamType stream, bool state)
+        {
+            switch(stream)
+            {
+                case StreamType.Ecg:
+                    eCGFileLogToolStripMenuItem.Checked = state;
+                    break;
+                case StreamType.RToR:
+                    rToRFileLogToolStripMenuItem.Checked = state;
+                    break;
+                case StreamType.Pace:
+                    paceFileLogToolStripMenuItem.Checked = state;
+                    break;
+                case StreamType.BioZ:
+                    bioZFileLogToolStripMenuItem.Checked = state;
+                    break;
+                case StreamType.Optical:
+                    opticalAccelerometerFileLogToolStripMenuItem.Checked = state;
+                    break;
+                
+                // TODO other stream types
+            }
+        }
+
+        public void OpticalLogFileItem(bool state)
+        {
+            opticalAccelerometerFileLogToolStripMenuItem.Checked = state;
+        }
+
+        public void EcgLogFileItem(bool state)
+        {
+            eCGFileLogToolStripMenuItem.Checked = state;
+        }
+
+        public void BioZLogFileItem(bool state)
+        {
+            bioZFileLogToolStripMenuItem.Checked = state;
+        }
+
+        public void RtoRLogFileItem(bool state)
+        {
+            rToRFileLogToolStripMenuItem.Checked = state;
+        }
+
+        public void PaceLogFileItem(bool state)
+        {
+            paceFileLogToolStripMenuItem.Checked = state;
+        }
+
+        private void eCGBioZFileLogToolStripMenuItem_Click(object sender, EventArgs e)
+        {
+            if (FileLogEnable != null)
+                FileLogEnable(this, new EnableEventArgs(StreamType.Ecg, !eCGBioZFileLogToolStripMenuItem.Checked));
+        }
+
+        private void eCGFileLogToolStripMenuItem_Click(object sender, EventArgs e)
+        {
+            if (FileLogEnable != null)
+                FileLogEnable(this, new EnableEventArgs(StreamType.Ecg, !eCGFileLogToolStripMenuItem.Checked));
+        }
+
+        private void rToRFileLogToolStripMenuItem_Click(object sender, EventArgs e)
+        {
+            if (FileLogEnable != null)
+                FileLogEnable(this, new EnableEventArgs(StreamType.RToR, !rToRFileLogToolStripMenuItem.Checked));
+        }
+
+        private void paceFileLogToolStripMenuItem_Click(object sender, EventArgs e)
+        {
+            if (FileLogEnable != null)
+                FileLogEnable(this, new EnableEventArgs(StreamType.Pace, !paceFileLogToolStripMenuItem.Checked));
+        }
+
+        private void bioZFileLogToolStripMenuItem_Click(object sender, EventArgs e)
+        {
+            if (FileLogEnable != null)
+                FileLogEnable(this, new EnableEventArgs(StreamType.BioZ, !bioZFileLogToolStripMenuItem.Checked));
+        }
+
+        private void opticalAccelerometerFileLogToolStripMenuItem_Click(object sender, EventArgs e)
+        {
+            if (OpticalFileLogEnable != null)
+                OpticalFileLogEnable(this, new EnableEventArgs(StreamType.Optical,!opticalAccelerometerFileLogToolStripMenuItem.Checked));
+        }
+
+        private void registerExportToolStripMenuItem_Click(object sender, EventArgs e)
+        {
+            if (RegisterExport != null)
+                RegisterExport(this, e);
+        }
+
+        private void loadAllRegisterSettingsToolStripMenuItem_Click(object sender, EventArgs e)
+        {
+            if (RegisterImport != null)
+                RegisterImport(this, e);
+        }
+
+
+        #region Home Tab
+        private void linkTempSensor_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
+        {
+            maximTabControl1.SelectedTab = tpTemperature;
+        }
+
+        private void linkOpticalSensor_Click(object sender, LinkLabelLinkClickedEventArgs e)
+        {
+            maximTabControl1.SelectedTab = tpOpticalSensor;
+        }
+
+        private void linkEcgChannel_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
+        {
+            maximTabControl1.SelectedTab = tpMAX30001EcgChannel;
+        }
+
+        private void linkEcgMux_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
+        {
+            maximTabControl1.SelectedTab = tpMAX30001InputMux;
+        }
+
+        private void linkPaceChannel_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
+        {
+            maximTabControl1.SelectedTab = tpMAX30001Pace;
+        }
+
+        private void linkBioZChannel_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
+        {
+            maximTabControl1.SelectedTab = tpBioZChannel;
+        }
+
+        private void linkBioZMux_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
+        {
+            maximTabControl1.SelectedTab = tpMAX30001BioZInputMux;
+        }
+
+        private void linkBioZLoad_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
+        {
+            maximTabControl1.SelectedTab = tpMAX30001BioZLoad;
+        } 
+        #endregion
+
+        private void updateBlockDiagramLayout()
+        {
+            //Stopwatch stopWatch = new Stopwatch();
+            double scale;
+            int scaledWidth, scaledHeight;
+            int widthOffset;
+            int blockWidth = pnlBlockDiagram.Width;
+            int blockHeight = pnlBlockDiagram.Height;
+
+            int height = maximTabControl1.TabPages[0].Height;
+            int width = maximTabControl1.TabPages[0].Width;
+
+            //stopWatch.Start();
+
+            if (height < width)
+            {
+                scale = (double)height / blockHeight;
+            }
+            else
+            {
+                scale = (double)width / blockWidth;
+            }
+
+            scaledWidth = (int)(scale * blockWidth + 0.5);
+            scaledHeight = (int)(scale * blockHeight + 0.5);
+            widthOffset = (int)((width - scaledWidth + 0.5) / 2.0);
+
+            pnlBlockDiagram.Width = scaledWidth;
+            pnlBlockDiagram.Height = scaledHeight;
+            pnlBlockDiagram.Location = new Point(widthOffset, 0);
+
+            //System.Diagnostics.Debug.Print(" X: " + linkTempSensor.Location.X + " Y: " + linkTempSensor.Location.Y);
+            scaleControlCenter(linkTempSensor, scale);
+            scaleControlCenter(linkOpticalSensor, scale);
+            scaleControlCenter(linkEcgChannel, scale);
+            scaleControlCenter(linkEcgMux, scale);
+            scaleControlCenter(linkBioZChannel, scale);
+            scaleControlCenter(linkBioZMux, scale);
+            scaleControlCenter(linkBioZLoad, scale);
+            scaleControlCenter(linkPaceChannel, scale);
+
+            // Quick Start Location
+            tlbQuickStart.Location = new Point(pnlBlockDiagram.Location.X + pnlBlockDiagram.Size.Width + 5, pnlBlockDiagram.Location.Y + 50);
+            //System.Diagnostics.Debug.Print("Scale: " + scale + " X: " + linkTempSensor.Location.X + " Y: " + linkTempSensor.Location.Y);
+
+            if (maximTabControl1.SelectedTab.Name != "tpBlockDiagram")
+            {
+                maximTabControl1.Refresh();
+            }
+
+            //stopWatch.Stop();
+
+            //TimeSpan ts = stopWatch.Elapsed;
+
+            //string elapsedTime = String.Format("{0:00}:{1:00}:{2:00}.{3:00}", ts.Hours, ts.Minutes, ts.Seconds, ts.Milliseconds / 10);
+            //System.Diagnostics.Debug.Print("Run time " + elapsedTime);
+        }
+
+        private void updateOT90DiagramLayout(Panel panel)
+        {
+            updateOT90DiagramLayout(panel, 0);
+        }
+
+        private void updateOT90DiagramLayout(Panel panel, int heightOffset)
+        {
+            Stopwatch stopWatch = new Stopwatch();
+            double scale, scaleWidth, scaleHeight;
+            int scaledWidth, scaledHeight;
+            int widthOffset;
+            int blockWidth = panel.Width;
+            int blockHeight = panel.Height;
+
+            int height = maximTabControl1.SelectedTab.Height - pnlMAX30001Global.Height - heightOffset;
+            int width = maximTabControl1.SelectedTab.Width;
+
+            stopWatch.Start();
+
+            // Scale to the smaller dimension, the smaller side dominates the scaling factor
+            scaleWidth = (double)(width - 40) / blockWidth;
+            scaleHeight = (double)height / blockHeight;
+            if (scaleWidth < scaleHeight)
+                scale = scaleWidth;
+            else
+                scale = scaleHeight;
+
+            scaledWidth = (int)(scale * blockWidth + 0.5);
+            scaledHeight = (int)(scale * blockHeight + 0.5);
+            widthOffset = (int)((width - scaledWidth + 0.5) / 2.0);
+
+            panel.Width = scaledWidth;
+            panel.Height = scaledHeight;
+            panel.Location = new Point(widthOffset, 10);
+
+            foreach (Control cntl in panel.Controls)
+            {
+                scaleControl(cntl, scale);
+            }
+
+            //maximTabControl1.Refresh();
+
+            stopWatch.Stop();
+
+            TimeSpan ts = stopWatch.Elapsed;
+
+            string elapsedTime = String.Format("{0:00}:{1:00}:{2:00}.{3:00}", ts.Hours, ts.Minutes, ts.Seconds, ts.Milliseconds / 10);
+            System.Diagnostics.Debug.Print("Run time " + elapsedTime);
+        }
+
+        void scaleControl(Control c, double scale)
+        {
+            int x = c.Location.X;
+            int y = c.Location.Y;
+
+            double newX, newY;
+
+            newX = ((x) * scale + 0.5);
+            newY = ((y + c.Size.Height / 2) * scale + 0.5) - c.Size.Height / 2;
+
+            c.Location = new Point((int)(newX), (int)(newY));
+        }
+
+        void scaleControlCenter(Control c, double scale)
+        {
+            int x = c.Location.X;
+            int y = c.Location.Y;
+
+            double newX, newY;
+
+            newX = ((x + c.Size.Width / 2) * scale + 0.5) - c.Size.Width / 2;
+            newY = ((y + c.Size.Height / 2) * scale + 0.5) - c.Size.Height / 2;
+
+            c.Location = new Point((int)newX, (int)newY);
+        }
+
+        void scaleControlRight(Control c, double scale)
+        {
+            double AlignX = 590.0/636;
+            int x = c.Location.X;
+            int y = c.Location.Y;
+
+            double newX, newY;
+
+            newX = ((x + c.Size.Width) * scale + 0.5) - c.Size.Width;
+            newY = ((y + c.Size.Height / 2) * scale + 0.5) - c.Size.Height / 2;
+
+            c.Location = new Point((int)(AlignX * picBlockDiagram.Width - c.Size.Width), (int)(newY));
+
+        }
+
+        private void updateAllBlockDiagrams()
+        {
+            //this.SuspendLayout();
+            updateBlockDiagramLayout();
+            updateOT90DiagramLayout(pnlEcgChannel, grpRToR.Height + 20);
+            updateOT90DiagramLayout(pnlEcgMux);
+            updateOT90DiagramLayout(pnlBioZChannel);
+            updateOT90DiagramLayout(pnlBioZMux);
+            updateOT90DiagramLayout(pnlBioZLoad);
+            updateOT90DiagramLayout(pnlPace);
+            //this.ResumeLayout();
+        }
+
+        private void HspForm_ResizeEnd(object sender, EventArgs e)
+        {
+            updateAllBlockDiagrams();
+        }
+
+        protected override void WndProc(ref Message m)
+        {
+            if (m.Msg == /*WM_SIZE*/ 0x0005)
+            {
+                if (this.WindowState == FormWindowState.Maximized || this.WindowState == FormWindowState.Normal)
+                {
+                    updateAllBlockDiagrams();
+                }
+            }
+
+            base.WndProc(ref m);
+        }
+
+        public class DebugTextWriter : StreamWriter
+        {
+            public DebugTextWriter()
+                : base(new DebugOutStream(), Encoding.Unicode, 1024)
+            {
+                this.AutoFlush = true;
+            }
+
+            class DebugOutStream : Stream
+            {
+                public override void Write(byte[] buffer, int offset, int count)
+                {
+                    Debug.Write(Encoding.Unicode.GetString(buffer, offset, count));
+                }
+
+                public override bool CanRead { get { return false; } }
+                public override bool CanSeek { get { return false; } }
+                public override bool CanWrite { get { return true; } }
+                public override void Flush() { Debug.Flush(); }
+                public override long Length { get { throw new InvalidOperationException(); } }
+                public override int Read(byte[] buffer, int offset, int count) { throw new InvalidOperationException(); }
+                public override long Seek(long offset, SeekOrigin origin) { throw new InvalidOperationException(); }
+                public override void SetLength(long value) { throw new InvalidOperationException(); }
+                public override long Position
+                {
+                    get { throw new InvalidOperationException(); }
+                    set { throw new InvalidOperationException(); }
+                }
+            };
+        }
+
+        private void onlineDocumentationToolStripMenuItem_Click(object sender, EventArgs e)
+        {
+            Process.Start("http://www.maximintegrated.com/MAXREFDES100");
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HspGuiSourceV301/HSPGui/Form1.resx	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,299 @@
+<?xml version="1.0" encoding="utf-8"?>
+<root>
+  <!-- 
+    Microsoft ResX Schema 
+    
+    Version 2.0
+    
+    The primary goals of this format is to allow a simple XML format 
+    that is mostly human readable. The generation and parsing of the 
+    various data types are done through the TypeConverter classes 
+    associated with the data types.
+    
+    Example:
+    
+    ... ado.net/XML headers & schema ...
+    <resheader name="resmimetype">text/microsoft-resx</resheader>
+    <resheader name="version">2.0</resheader>
+    <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+    <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+    <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
+    <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+    <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+        <value>[base64 mime encoded serialized .NET Framework object]</value>
+    </data>
+    <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+        <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
+        <comment>This is a comment</comment>
+    </data>
+                
+    There are any number of "resheader" rows that contain simple 
+    name/value pairs.
+    
+    Each data row contains a name, and value. The row also contains a 
+    type or mimetype. Type corresponds to a .NET class that support 
+    text/value conversion through the TypeConverter architecture. 
+    Classes that don't support this are serialized and stored with the 
+    mimetype set.
+    
+    The mimetype is used for serialized objects, and tells the 
+    ResXResourceReader how to depersist the object. This is currently not 
+    extensible. For a given mimetype the value must be set accordingly:
+    
+    Note - application/x-microsoft.net.object.binary.base64 is the format 
+    that the ResXResourceWriter will generate, however the reader can 
+    read any of the formats listed below.
+    
+    mimetype: application/x-microsoft.net.object.binary.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
+            : and then encoded with base64 encoding.
+    
+    mimetype: application/x-microsoft.net.object.soap.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+            : and then encoded with base64 encoding.
+
+    mimetype: application/x-microsoft.net.object.bytearray.base64
+    value   : The object must be serialized into a byte array 
+            : using a System.ComponentModel.TypeConverter
+            : and then encoded with base64 encoding.
+    -->
+  <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+    <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
+    <xsd:element name="root" msdata:IsDataSet="true">
+      <xsd:complexType>
+        <xsd:choice maxOccurs="unbounded">
+          <xsd:element name="metadata">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" />
+              </xsd:sequence>
+              <xsd:attribute name="name" use="required" type="xsd:string" />
+              <xsd:attribute name="type" type="xsd:string" />
+              <xsd:attribute name="mimetype" type="xsd:string" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="assembly">
+            <xsd:complexType>
+              <xsd:attribute name="alias" type="xsd:string" />
+              <xsd:attribute name="name" type="xsd:string" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="data">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+                <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
+              <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+              <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="resheader">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" />
+            </xsd:complexType>
+          </xsd:element>
+        </xsd:choice>
+      </xsd:complexType>
+    </xsd:element>
+  </xsd:schema>
+  <resheader name="resmimetype">
+    <value>text/microsoft-resx</value>
+  </resheader>
+  <resheader name="version">
+    <value>2.0</value>
+  </resheader>
+  <resheader name="reader">
+    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <resheader name="writer">
+    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <metadata name="ss_Status.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
+    <value>17, 17</value>
+  </metadata>
+  <metadata name="toolTip1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
+    <value>400, 17</value>
+  </metadata>
+  <metadata name="menuStrip1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
+    <value>497, 17</value>
+  </metadata>
+  <metadata name="$this.TrayHeight" type="System.Int32, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
+    <value>42</value>
+  </metadata>
+  <assembly alias="System.Drawing" name="System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
+  <data name="$this.Icon" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+    <value>
+        AAABAAEAMDAAAAEAIACoJQAAFgAAACgAAAAwAAAAYAAAAAEAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAqbEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAqLEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAKmyAAAAAAAAAAAAAAAAAACpsgABqLEACqmyABGpsgAWqbIAGaixABqosQAaqbIAGaix
+        ABapsgARqLEAC6myAAIAAAAAAAAAAAAAAACpsgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAACpsgAAAAAAAAAAAAAAAAAAqLEAE6ixACuosQBUqLEAkqmyAMGpsgDlqbIA/aix
+        AP+osQD/qLEA/qmyAOiosQDFqbIAl6myAFqpsgAuqbIAFQAAAAAAAAAAAAAAAKixAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAqbIAAKixAAAAAAAAAAAAAKmyAB6psgBUqbIApKmyAOupsgD/qLEA/6my
+        AP+osQD/qLEA/6ixAP+psgD/qLEA/6ixAP+osQD/qbIA/6ixAP+osQDyqLEAqqmyAFmpsgAiAAAAAAAA
+        AACpsgAAqLEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACpsgAAAAAAAAAAAACosQANqbIAXKmyALiosQD/qLEA/6my
+        AP+osQD+qLEA/qmyAP+psgD/qbIA/6myAP+psgD/qbIA/6myAP+psgD/qLEA/qixAP6psgD/qLEA/6my
+        AP+osQC/qbIAZKixABEAAAAAAAAAAKmyAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKmyAAAAAAAAAAAAAKixACuosQCjqbIA9aix
+        AP+psgD/qLEA/qmyAP+psgD/qbIA/6myAP+psgD/qbIA/6myAP+psgD/qbIA/6myAP+psgD/qbIA/6my
+        AP+psgD/qbIA/qmyAP+psgD/qbIA+aixAKupsgA0AAAAAAAAAACpsgAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAqbIARqix
+        ANWosQD/qbIA/6ixAP+osQD+qbIA/6myAP+psgD/qbIA/6myAP+psgD/qbIA/6myAP+psgD/qbIA/6my
+        AP+psgD/qbIA/6myAP+psgD/qbIA/6ixAP6osQD+qbIA/6myAP+osQDcqbIAUwAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAqbIAAAAA
+        AACosQBVqLEA76myAP+psgD/qLEA/qmyAP+psgD/qbIA/6myAP+psgD/qbIA/6myAP+psgD/qbIA/6my
+        AP+psgD/qbIA/6myAP+psgD/qbIA/6myAP+psgD/qbIA/6myAP+psgD/qLEA/qmyAP+psgD/qLEA86my
+        AGUAAAAAqbIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AACpsgAAAAAAAKmyAE6psgD8qbIA/6myAP+osQD+qbIA/6myAP+psgD/qbIA/6myAP+psgD/qbIA/6my
+        AP+psgD/qbIA/6myAP+psgD/qbIA/6myAP+psgD/qbIA/6myAP+psgD/qbIA/6myAP+psgD/qbIA/6ix
+        AP6psgD+qLEA/6myAP6psgBhAAAAAKixAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAKixAAAAAAAAqbIANKixAP2osQD/qLEA/6ixAP6psgD/qbIA/6myAP+psgD/qbIA/6my
+        AP+psgD/qbIA/6myAP+psgD/qbIA/6myAP+psgD/qbIA/6myAP+psgD/qbIA/6myAP+psgD/qbIA/6my
+        AP+psgD/qbIA/6myAP+psgD+qLEA/qmyAP+osQD/qLEARwAAAACpsgAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAqLEAAAAAAACosQASqbIA6KmyAP+psgD+qbIA/6myAP+psgD/qbIA/6my
+        AP+psgD/qbIA/6myAP+psgD/qbIA/6myAP+psgD/qbIA/6myAP+psgD/qbIA/6myAP+psgD/qbIA/6my
+        AP+psgD/qbIA/6myAP+psgD/qbIA/6myAP+psgD/qbIA/6myAP6psgD/qbIA8qixAB8AAAAAqLEAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACosQAAAAAAAAAAAACpsgCvqbIA/qmyAP6psgD/qLEA/6ix
+        AP+osQD/qLEA/6ixAP+osQD/qLEA/6ixAP+osQD/qLEA/6ixAP+osQD/qbIA/6myAP+psgD/qbIA/6ix
+        AP+osQD/qLEA/6ixAP+osQD/qLEA/6ixAP+osQD/qLEA/6ixAP+osQD/qLEA/6myAP+psgD+qbIA/qix
+        AMGosgAAAAAAAKixAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACosQAAAAAAAKixAFuosQD1qLEA/6my
+        AP+osQD/q7QI/7a9J/+3vyv/t78r/7i/Lf+stAn/rbYN/7jALv+3viv/t78r/7i/LP+stAn/qLEA/6my
+        AP+psgD/qLEA/6u0B/+3vin/t78r/7e/K/+4vy7/r7cS/6u0Bv+4vy3/t78r/7e/K/+2vin/rLQJ/6ix
+        AP+psgD/qbIA/6ixAPepsgBuAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKmyAAAAAAAAqbIADqmy
+        AMSosQD/qbIA/6myAP+osQD/t78q/+zuxv/09N3/8/Ta//b35f+5wC//tbwk//Lz2P/z9Nz/8/Tb//X1
+        4v/GzFj/qbIC/6ixAP+osQD/qbIA/8PIS//z9N3/8/Tb//P02//09d7/ucEy/7S8Iv/39+b/8/Ta//T0
+        3f/v8M//uMAv/6ixAP+psgD/qbIA/qmyAP+psgDPqLEAGQAAAACpsgAAAAAAAAAAAAAAAAAAAAAAAKix
+        AAAAAAAAqLEAY6myAPKosQD/qLEA/qmyAP+osQD/usEz//j57P////////////////+9xDr/qbIB/97i
+        nf/////////////////w8tX/sLkX/6ixAP+osQD/rrcQ/+vtxP/////////////////m6LT/qrMD/7e+
+        Kf/////////////////8/Pb/u8M4/6exAP+psgD/qLEA/qixAP+osQD3qLEAcgAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAACpsgALqLEAqqmyAP+psgD/qbIA/6myAP+osQD/ucEy//f45///////////////
+        //+9wzj/qLEA/7e+Kv/5+e3/////////////////ztRx/6myAP+psgD/yc5e//////////////////39
+        +f+6wjX/qLEA/7e+Kf/////////////////6+/L/u8I3/6ixAP+psgD/qbIA/6ixAP6osQD/qbIAtqmy
+        ABQAAAAAAAAAAAAAAAAAAAAAqLEAAAAAAACosQA7qLEA3amyAP+osQD+qbIA/6myAP+osQD/ucEy//f4
+        5/////////////////+9wzj/qLEA/6qzBf/T13z///////7+/v//////+frw/7C4FP+ttQr/9fbi////
+        ///+/v7//////9ndkP+rtAj/qLEA/7e+Kf/////////////////6+/L/u8I3/6ixAP+psgD/qbIA/6ix
+        AP6psgD/qLEA6KmyAEUAAAAAqbIAAAAAAAAAAAAAAAAAAAAAAACpsgBlqbIA/6myAP+psgD/qbIA/6my
+        AP+osQD/ucEy//f45/////////////////+9wzj/qLEA/6ixAP+3vyv/8fLW///////+/v7//////9rd
+        kP/S1nj/////////////////9vfk/7vCNf+osQD/qLEA/7e+Kf/////////////////6+/L/u8I3/6ix
+        AP+psgD/qbIA/6myAP+psgD/qbIA/6myAHMAAAAAAAAAAAAAAAAAAAAAAAAAAKmyAAqosQCTqLEA/6ix
+        AP+psgD/qbIA/6myAP+osQD/ucEy//f45/////////////////+9wzj/qLEA/6ixAP+osQD/0NV1////
+        //////////////z9+f/7+/P/////////////////1tqE/6qzA/+osQD/qLEA/7e+Kf//////////////
+        ///6+/L/u8I3/6ixAP+psgD/qbIA/6myAP+osQD+qbIA/6ixAKKosQARAAAAAAAAAAAAAAAAAAAAAKmy
+        AByosQC5qbIA/6myAP+psgD/qbIA/6myAP+osQD/ucEy//f45/////////////////+9wzj/qLEA/6my
+        AP+nsAD/tr0n/+zuyP/////////////+/////////v7+///////w8tX/usEz/6ewAP+psgD/qLEA/7e+
+        Kf/////////////////6+/L/u8I3/6ixAP+psgD/qbIA/6myAP+psgD/qbIA/6ixAMqosQAkAAAAAAAA
+        AAAAAAAAAAAAAKixACqosQDYqbIA/6myAP+psgD/qbIA/6myAP+osQD/ucEy//f45///////////////
+        //+9wzj/qLEA/6myAP+psQD/pa4A/9DVdP/9/fn///////7+/v/+/v7///////7+/v/V2oX/prAA/6ix
+        AP+psgD/qLEA/7e+Kf/////////////////6+/L/u8I3/6ixAP+psgD/qbIA/6myAP+psgD/qbIA/6my
+        AOipsgAyAAAAAAAAAAAAAAAAAAAAAKixADSosQDtqLEA/6myAP+psgD/qbIA/6myAP+osQD/ucEy//f4
+        5/////////////////+9wzj/qLEA/6myAP+psgD/p7AA/7C5Fv/r7cb//////////////////////+7w
+        zv+1vSX/p7AA/6myAP+psgD/qLEA/7e+Kf/////////////////6+/L/u8I3/6ixAP+psgD/qbIA/6my
+        AP+psgD/qLEA/6ixAPypsgA7AAAAAAAAAAAAAAAAAAAAAKmyADqosQD6qbIA/6myAP+psgD/qbIA/6my
+        AP+osQD/ucEy//f45/////////////////+9wzj/qLEA/6myAP+psgD/qbIA/6StAP/L0Gb/+/z2////
+        /////////v79/93gm/+irAD/qbIA/6myAP+psgD/qLEA/7e+Kf/////////////////6+/L/u8I3/6ix
+        AP+psgD/qbIA/6myAP+psgD/qbIA/6ixAP+psgBCAAAAAAAAAAAAAAAAAAAAAKixADyosQD9qbIA/6my
+        AP+psgD/qbIA/6myAP+osQD/ucEy//f45/////////////////+9wzj/qLEA/6myAP+psgD/qLEA/6ew
+        AP+psgH/6+3F//7+/v///////////+jqvP+utxD/p7AA/6myAP+psgD/qLEA/7e+Kf//////////////
+        ///6+/L/u8I3/6ixAP+psgD/qbIA/6myAP+psgD/qbIA/qixAP+psgBFAAAAAAAAAAAAAAAAAAAAAKmy
+        ADqosQD6qLEA/6myAP+psgD/qbIA/6myAP+osQD/ucEy//f45/////////////////+9wzj/qLEA/6my
+        AP+psgD/qLEA/663Ef+osQD/wMZF//7+/P/+/v7///////v89v/O023/pq8A/6ixAP+psgD/qLEA/7e+
+        Kf/////////////////6+/L/u8I3/6ixAP+psgD/qbIA/6myAP+psgD/qbIA/6ixAP+psgBDAAAAAAAA
+        AAAAAAAAAAAAAKixADWosQDvqLEA/6myAP+psgD/qbIA/6myAP+osQD/ucEy//f45///////////////
+        //+9wzj/qLEA/6myAP+nsQD/srob/9vflv+4wC7/pq8A/+Tnsf///////v7+///////r7cX/tLwh/6ew
+        AP+psgD/qLEA/7e+Kf/////////////////6+/L/u8I3/6ixAP+psgD/qbIA/6myAP+psgD/qLEA/6ix
+        AP2osQA8AAAAAAAAAAAAAAAAAAAAAKmyACupsgDZqLEA/6myAP+psgD/qbIA/6myAP+osQD/ucEy//f4
+        5/////////////////+9wzj/qLEA/6ixAP+nsAD/ys9h///////X24n/qrME/7W8Iv//////////////
+        ////////z9Nw/6ixAP+osQD/qLEA/7e+Kf/////////////////6+/L/u8I3/6ixAP+psgD/qbIA/6my
+        AP+psgD/qLEA/6myAOqpsgAzAAAAAAAAAAAAAAAAAAAAAKixAB2osQC8qLEA/6myAP+psgD/qbIA/6my
+        AP+osQD/ucEy//f45/////////////////+9wzj/qLEA/6ixAP+zux//6uzD///////9/Pj/tr0m/6ix
+        AP/Y3Iz///////7+/v//////8PLU/7W9Jf+osQD/qLEA/7e+Kf/////////////////6+/L/u8I3/6ix
+        AP+psgD/qbIA/6myAP+psgD/qLEA/6ixAMuosQAkAAAAAAAAAAAAAAAAAAAAAKixAAuosQCVqLEA/6ix
+        AP6psgD/qbIA/6myAP+osQD/ucEy//f45/////////////////+8wzj/qLEA/6myAv/L0GP/////////
+        ////////3+Ki/6qzBP+vtxH/+vvy/////////////////9HVdf+qswX/qLEA/7a+KP//////////////
+        ///6+/L/u8I3/6ixAP+psgD/qbIA/6myAP+osQD+qLEA/6ixAKWpsgASAAAAAAAAAAAAAAAAAAAAAAAA
+        AACosQBpqLEA/6ixAP+psgD/qbIA/6myAP+osQD/ucEy//f45//////////////////HzVr/t74p/77F
+        Pv/z89r/////////////////2d2O/6qzBP+psgL/z9Nu//////////////////j56v+/xkH/t74p/8PK
+        Tf/////////////////6+/L/u8I3/6ixAP+psgD/qbIA/6myAP+psgD/qLEA/6ixAHYAAAAAAAAAAAAA
+        AAAAAAAAqLEAAAAAAACpsgA+qLEA4KixAP+psgD+qbIA/6myAP+osQD/usEy//f46P////////////7+
+        /v///////////////////////v7+///////3+en/srsc/6ixAP+osQD/sLcU//Hz1////////v7+////
+        ///////////////////+/v7////////////6+/L/u8I3/6exAP+psgD/qbIA/6myAP6psgD/qLEA7Kix
+        AEoAAAAAqbIAAAAAAAAAAAAAAAAAAAAAAACosQAOqbIAramyAP+osQD/qbIA/6myAP+osQD/ucAx//b3
+        5v///////v7+///////////////////////+/v7////////////P1HH/qrME/6ixAP+osQD/qbIC/8jO
+        Xf////////////7+/v///////////////////////v7+///////6+/H/u8I2/6ixAP+psgD/qbIA/6my
+        AP+osQD/qbIAuqmyABkAAAAAAAAAAAAAAAAAAAAAAAAAAKmyAAAAAAAAqbIAaamyAPWosQD/qbIA/qmy
+        AP+osQD/sroc/+jqvP///////////////////////////////////////////+3vyv+zux7/qLEA/6my
+        AP+psgD/qLEA/7G5GP/n6rr////////////////////////////////////////////t78v/tLwj/6ix
+        AP+psgD/qbIA/qmyAP+osQD6qLEAeAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKmyAAAAAAAAqbIAFamy
+        AMiosQD/qLEA/6myAP+osQD/qbIA/77FP//f46H/5Oev/+Pnrv/j567/4+eu/+Pnrv/k56//3+Oi/77F
+        QP+psgD/qLEA/6myAP+psgD/qLEA/6ixAP+8wzj/3uKe/+Tnr//j567/4+eu/+Pnrv/j567/5Oev/+Hk
+        pf/Bx0j/qrIC/6ixAP+psgD/qbIA/qmyAP+psgDTqLEAIQAAAACosQAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AACosQAAAAAAAKixAGSosQD3qLEA/6myAP+psgD/qLEA/6ewAP+stQr/sLkW/7C5Fv+wuRb/sLkW/7C5
+        Fv+wuRb/rLUK/6ewAP+osQD/qbIA/6myAP+psgD/qbIA/6ixAP+nsAD/rLQJ/7C5Fv+wuRb/sLkW/7C5
+        Fv+wuRb/sLkW/621DP+nsAD/qLEA/6myAP+psgD/qLEA/6ixAPmpsgB3AAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAACpsgAAAAAAAAAAAACosQC2qLEA/6myAP6psgD/qbIA/6ixAP+osQD/qLEA/6ix
+        AP+osQD/qLEA/6ixAP+osQD/qLEA/6ixAP+psgD/qbIA/6myAP+psgD/qbIA/6myAP+osQD/qLEA/6ix
+        AP+osQD/qLEA/6ixAP+osQD/qLEA/6ixAP+osQD/qbIA/6myAP+osQD+qLEA/6myAMaosQAGAAAAAKix
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAqbIAAAAAAACpsgAbqLEA7aixAP+osQD+qbIA/6my
+        AP+psgD/qbIA/6myAP+psgD/qbIA/6myAP+psgD/qbIA/6myAP+psgD/qbIA/6myAP+psgD/qbIA/6my
+        AP+psgD/qbIA/6myAP+psgD/qbIA/6myAP+psgD/qbIA/6myAP+psgD/qbIA/6ixAP6psgD/qLEA9aix
+        ACoAAAAAqLEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAqLEAPKix
+        AP+osQD/qLEA/qmyAP+psgD/qbIA/6myAP+psgD/qbIA/6myAP+psgD/qbIA/6myAP+psgD/qbIA/6my
+        AP+psgD/qbIA/6myAP+psgD/qbIA/6myAP+psgD/qbIA/6myAP+psgD/qbIA/6myAP+psgD/qLEA/qix
+        AP6osQD/qLEATgAAAAAAAAAAqLEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AACosQAAAAAAAKmyAFWosQD/qbIA/6ixAP+psgD+qbIA/6myAP+psgD/qbIA/6myAP+psgD/qbIA/6my
+        AP+psgD/qbIA/6myAP+psgD/qbIA/6myAP+psgD/qbIA/6myAP+psgD/qbIA/6myAP+psgD/qbIA/6my
+        AP6osQD/qbIA/6ixAP+psgBqAAAAAKixAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAqLEAAAAAAACpsgBbqLEA+qixAP+psgD/qLEA/qmyAP+psgD/qbIA/6my
+        AP+psgD/qbIA/6myAP+psgD/qbIA/6myAP+psgD/qbIA/6myAP+psgD/qbIA/6myAP+psgD/qbIA/6my
+        AP+psgD/qLEA/qixAP+osQD/qbIA/qmyAG4AAAAAqbIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAqbIAT6ixAOKosQD/qLEA/6ix
+        AP+psgD+qbIA/6myAP+psgD/qbIA/6myAP+psgD/qbIA/6myAP+psgD/qbIA/6myAP+psgD/qbIA/6my
+        AP+psgD/qbIA/6myAP6osQD/qLEA/6ixAP+osQDpqbIAXAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKixAAAAAAAAAAAAAKix
+        ADGosQC0qLEA96ixAP+osQD/qbIA/qmyAP+psgD/qbIA/6myAP+psgD/qbIA/6myAP+psgD/qbIA/6my
+        AP+psgD/qbIA/6myAP+psgD/qbIA/qmyAP+osQD/qLEA+amyALypsgA8AAAAAAAAAACosQAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AACpsgAAAAAAAAAAAACosQAOqbIAcKixAMWosQD/qbIA/6myAP+osQD+qbIA/qmyAP+psgD/qbIA/6my
+        AP+psgD/qbIA/6myAP+psgD/qbIA/qmyAP6osQD/qbIA/6myAP+osQDKqLEAeaixABMAAAAAAAAAAKix
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAqLEAAKixAAAAAAAAAAAAAKmyACapsgBrqbIAsKixAO2osQD/qLEA/6ix
+        AP+osQD/qLEA/6ixAP+osQD/qLEA/6ixAP+osQD/qLEA/6ixAP+osQDwqbIAtqixAHGosQArAAAAAAAA
+        AACosQAAqbIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACpsgAAAAAAAAAAAAAAAAAAqbIAGamy
+        AECosQBpqLEAnamyAMeosQDlqLEA+qixAP+psgD/qbIA/KmyAOipsgDKqLEAoaixAG6psgBCqbIAHQAA
+        AAAAAAAAAAAAAKixAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKmy
+        AAAAAAAAAAAAAAAAAACosQAAqLEAEamyAB6psgAoqbIAL6ixADKpsgAyqLEAL6ixACmpsgAfqLEAEqmy
+        AAEAAAAAAAAAAAAAAACosQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAqLEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAqLEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD///////8AAP///////wAA///gB///
+        AAD//wAA//8AAP/8AAA//wAA//AAAA//AAD/4AAAB/8AAP/AAAAD/wAA/4AAAAH/AAD/AAAAAP8AAP4A
+        AAAAfwAA/AAAAAA/AAD8AAAAAD8AAPgAAAAAHwAA+AAAAAAfAADwAAAAAA8AAPAAAAAADwAA8AAAAAAP
+        AADgAAAAAAcAAOAAAAAABwAA4AAAAAAHAADgAAAAAAcAAOAAAAAABwAA4AAAAAAHAADgAAAAAAcAAOAA
+        AAAABwAA4AAAAAAHAADgAAAAAAcAAOAAAAAABwAA8AAAAAAPAADwAAAAAA8AAPAAAAAADwAA+AAAAAAf
+        AAD4AAAAAB8AAPwAAAAAPwAA/AAAAAA/AAD+AAAAAH8AAP8AAAAA/wAA/4AAAAH/AAD/wAAAA/8AAP/g
+        AAAH/wAA//AAAA//AAD//AAAP/8AAP//AAD//wAA///gB///AAD///////8AAP///////wAA////////
+        AAA=
+</value>
+  </data>
+</root>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HspGuiSourceV301/HSPGui/FormConnection.Designer.cs	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,261 @@
+namespace HealthSensorPlatform
+{
+    partial class FormConnection
+    {
+        /// <summary>
+        /// Required designer variable.
+        /// </summary>
+        private System.ComponentModel.IContainer components = null;
+
+        /// <summary>
+        /// Clean up any resources being used.
+        /// </summary>
+        /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
+        protected override void Dispose(bool disposing)
+        {
+            if (disposing && (components != null))
+            {
+                components.Dispose();
+            }
+            base.Dispose(disposing);
+        }
+
+        #region Windows Form Designer generated code
+
+        /// <summary>
+        /// Required method for Designer support - do not modify
+        /// the contents of this method with the code editor.
+        /// </summary>
+        private void InitializeComponent()
+        {
+            System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(FormConnection));
+            this.btnConnect = new MaximStyle.MaximButton();
+            this.label1 = new System.Windows.Forms.Label();
+            this.maximGroupBox1 = new MaximStyle.MaximGroupBox();
+            this.cboPort = new MaximStyle.MaximComboBox();
+            this.tbFlowControl = new System.Windows.Forms.TextBox();
+            this.label4 = new System.Windows.Forms.Label();
+            this.tbStopBits = new System.Windows.Forms.TextBox();
+            this.label5 = new System.Windows.Forms.Label();
+            this.tbDataBits = new System.Windows.Forms.TextBox();
+            this.label6 = new System.Windows.Forms.Label();
+            this.tbParity = new System.Windows.Forms.TextBox();
+            this.label3 = new System.Windows.Forms.Label();
+            this.tbBaudRate = new System.Windows.Forms.TextBox();
+            this.label2 = new System.Windows.Forms.Label();
+            this.btnScan = new MaximStyle.MaximButton();
+            this.btnCancel = new MaximStyle.MaximButton();
+            this.maximGroupBox1.SuspendLayout();
+            this.SuspendLayout();
+            // 
+            // btnConnect
+            // 
+            this.btnConnect.Location = new System.Drawing.Point(141, 179);
+            this.btnConnect.Name = "btnConnect";
+            this.btnConnect.Size = new System.Drawing.Size(75, 23);
+            this.btnConnect.TabIndex = 0;
+            this.btnConnect.Text = "Connect";
+            this.btnConnect.UseVisualStyleBackColor = true;
+            this.btnConnect.Click += new System.EventHandler(this.btnConnect_Click);
+            // 
+            // label1
+            // 
+            this.label1.AutoSize = true;
+            this.label1.BackColor = System.Drawing.Color.White;
+            this.label1.Location = new System.Drawing.Point(31, 55);
+            this.label1.Name = "label1";
+            this.label1.Size = new System.Drawing.Size(56, 13);
+            this.label1.TabIndex = 2;
+            this.label1.Text = "COM Port:";
+            // 
+            // maximGroupBox1
+            // 
+            this.maximGroupBox1.BackgroundColor = System.Drawing.Color.White;
+            this.maximGroupBox1.Controls.Add(this.cboPort);
+            this.maximGroupBox1.Controls.Add(this.tbFlowControl);
+            this.maximGroupBox1.Controls.Add(this.label4);
+            this.maximGroupBox1.Controls.Add(this.tbStopBits);
+            this.maximGroupBox1.Controls.Add(this.label5);
+            this.maximGroupBox1.Controls.Add(this.tbDataBits);
+            this.maximGroupBox1.Controls.Add(this.label6);
+            this.maximGroupBox1.Controls.Add(this.tbParity);
+            this.maximGroupBox1.Controls.Add(this.label3);
+            this.maximGroupBox1.Controls.Add(this.tbBaudRate);
+            this.maximGroupBox1.Controls.Add(this.label2);
+            this.maximGroupBox1.Location = new System.Drawing.Point(12, 12);
+            this.maximGroupBox1.Name = "maximGroupBox1";
+            this.maximGroupBox1.Size = new System.Drawing.Size(336, 153);
+            this.maximGroupBox1.TabIndex = 3;
+            this.maximGroupBox1.TabStop = false;
+            this.maximGroupBox1.Text = "UART Configuration";
+            // 
+            // cboPort
+            // 
+            this.cboPort.BackColor = System.Drawing.Color.White;
+            this.cboPort.DropDownHeight = 200;
+            this.cboPort.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
+            this.cboPort.DropDownWidth = 70;
+            this.cboPort.Location = new System.Drawing.Point(81, 40);
+            this.cboPort.Name = "cboPort";
+            this.cboPort.Size = new System.Drawing.Size(70, 20);
+            this.cboPort.TabIndex = 14;
+            this.cboPort.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
+            this.cboPort.TextAlignDropDownList = System.Windows.Forms.HorizontalAlignment.Left;
+            // 
+            // tbFlowControl
+            // 
+            this.tbFlowControl.Location = new System.Drawing.Point(242, 108);
+            this.tbFlowControl.Name = "tbFlowControl";
+            this.tbFlowControl.ReadOnly = true;
+            this.tbFlowControl.Size = new System.Drawing.Size(70, 20);
+            this.tbFlowControl.TabIndex = 12;
+            this.tbFlowControl.Text = "0";
+            // 
+            // label4
+            // 
+            this.label4.AutoSize = true;
+            this.label4.BackColor = System.Drawing.Color.White;
+            this.label4.Location = new System.Drawing.Point(168, 111);
+            this.label4.Name = "label4";
+            this.label4.Size = new System.Drawing.Size(68, 13);
+            this.label4.TabIndex = 13;
+            this.label4.Text = "Flow Control:";
+            // 
+            // tbStopBits
+            // 
+            this.tbStopBits.Location = new System.Drawing.Point(242, 72);
+            this.tbStopBits.Name = "tbStopBits";
+            this.tbStopBits.ReadOnly = true;
+            this.tbStopBits.Size = new System.Drawing.Size(70, 20);
+            this.tbStopBits.TabIndex = 10;
+            this.tbStopBits.Text = "1";
+            // 
+            // label5
+            // 
+            this.label5.AutoSize = true;
+            this.label5.BackColor = System.Drawing.Color.White;
+            this.label5.Location = new System.Drawing.Point(168, 75);
+            this.label5.Name = "label5";
+            this.label5.Size = new System.Drawing.Size(52, 13);
+            this.label5.TabIndex = 11;
+            this.label5.Text = "Stop Bits:";
+            // 
+            // tbDataBits
+            // 
+            this.tbDataBits.Location = new System.Drawing.Point(242, 40);
+            this.tbDataBits.Name = "tbDataBits";
+            this.tbDataBits.ReadOnly = true;
+            this.tbDataBits.Size = new System.Drawing.Size(70, 20);
+            this.tbDataBits.TabIndex = 8;
+            this.tbDataBits.Text = "8";
+            // 
+            // label6
+            // 
+            this.label6.AutoSize = true;
+            this.label6.BackColor = System.Drawing.Color.White;
+            this.label6.Location = new System.Drawing.Point(168, 43);
+            this.label6.Name = "label6";
+            this.label6.Size = new System.Drawing.Size(53, 13);
+            this.label6.TabIndex = 9;
+            this.label6.Text = "Data Bits:";
+            // 
+            // tbParity
+            // 
+            this.tbParity.Location = new System.Drawing.Point(81, 108);
+            this.tbParity.Name = "tbParity";
+            this.tbParity.ReadOnly = true;
+            this.tbParity.Size = new System.Drawing.Size(70, 20);
+            this.tbParity.TabIndex = 6;
+            this.tbParity.Text = "0";
+            // 
+            // label3
+            // 
+            this.label3.AutoSize = true;
+            this.label3.BackColor = System.Drawing.Color.White;
+            this.label3.Location = new System.Drawing.Point(19, 111);
+            this.label3.Name = "label3";
+            this.label3.Size = new System.Drawing.Size(36, 13);
+            this.label3.TabIndex = 7;
+            this.label3.Text = "Parity:";
+            // 
+            // tbBaudRate
+            // 
+            this.tbBaudRate.Location = new System.Drawing.Point(81, 72);
+            this.tbBaudRate.Name = "tbBaudRate";
+            this.tbBaudRate.ReadOnly = true;
+            this.tbBaudRate.Size = new System.Drawing.Size(70, 20);
+            this.tbBaudRate.TabIndex = 4;
+            this.tbBaudRate.Text = "9600";
+            // 
+            // label2
+            // 
+            this.label2.AutoSize = true;
+            this.label2.BackColor = System.Drawing.Color.White;
+            this.label2.Location = new System.Drawing.Point(19, 75);
+            this.label2.Name = "label2";
+            this.label2.Size = new System.Drawing.Size(61, 13);
+            this.label2.TabIndex = 5;
+            this.label2.Text = "Baud Rate:";
+            // 
+            // btnScan
+            // 
+            this.btnScan.Location = new System.Drawing.Point(34, 179);
+            this.btnScan.Name = "btnScan";
+            this.btnScan.Size = new System.Drawing.Size(75, 23);
+            this.btnScan.TabIndex = 4;
+            this.btnScan.Text = "Scan Ports";
+            this.btnScan.UseVisualStyleBackColor = true;
+            this.btnScan.Click += new System.EventHandler(this.btnScan_Click);
+            // 
+            // btnCancel
+            // 
+            this.btnCancel.Location = new System.Drawing.Point(249, 179);
+            this.btnCancel.Name = "btnCancel";
+            this.btnCancel.Size = new System.Drawing.Size(75, 23);
+            this.btnCancel.TabIndex = 5;
+            this.btnCancel.Text = "Cancel";
+            this.btnCancel.UseVisualStyleBackColor = true;
+            this.btnCancel.Click += new System.EventHandler(this.btnCancel_Click);
+            // 
+            // FormConnection
+            // 
+            this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
+            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+            this.BackColor = System.Drawing.Color.White;
+            this.ClientSize = new System.Drawing.Size(366, 218);
+            this.Controls.Add(this.btnCancel);
+            this.Controls.Add(this.btnScan);
+            this.Controls.Add(this.label1);
+            this.Controls.Add(this.btnConnect);
+            this.Controls.Add(this.maximGroupBox1);
+            this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon")));
+            this.Name = "FormConnection";
+            this.Text = "Connection";
+            this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.FormConnection_FormClosing);
+            this.maximGroupBox1.ResumeLayout(false);
+            this.maximGroupBox1.PerformLayout();
+            this.ResumeLayout(false);
+            this.PerformLayout();
+
+        }
+
+        #endregion
+
+        private MaximStyle.MaximButton btnConnect;
+        private System.Windows.Forms.Label label1;
+        private MaximStyle.MaximGroupBox maximGroupBox1;
+        private System.Windows.Forms.TextBox tbBaudRate;
+        private System.Windows.Forms.Label label2;
+        private System.Windows.Forms.TextBox tbParity;
+        private System.Windows.Forms.Label label3;
+        private System.Windows.Forms.TextBox tbFlowControl;
+        private System.Windows.Forms.Label label4;
+        private System.Windows.Forms.TextBox tbStopBits;
+        private System.Windows.Forms.Label label5;
+        private System.Windows.Forms.TextBox tbDataBits;
+        private System.Windows.Forms.Label label6;
+        private MaximStyle.MaximButton btnScan;
+        private MaximStyle.MaximButton btnCancel;
+        private MaximStyle.MaximComboBox cboPort;
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HspGuiSourceV301/HSPGui/FormConnection.cs	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,182 @@
+/*******************************************************************************
+* Copyright (C) 2016 Maxim Integrated Products, Inc., All rights Reserved.
+* 
+* This software is protected by copyright laws of the United States and
+* of foreign countries. This material may also be protected by patent laws
+* and technology transfer regulations of the United States and of foreign
+* countries. This software is furnished under a license agreement and/or a
+* nondisclosure agreement and may only be used or reproduced in accordance
+* with the terms of those agreements. Dissemination of this information to
+* any party or parties not specified in the license agreement and/or
+* nondisclosure agreement is expressly prohibited.
+*
+* The above copyright notice and this permission notice shall be included
+* in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+* OTHER DEALINGS IN THE SOFTWARE.
+*
+* Except as contained in this notice, the name of Maxim Integrated
+* Products, Inc. shall not be used except as stated in the Maxim Integrated
+* Products, Inc. Branding Policy.
+*
+* The mere transfer of this software does not imply any licenses
+* of trade secrets, proprietary technology, copyrights, patents,
+* trademarks, maskwork rights, or any other form of intellectual
+* property whatsoever. Maxim Integrated Products, Inc. retains all
+* ownership rights.
+*******************************************************************************
+*/
+
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Data;
+using System.Drawing;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows.Forms;
+
+using System.IO.Ports;
+
+namespace HealthSensorPlatform
+{
+    public partial class FormConnection : Form
+    {
+        string port;
+        bool done = false;
+        //bool canceled = false;
+        //bool connect = false;
+
+        public bool Canceled { get; set; }
+       // public bool Connect { get; set; }
+
+        internal const Int32 WM_DEVICECHANGE = 0x219;
+        internal const Int32 DBT_DEVICEARRIVAL = 0x8000;
+        internal const Int32 DBT_DEVICEREMOVECOMPLETE = 0x8004;
+
+        public FormConnection()
+        {
+            InitializeComponent();
+            ScanPorts();
+
+            port = Properties.Settings.Default.ComPort;
+        }
+
+        private void btnConnect_Click(object sender, EventArgs e)
+        {
+            if (cboPort.SelectedItem != null)
+            {
+                port = cboPort.SelectedItem.ToString();
+
+                // Save default COM port for next application use
+                Properties.Settings.Default["ComPort"] = Port;
+                Properties.Settings.Default.Save();
+
+                done = true;
+                Close();
+            }
+            else
+            {
+                MessageBox.Show("Selected port is invalid.", "Connection");
+            }
+        }
+
+        /// <summary>
+        /// Reset the state of the connection Form.
+        /// </summary>
+        public void Reset()
+        {
+            Canceled = false;
+        }
+
+
+        /// <summary>
+        /// Returns default port saved in Properties.Settings.Default.ComPort
+        /// if port is not selected or user selected port from drop down menu
+        /// </summary>
+        /// <returns></returns>
+        public string Port
+        {
+            get { return port; }
+        }
+       
+
+        private void btnScan_Click(object sender, EventArgs e)
+        {
+            ScanPorts();
+
+        }
+
+        /// <summary>
+        /// Scan the port names
+        /// </summary>
+        public void ScanPorts()
+        {
+            string[] ports = SerialPort.GetPortNames();
+
+            cboPort.Items.Clear();
+            //cboPort.SelectedItem = null;
+            cboPort.SelectedIndex = -1;
+
+            foreach (string port in ports)
+            {
+                cboPort.Items.Add(port);
+
+                if(String.Compare(port,Properties.Settings.Default.ComPort) == 0)
+                {
+                    // Select the last used COM Port
+                    cboPort.SelectedItem = Properties.Settings.Default.ComPort;
+                }
+            }
+            
+        }
+
+        private void btnCancel_Click(object sender, EventArgs e)
+        {
+            Canceled = true;
+            done = true;
+            Close();
+        }
+
+        public bool HandleWMDeviceChangeMessage(Message m)
+        {
+            string[] ports;
+            bool removal = false;
+
+            if (m.Msg == WM_DEVICECHANGE)
+            {
+                if (m.WParam.ToInt32() == DBT_DEVICEREMOVECOMPLETE)
+                {
+                    ports = SerialPort.GetPortNames();
+
+                    foreach(string p in ports)
+                    {
+                        if (String.Compare(p, Port) == 0)
+                        {
+                            removal = true;
+                            break;
+                        }
+                    }
+                }
+
+            }
+
+            return removal;
+        }
+
+        private void FormConnection_FormClosing(object sender, FormClosingEventArgs e)
+        {
+            // User clicked "X" button to close form,
+            // action should be the same as if user clicked on "Canceled" button
+            if (done == false)
+                Canceled = true;
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HspGuiSourceV301/HSPGui/FormConnection.resx	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,546 @@
+<?xml version="1.0" encoding="utf-8"?>
+<root>
+  <!-- 
+    Microsoft ResX Schema 
+    
+    Version 2.0
+    
+    The primary goals of this format is to allow a simple XML format 
+    that is mostly human readable. The generation and parsing of the 
+    various data types are done through the TypeConverter classes 
+    associated with the data types.
+    
+    Example:
+    
+    ... ado.net/XML headers & schema ...
+    <resheader name="resmimetype">text/microsoft-resx</resheader>
+    <resheader name="version">2.0</resheader>
+    <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+    <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+    <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
+    <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+    <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+        <value>[base64 mime encoded serialized .NET Framework object]</value>
+    </data>
+    <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+        <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
+        <comment>This is a comment</comment>
+    </data>
+                
+    There are any number of "resheader" rows that contain simple 
+    name/value pairs.
+    
+    Each data row contains a name, and value. The row also contains a 
+    type or mimetype. Type corresponds to a .NET class that support 
+    text/value conversion through the TypeConverter architecture. 
+    Classes that don't support this are serialized and stored with the 
+    mimetype set.
+    
+    The mimetype is used for serialized objects, and tells the 
+    ResXResourceReader how to depersist the object. This is currently not 
+    extensible. For a given mimetype the value must be set accordingly:
+    
+    Note - application/x-microsoft.net.object.binary.base64 is the format 
+    that the ResXResourceWriter will generate, however the reader can 
+    read any of the formats listed below.
+    
+    mimetype: application/x-microsoft.net.object.binary.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
+            : and then encoded with base64 encoding.
+    
+    mimetype: application/x-microsoft.net.object.soap.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+            : and then encoded with base64 encoding.
+
+    mimetype: application/x-microsoft.net.object.bytearray.base64
+    value   : The object must be serialized into a byte array 
+            : using a System.ComponentModel.TypeConverter
+            : and then encoded with base64 encoding.
+    -->
+  <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+    <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
+    <xsd:element name="root" msdata:IsDataSet="true">
+      <xsd:complexType>
+        <xsd:choice maxOccurs="unbounded">
+          <xsd:element name="metadata">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" />
+              </xsd:sequence>
+              <xsd:attribute name="name" use="required" type="xsd:string" />
+              <xsd:attribute name="type" type="xsd:string" />
+              <xsd:attribute name="mimetype" type="xsd:string" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="assembly">
+            <xsd:complexType>
+              <xsd:attribute name="alias" type="xsd:string" />
+              <xsd:attribute name="name" type="xsd:string" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="data">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+                <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
+              <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+              <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="resheader">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" />
+            </xsd:complexType>
+          </xsd:element>
+        </xsd:choice>
+      </xsd:complexType>
+    </xsd:element>
+  </xsd:schema>
+  <resheader name="resmimetype">
+    <value>text/microsoft-resx</value>
+  </resheader>
+  <resheader name="version">
+    <value>2.0</value>
+  </resheader>
+  <resheader name="reader">
+    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <resheader name="writer">
+    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <assembly alias="System.Drawing" name="System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
+  <data name="$this.Icon" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+    <value>
+        AAABAAkAEBAQAAEABAAoAQAAlgAAACAgEAABAAQA6AIAAL4BAAAwMBAAAQAEAGgGAACmBAAAEBAAAAEA
+        CABoBQAADgsAACAgAAABAAgAqAgAAHYQAAAwMAAAAQAIAKgOAAAeGQAAEBAAAAEAIABoBAAAxicAACAg
+        AAABACAAqBAAAC4sAAAwMAAAAQAgAKglAADWPAAAKAAAABAAAAAgAAAAAQAEAAAAAADAAAAAAAAAAAAA
+        AAAQAAAAAAAAAAAAAP8AAID/AIAA/wCAgP+AAAD/gACA/4CAAP+AgID/wMDA/wAA//8A/wD/AP////8A
+        AP//AP////8A//////8AAAAAAAAAAAAAAGbmAAAAAABubmbmAAAABmbm5ubgAADujoboeOYAAGj++I/v
+        hgAOaPaP+G+OYAbo9uj27+bgDm7+aP5vhuAOaPb+j2+GYABo//jv/44AAG6I5m6I5gAABuZuZuZgAAAA
+        bmbmbgAAAAAAbm4AAAAAAAAAAAAAAP//AAD8PwAA8A8AAOAHAADAAwAAwAMAAIABAACAAQAAgAEAAIAB
+        AADAAwAAwAMAAOAHAADwDwAA/D8AAP//AAAoAAAAIAAAAEAAAAABAAQAAAAAAIACAAAAAAAAAAAAABAA
+        AAAAAAAAAAAA/wAAgP8AgAD/AICA/4AAAP+AAID/gIAA/4CAgP/AwMD/AAD//wD/AP8A/////wAA//8A
+        /////wD//////wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADmYAAAAAAAAAAAAAAABm5uZuZuYAAAAAAAAA
+        AADm5m5uZuZuZgAAAAAAAAAOZmbmZubm5ubgAAAAAAAAbm5ubm5mZmbmbgAAAAAABubmbmbmbm5uZuZg
+        AAAAAG5mbmZuZuZm5uZubgAAAA5m6Ofo6G5ujoaOhuZgAAAGbo//b/+GaP/+j/huYAAABuZ/+Of//m//
+        ho/+5mYAAGZu7/huj/jv+G6P+G5uAADm5o/45u////5uj/5m5gAAbmbv+G5o//+OZv/3bm4AAObmf/jm
+        bv//5m6P/uZmAAZubo/4bmaP+G5m//hubmAG5mbv+Obmb//mbo/+bmZgAG5uf/jm6Of/jmb/+GbmAABu
+        Zu/4Zo+Oj/jmj/5ubgAAZuaP+Ob/9o//bo/4ZuYAAG5m7/+I//bo/4j//m5mAAAGbo/////mbv////hm
+        5gAABuZv///4ZuaP///+bmAAAABubn5+5uZubn5+ZubgAAAAZuZuZmbm5m5m5m5mAAAAAA5m5ubmZm5m
+        bmbm4AAAAAAA5uZuZubm5uZubgAAAAAAAAZuZuZuZm5m5mAAAAAAAAAABuZuZubmbm4AAAAAAAAAAAAO
+        bm5m5uAAAAAAAAAAAAAAAAAOYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA///////+P///wAP//wAA//4A
+        AH/8AAA/+AAAH/AAAA/gAAAH4AAAB+AAAAPAAAADwAAAA8AAAAPAAAADgAAAAYAAAAHAAAADwAAAA8AA
+        AAPAAAAD4AAAA+AAAAfwAAAH8AAAD/gAAB/8AAA//gAAf/+AAP//4Af///5///////8oAAAAMAAAAGAA
+        AAABAAQAAAAAAAAGAAAAAAAAAAAAABAAAAAAAAAAAAAA/wAAgP8AgAD/AICA/4AAAP+AAID/gIAA/4CA
+        gP/AwMD/AAD//wD/AP8A/////wAA//8A/////wD//////wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOZuZubmbgAAAAAAAAAAAAAAAAAAAAAOZubmbmbm
+        5m5gAAAAAAAAAAAAAAAAAA5m5uZm5uZuZubm4AAAAAAAAAAAAAAABuZuZm5uZm5m5q5mZuAAAAAAAAAA
+        AAAAbqbm5ubq5uZuZuZubmYAAAAAAAAAAAAG5m5mZuZmbm5m5m5m5ubgAAAAAAAAAABuZuZubmbm5mZu
+        ZuZuZm5mAAAAAAAAAA5m5m5m5uZubm5m5m5m5uZuYAAAAAAAAOZuZubmZubmZuZuZubmbmbm5gAAAAAA
+        Dm5m5mbm5mZubmbmbmZuZm5mbmAAAAAABuZufo5ufn6G5m5ufn7n6Ofm5uAAAAAA5m5o//+G///+ZuaP
+        //ho//9+Zm4AAAAAZuZu//+Ob//45uaP//ju///mbm4AAAAG5m5m///m6P//hm7//4Zo//9+ZubgAAAO
+        ZuZu//+Gbv//jm///+5o///mbmbgAAAObmbn//+G5o//+O//+Gbo//9+ZuZgAADmZuZu//+OZu//////
+        /m5u///m5m5uAABubmbn///m5mj/////huZo//92bmrmAADmpuZu//+Gbm6P////bmbo///m5uZuAABu
+        bmbn//+ObmaP///+Zm5o//9+Zm5mAABuZuZu//+GZm5v///2bm5u///m5uZuAABm5m5m///m5uZu//+O
+        ZuZo//92bmbmAABuZuZu//+OZm5mj//4bmbo///m5m5uAABubmbn//+G5ubm7//45m5o//9+ZuZuAADm
+        ZuZu//+OZmj+aP//huZu///mbmbmAABubmbn///m5u/4bv///m5o//9+ZuZuAADmZuZu//+G5o//5o//
+        +Gbo///m5m5mAABubmbm//+Gbv//jm///+Zo//92bm5uAAAG5m5n//+I6P//hm7//4jo///m5mZgAAAG
+        bmbu///////4Zub////////mbm5gAAAO5m5m///////+bmbv//////+G5uZgAAAAZubm//////+G5m5o
+        //////9uZm4AAAAA5uZuf4////huZuZuj///j/5m5uYAAAAADmbm5uZuZuZubmbmbmbm5ubmbmAAAAAA
+        Dm5mbmbmbmbmZuZuaubmZm5m5mAAAAAAAGbm5m5m5m5ubmbmbmZubmbmbgAAAAAAAA5uZuZuZuZupuZu
+        Zubm5m5m4AAAAAAAAADmbm5m5m5mbmbmbmbmbmbmAAAAAAAAAAAObmZubmbm5uZuZuZm5m5gAAAAAAAA
+        AAAAZubmbm5mbmbmbm5uZuYAAAAAAAAAAAAADm5m5mbm5m5ubmbmbmAAAAAAAAAAAAAAAAbm5uZuZuZu
+        ZuZuYAAAAAAAAAAAAAAAAAAGbmbmbm5mbm5gAAAAAAAAAAAAAAAAAAAAAObm5m5uZgAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP///////wAA////////
+        AAD//8AD//8AAP/+AAB//wAA//gAAB//AAD/4AAAB/8AAP/AAAAD/wAA/4AAAAH/AAD/AAAAAP8AAP4A
+        AAAAfwAA/AAAAAA/AAD4AAAAAB8AAPgAAAAAHwAA8AAAAAAPAADwAAAAAA8AAOAAAAAABwAA4AAAAAAH
+        AADgAAAAAAcAAMAAAAAAAwAAwAAAAAADAADAAAAAAAMAAMAAAAAAAwAAwAAAAAADAADAAAAAAAMAAMAA
+        AAAAAwAAwAAAAAADAADAAAAAAAMAAMAAAAAAAwAAwAAAAAADAADAAAAAAAMAAOAAAAAABwAA4AAAAAAH
+        AADgAAAAAAcAAPAAAAAADwAA8AAAAAAPAAD4AAAAAB8AAPgAAAAAHwAA/AAAAAA/AAD+AAAAAH8AAP8A
+        AAAA/wAA/4AAAAH/AAD/wAAAA/8AAP/gAAAH/wAA//gAAB//AAD//gAAf/8AAP//wAP//wAA////////
+        AAD///////8AACgAAAAQAAAAIAAAAAEACAAAAAAAQAEAAAAAAAAAAAAAAAEAAAAAAAAAAAD/gAAA/wCA
+        AP+AgAD/AACA/4AAgP8AgID/wMDA/8DcwP+myvD/8PDw////mf+Z1Jn/mdT////M////mZn/IiIw/wAA
+        Ef8AACL/AABE/wAAVf8AAHf/AACI/wAAqv8AAN3/AADu/wARAP8AIgD/AEQA/wBVAP8AdwD/AIgA/wCq
+        AP8A3QD/AO4A/xEAAP8iAAD/RAAA/1UAAP93AAD/kAAA/6oAAP/dAAD/7gAA/wAAM/8AAGb/AACZ/wAA
+        zP8AMwD/ADMz/wAzZv8AM6H/ADPM/wAz//8AZgD/AGYz/wBmZv8AZpn/AGbM/wBm//8AmQD/AJkz/wCZ
+        Zv8AmZn/AJnM/wCZ//8AzAD/AMwz/wDMZv8AzJn/AMzM/wDM//8A/zP/AP9m/wD/mf8A/8z/MwAA/zMA
+        M/8zAGb/MwCZ/zMAzP8zAP//MzMA/zMzO/8zM2b/MzOZ/zMzzP8zM///M2YA/zNuM/8zZmb/M2aZ/zNm
+        zP8zZv//M5kA/zOZM/8zmWb/M5mZ/zOZzP8zmf//M8wA/zPMM/8zzGb/M8yZ/zPMzP8zzP//M/8A/zP/
+        M/8z/2b/M/+Z/zP/zP8z////ZgAA/2YAM/9mAGb/ZgCZ/2YAzP9mAP//ZjMA/2YzM/9mM2b/ZjOZ/2Yz
+        zP9mM///ZmYA/2ZmM/9mZmb/ZmaZ/2ZmzP9mZv//ZpkA/2aZM/9mmWb/ZpmZ/2aZzP9mmf//ZswA/2bM
+        M/9mzGb/ZsyZ/2bMzP9mzP//Zv8A/2b/M/9m/2b/Zv+Z/2b/zP9m////mQAA/5kAM/+ZAGb/mQCZ/5kA
+        zP+ZAP//mTMA/5kzM/+ZM2b/mTOZ/5kzzP+ZM///oWYA/5lmM/+ZZmb/mWaZ/5lmzP+ZZv//mZkA/5mZ
+        M/+ZmWb/mZmZ/5mZzP+Zmf//mcwA/5nMM/+ZzGb/mcyZ/5nMzP+ZzP//mf8A/5n/M/+Z/2b/mf+Z/5n/
+        zP+Z////zAAA/8wAM//MAGb/zACZ/8wAzP/UCP//zDMA/8wzM//MM2b/zDOZ/8wzzP/MM///zGYA/8xm
+        M//MZmb/zGaZ/8xmzP/MZv//zJkA/8yZM//MmWb/zJmZ/8yZzP/Mmf//zMwA/8zMM//MzGb/zMyZ/8zM
+        zP/MzP//zP8A/8z/M//M/2b/zP+Z/8z/zP/M/////wAz//8AZv//AJn//wDM//8zAP//MzP//zNm//8z
+        mf//M8z//zP///9mAP//ZjP//2Zm//9mmf//Zsz//2b///+ZAP/d3d3//5nM///MZv+IAAD/zAD//wAz
+        mf8zZjP/mWYA/zMzM///+/D/oKCk/4CAgP//AAD/AP8A////AP8AAP///wD//wD/////////AAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAKzKrMoAAAAAAAAAAAAA0KzKrMqsyqwAAAAAAAAA0KaspqymrKbQpgAAAAAA
+        rNHT0tPQrdPR09KsAAAAAKwLCtH/0wv/0f/ZygAAAMqs0/+s0v//0qb/06bQAACspgv/yqwK/6zQCgus
+        pgAAyqzS/6zR0grSpgrZptAAAKasCwrQ7dLa9tAKC6ymAAAAptP/Cv/R0f///9OmAAAAAKzR0tPSrMrS
+        0tPRrAAAAAAAyqzKrMqspqzKrAAAAAAAAACspqym0KaspgAAAAAAAAAAAACm0KymAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAP//AAD8PwAA8A8AAOAHAADAAwAAwAMAAIABAACAAQAAgAEAAIABAADAAwAAwAMAAOAH
+        AADwDwAA/D8AAP//AAAoAAAAIAAAAEAAAAABAAgAAAAAAIAEAAAAAAAAAAAAAAABAAAAAAAAAAAA/4AA
+        AP8AgAD/gIAA/wAAgP+AAID/AICA/8DAwP/A3MD/psrw//Dw8P///5n/mdSZ/5nU////zP///5mZ/yIi
+        MP8AABH/AAAi/wAARP8AAFX/AAB3/wAAiP8AAKr/AADd/wAA7v8AEQD/ACIA/wBEAP8AVQD/AHcA/wCI
+        AP8AqgD/AN0A/wDuAP8RAAD/IgAA/0QAAP9VAAD/dwAA/5AAAP+qAAD/3QAA/+4AAP8AADP/AABm/wAA
+        mf8AAMz/ADMA/wAzM/8AM2b/ADOh/wAzzP8AM///AGYA/wBmM/8AZmb/AGaZ/wBmzP8AZv//AJkA/wCZ
+        M/8AmWb/AJmZ/wCZzP8Amf//AMwA/wDMM/8AzGb/AMyZ/wDMzP8AzP//AP8z/wD/Zv8A/5n/AP/M/zMA
+        AP8zADP/MwBm/zMAmf8zAMz/MwD//zMzAP8zMzv/MzNm/zMzmf8zM8z/MzP//zNmAP8zbjP/M2Zm/zNm
+        mf8zZsz/M2b//zOZAP8zmTP/M5lm/zOZmf8zmcz/M5n//zPMAP8zzDP/M8xm/zPMmf8zzMz/M8z//zP/
+        AP8z/zP/M/9m/zP/mf8z/8z/M////2YAAP9mADP/ZgBm/2YAmf9mAMz/ZgD//2YzAP9mMzP/ZjNm/2Yz
+        mf9mM8z/ZjP//2ZmAP9mZjP/ZmZm/2Zmmf9mZsz/Zmb//2aZAP9mmTP/Zplm/2aZmf9mmcz/Zpn//2bM
+        AP9mzDP/Zsxm/2bMmf9mzMz/Zsz//2b/AP9m/zP/Zv9m/2b/mf9m/8z/Zv///5kAAP+ZADP/mQBm/5kA
+        mf+ZAMz/mQD//5kzAP+ZMzP/mTNm/5kzmf+ZM8z/mTP//6FmAP+ZZjP/mWZm/5lmmf+ZZsz/mWb//5mZ
+        AP+ZmTP/mZlm/5mZmf+Zmcz/mZn//5nMAP+ZzDP/mcxm/5nMmf+ZzMz/mcz//5n/AP+Z/zP/mf9m/5n/
+        mf+Z/8z/mf///8wAAP/MADP/zABm/8wAmf/MAMz/1Aj//8wzAP/MMzP/zDNm/8wzmf/MM8z/zDP//8xm
+        AP/MZjP/zGZm/8xmmf/MZsz/zGb//8yZAP/MmTP/zJlm/8yZmf/Mmcz/zJn//8zMAP/MzDP/zMxm/8zM
+        mf/MzMz/zMz//8z/AP/M/zP/zP9m/8z/mf/M/8z/zP////8AM///AGb//wCZ//8AzP//MwD//zMz//8z
+        Zv//M5n//zPM//8z////ZgD//2Yz//9mZv//Zpn//2bM//9m////mQD/3d3d//+ZzP//zGb/iAAA/8wA
+        //8AM5n/M2Yz/5lmAP8zMzP///vw/6CgpP+AgID//wAA/wD/AP///wD/AAD///8A//8A/////////wAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAArMqsAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAptDKrKbQptCmrMqsAAAAAAAAAAAAAAAAAAAAAAAArMqspqzKrKasptCmrMqspgAA
+        AAAAAAAAAAAAAAAAAMqsyqym0KasyqzKrKbQpqzKrAAAAAAAAAAAAAAAAACm0KasptCsptCmrKbQpqzK
+        rKbQpgAAAAAAAAAAAAAA0Kym0KbQpqbQpqzKrMqsyqzKrKbQrAAAAAAAAAAAAKzKpqymrKbQrKasyqym
+        rKaspqym0Kam0AAAAAAAAADKrKzR0tLS0dLT0sqsptDS0tPR0dPS0aymrAAAAAAAAKymytL///asCv//
+        0qym0v//CtDt///S0KbQAAAAAAAA0Kas0v//9qbS//8K0dAK///SrNP//9KmrKamAAAAAKym0KbS///T
+        rKb2///T0v//9qas9gr/0tCm0KwAAAAAptCmrNL///bQptH////////S0Kb2///Spqym0AAAAACsptCm
+        0v//06ymrNP/////06aspvb//9KsyqymAAAAAKbQpqzS///ayqzKrf///wrRrMqs0///0qasyqwAAACm
+        rKbQptL///amrKbQ0///9qymrMra///SyqzKptAAAKasyqym0v8K9qbQpqzQCv//0qbQpvb//9Kspqys
+        pgAAAMqsptDS///2pqzK2cvS///2pqym9gr/0sqsyqYAAAAArMqsptL//9OsptL/2ab2///S0Kb2///S
+        rKas0AAAAACmrMqs0v//9qbQCv8K0NL//wqspvb//9Km0KamAAAAAKzKrKbS//8K0/b//+3Qpu3///bT
+        Cv//0qym0KwAAAAAAKzKrNL/////////0qbQrf/////////SptCmpgAAAAAArMqm0Qr//////wumrKbQ
+        0////wr/CtGsptAAAAAAAAAArKym0dHR0dHRpqzKrKas0dGt0dGtyqymrAAAAAAAAADQpsqspqymrKbQ
+        ptCmrMqsptCmrMqsptAAAAAAAAAAAACsrMqsyqym0KaspqzKrKbQpqzKrKbQAAAAAAAAAAAAAADKrKas
+        yqymrMqsyqym0KbQpqzKrAAAAAAAAAAAAAAAAACsyqym0KbQrKasyqymrKasyqwAAAAAAAAAAAAAAAAA
+        AAAArMqspqamyqym0KbQptCmAAAAAAAAAAAAAAAAAAAAAAAAANCs0KzQptCmrKYAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAKamAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAD///////4////AA///AAD//gAAf/wAAD/4AAAf8AAAD+AAAAfgAAAH4AAAA8AAAAPAAAADwAAAA8AA
+        AAOAAAABgAAAAcAAAAPAAAADwAAAA8AAAAPgAAAD4AAAB/AAAAfwAAAP+AAAH/wAAD/+AAB//4AA///g
+        B////n///////ygAAAAwAAAAYAAAAAEACAAAAAAAgAoAAAAAAAAAAAAAAAEAAAAAAAAAAAD/gAAA/wCA
+        AP+AgAD/AACA/4AAgP8AgID/wMDA/8DcwP+myvD/8PDw////mf+Z1Jn/mdT////M////mZn/IiIw/wAA
+        Ef8AACL/AABE/wAAVf8AAHf/AACI/wAAqv8AAN3/AADu/wARAP8AIgD/AEQA/wBVAP8AdwD/AIgA/wCq
+        AP8A3QD/AO4A/xEAAP8iAAD/RAAA/1UAAP93AAD/kAAA/6oAAP/dAAD/7gAA/wAAM/8AAGb/AACZ/wAA
+        zP8AMwD/ADMz/wAzZv8AM6H/ADPM/wAz//8AZgD/AGYz/wBmZv8AZpn/AGbM/wBm//8AmQD/AJkz/wCZ
+        Zv8AmZn/AJnM/wCZ//8AzAD/AMwz/wDMZv8AzJn/AMzM/wDM//8A/zP/AP9m/wD/mf8A/8z/MwAA/zMA
+        M/8zAGb/MwCZ/zMAzP8zAP//MzMA/zMzO/8zM2b/MzOZ/zMzzP8zM///M2YA/zNuM/8zZmb/M2aZ/zNm
+        zP8zZv//M5kA/zOZM/8zmWb/M5mZ/zOZzP8zmf//M8wA/zPMM/8zzGb/M8yZ/zPMzP8zzP//M/8A/zP/
+        M/8z/2b/M/+Z/zP/zP8z////ZgAA/2YAM/9mAGb/ZgCZ/2YAzP9mAP//ZjMA/2YzM/9mM2b/ZjOZ/2Yz
+        zP9mM///ZmYA/2ZmM/9mZmb/ZmaZ/2ZmzP9mZv//ZpkA/2aZM/9mmWb/ZpmZ/2aZzP9mmf//ZswA/2bM
+        M/9mzGb/ZsyZ/2bMzP9mzP//Zv8A/2b/M/9m/2b/Zv+Z/2b/zP9m////mQAA/5kAM/+ZAGb/mQCZ/5kA
+        zP+ZAP//mTMA/5kzM/+ZM2b/mTOZ/5kzzP+ZM///oWYA/5lmM/+ZZmb/mWaZ/5lmzP+ZZv//mZkA/5mZ
+        M/+ZmWb/mZmZ/5mZzP+Zmf//mcwA/5nMM/+ZzGb/mcyZ/5nMzP+ZzP//mf8A/5n/M/+Z/2b/mf+Z/5n/
+        zP+Z////zAAA/8wAM//MAGb/zACZ/8wAzP/UCP//zDMA/8wzM//MM2b/zDOZ/8wzzP/MM///zGYA/8xm
+        M//MZmb/zGaZ/8xmzP/MZv//zJkA/8yZM//MmWb/zJmZ/8yZzP/Mmf//zMwA/8zMM//MzGb/zMyZ/8zM
+        zP/MzP//zP8A/8z/M//M/2b/zP+Z/8z/zP/M/////wAz//8AZv//AJn//wDM//8zAP//MzP//zNm//8z
+        mf//M8z//zP///9mAP//ZjP//2Zm//9mmf//Zsz//2b///+ZAP/d3d3//5nM///MZv+IAAD/zAD//wAz
+        mf8zZjP/mWYA/zMzM///+/D/oKCk/4CAgP//AAD/AP8A////AP8AAP///wD//wD/////////AAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAArMqsyqym0KbQpqzK
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA0Kasyqym0KbQpqzKrMqsptCmAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAMqspqzKrKbQpqymrMqspqym0KasyqwAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAACsyqym0Kasyqym0KbQpqzKrMqsptCmrMqsygAAAAAAAAAAAAAAAAAAAAAAAAAAAMqsptCmrMqs
+        pqzKrKasptCmrKbQpqzKrMqsptAAAAAAAAAAAAAAAAAAAAAAAAAArMqsyqym0Kasyqym0Kasyqym0Kas
+        yqaspqym0KasAAAAAAAAAAAAAAAAAAAAAACsyqymrMqsptCmrMqsptCmrMqsptCm0Kym0KbQpqzKrAAA
+        AAAAAAAAAAAAAAAAAKzKrKbQpqym0Kasyqym0Kasyqym0KaspqbQpqym0KasyqwAAAAAAAAAAAAAAAAA
+        rMqsptCm0KbQpqzKrMqsptCmrMqspqzKrNCm0KbQptCmptCmAAAAAAAAAAAAAACspqzKrKaspqasyqym
+        rKam0KasyqzKrKaspqamrKaspqysyqysygAAAAAAAAAAAADKrMqsptLS0tLRptLS0tLRrKbQpqym0dLS
+        0tLQrdHS0tLLrKbKrAAAAAAAAAAAANCmrMqs0f/////ZrPb/////0qym0KbS//////asC//////RrNCm
+        rMoAAAAAAAAAAKbQpqym0f////8LptH/////Csqspqz2/////9Gm0//////RpqasyqwAAAAAAAAA0Kas
+        yqzKrf/////YptDT/////9LQptL/////9qasCwr////RrMqsptCmAAAAAAAArKbQpqym0f////8LpqbR
+        /////wqsyvb/////0abQ0//////SpqzKrKbQAAAAAAAAyqym0Kas0f/////TrMqs0//////T2P/////T
+        pqymCwr////RptCmrMqsAAAAAACsptCmrMqs0f////8Lpqym0P////8K/////wrRrMqs0//////RrKbQ
+        pqym0AAAAADQpqzKrKam0f/////SrMqsptL//////////9Om0KasCwr////RptCmrMqsygAAAACsyqym
+        0Kas0f////8LpqzKrMr2////////CtCsptCm2f/////SrKasyqymrAAAAACmrMqspqzK0f/////TrMqs
+        pqzSCv//////0qbQpqymC//////RpqzKrKbQpgAAAACsyqym0Kam0f///wrZyqym0Kas9v/////t0Kas
+        ptCm2P/////Ryqymyqym0AAAAACsptCmrMqs0f/////TrMqsptCm0f/////2rMqsyqymC//////RrKbQ
+        pqzKrAAAAADKrKbQpqym0f///woLpqym0KasptP/////0qasptCm2f/////SptCmrMqspgAAAACsyqym
+        0Kas0f/////TptCmrNHSrNEK////CtCm0KasC//////Rpqym0KasygAAAACmrMqsptCm0f///wrZyqzK
+        ptIK0abZ/////9KspqzK0v/////RrKbQpqzKrAAAAACm0Kasyqym0f/////TrKas0Ar/06zLCv///wrR
+        ptCm2f/////RptCmrMqspgAAAADQrKbQpqym0f/////TrMqs0////9Gs0v/////TrKasC//////SrKbQ
+        pqzKrAAAAACsptCmrMqs0f/////SrKbRCv///9Osyvb/////0aas0v/////Rpqym0Kas0AAAAAAAyqas
+        yqym0f///wr20tL2/////++sptL/////9tLS9v/////RyqzKrKbQAAAAAAAArMqsptCm0f//////////
+        ////9qasyqz2///////////////RrKasyqymAAAAAAAA0KzKrKas0f//////////////0qzKrKbR////
+        ///////////RptCmrMqsAAAAAAAAAKasyqym0Qr///////////8LrKasyqzK2f/////////////RpqzK
+        rKYAAAAAAAAAAKzKrMqsptL2CgoKCgr2CtPRpqbQpqym0dkKCgoKCgr29tKm0KasyqwAAAAAAAAAAACs
+        pqzKrKbQpqzKrMqtyqymrMqspsqspsrQptCm0KzLrMqspqzKrAAAAAAAAAAAAADQpsqsptCmrMqsyqym
+        0KbQpqzKrKbQpqymrMqspqbQpqasyqym0AAAAAAAAAAAAAAArKzKrKasyqymrMqspqym0Kasyqym0KbQ
+        pqym0KasptCmrMqsAAAAAAAAAAAAAAAAAMqsptCm0Kasyqym0KbQpqzKrKbQpqymrMqsptCm0KasyqwA
+        AAAAAAAAAAAAAAAAAACm0KaspqzKrKbQpqym0KasptCmrMqsyqym0KasptCmrAAAAAAAAAAAAAAAAAAA
+        AAAArKbQptCmrMqsptCm0Kasyqym0KasptCmrMqs0KasAAAAAAAAAAAAAAAAAAAAAAAAANCmrKbQpqym
+        0KaspqzKrKbQpqzKrKbQpqymptAAAAAAAAAAAAAAAAAAAAAAAAAAAACsyqzKrKbQpqzKrMqsptCmrMqs
+        yqzKrKbQrAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKymrMqsptCmrMqsyqym0KaspqymrMoAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAyqzKrKbQpqymrKbQpqym0KbQAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAA0Kym0KbQptCsptDQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAA////////AAD///////8AAP//wAP//wAA//4AAH//AAD/+AAAH/8AAP/g
+        AAAH/wAA/8AAAAP/AAD/gAAAAf8AAP8AAAAA/wAA/gAAAAB/AAD8AAAAAD8AAPgAAAAAHwAA+AAAAAAf
+        AADwAAAAAA8AAPAAAAAADwAA4AAAAAAHAADgAAAAAAcAAOAAAAAABwAAwAAAAAADAADAAAAAAAMAAMAA
+        AAAAAwAAwAAAAAADAADAAAAAAAMAAMAAAAAAAwAAwAAAAAADAADAAAAAAAMAAMAAAAAAAwAAwAAAAAAD
+        AADAAAAAAAMAAMAAAAAAAwAA4AAAAAAHAADgAAAAAAcAAOAAAAAABwAA8AAAAAAPAADwAAAAAA8AAPgA
+        AAAAHwAA+AAAAAAfAAD8AAAAAD8AAP4AAAAAfwAA/wAAAAD/AAD/gAAAAf8AAP/AAAAD/wAA/+AAAAf/
+        AAD/+AAAH/8AAP/+AAB//wAA///AA///AAD///////8AAP///////wAAKAAAABAAAAAgAAAAAQAgAAAA
+        AABABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAnbEADaqzADmqswBXrbYAV6u0
+        ADqxsQANAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACzswAKq7QAd6y1ANqqswD/r7gA/6+4
+        AP+qswD/rLYA26u0AHqiuQALAAAAAAAAAAAAAAAAAAAAAAAAAACnsQAaqrMAwLG6AP+stQD/qbIA/6my
+        AP+psgD/qbIA/6y1AP+xuwD/q7QAwqqzABsAAAAAAAAAAAAAAACiogALqbIAwa+4AP+mrwD/qLEA/6av
+        AP+osQD/qLEA/6avAP+osQD/pq8A/6+4AP+qswDDqqoADAAAAAAAAAAAqLEAda+4AP/HzVb/2t6Q/8fN
+        VP/f4qD/s7sb/7K6Gf/f4p//yM5X/9rekP/Jzlj/r7kA/6mzAHkAAAAAubkAC6ixANypsgD/29+Q//3+
+        +P+8wzP//P32/9/im//e4Zf//f34/77FNv/+/vj/3uGU/6iyAP+osQDfsbEADaywADertAD+pq8A/9nd
+        iv/8/PP/rLUH/9HWcv///////////9LXd/+ttQf//Pzy/9zfjv+mrwD/q7QA/6u0ADqpsgBWr7gA/6Wv
+        AP/Z3Yr//Pzz/6+4EP+rswf/8/TZ//n67P+utw3/r7gP//z88v/b347/pq8A/6+4AP+rtABYq7QAVa+4
+        AP+lrwD/2d2K//v88/+utgv/tb0m/9HWb/////3/wshG/621CP/8/PL/29+O/6avAP+vuAD/q7QAWKqz
+        ADartAD+pq8A/9ndiv/7/PL/tb0d/+/xzP/U2Xj/6+2///Dxz/+2vh///Pzy/9vfjv+mrwD/q7UA/qew
+        ADqiuQALqbIA26myAP/Z3Yr///////v77v//////wchE/77FOf//////+/zv///////b343/qbIA/6mx
+        AN6dsQANAAAAAKmxAHOwuQD/uMAr/9TYfP/V2oL/y9Bg/6myAP+osgD/ys9d/9Xagf/U2Hz/ucAs/7C5
+        AP+psgB3AAAAAAAAAACzswAKqbMAvq+5AP+lrwD/pa8A/6avAP+psgD/qbIA/6avAP+lrwD/pa8A/6+5
+        AP+psgDBorkACwAAAAAAAAAAAAAAAKq1ABiqswC9sboA/6y2AP+psgD/qbIA/6myAP+psgD/rLYA/7G6
+        AP+rtAC/p7EAGgAAAAAAAAAAAAAAAAAAAAAAAAAAqqoACau0AHSstQDXqrMA/q+4AP+vuAD/q7QA/qy1
+        ANiqtQB1mbMACgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAoqIAC623ADWttgBUq7QAVa+4
+        ADaiuQALAAAAAAAAAAAAAAAAAAAAAAAAAAD4HwAA4AcAAMADAACAAQAAgAEAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAIABAACAAQAAwAMAAOAHAAD4HwAAKAAAACAAAABAAAAAAQAgAAAAAACAEAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAGurgAWqrAALa23ADWttwA1prEALrG8ABf//wABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK+z
+        ADartACIqrMAx6qzAOqpswD6qrMA/6qzAP+psgD7qrMA66u0AMirtgCJrrcAOQAAAAEAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKmw
+        AESstQC5rLQA+7C6AP+ttwD/q7QA/6qzAP+psgD/qbIA/6qzAP+rtAD/rbcA/7C6AP+qswD9q7UAvay0
+        AEcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKWl
+        ABGrtQCXrLUA/K+4AP+qswD/qbIA/6myAP+psgD/qbIA/6myAP+psgD/qbIA/6myAP+psgD/qbIA/6qz
+        AP+vuAD/rLUA/qu0AJ2mswAUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AACqsQAkqrUAyrG6AP+qswD/qbIA/6myAP+psgD/qbIA/6myAP+psgD/qbIA/6myAP+psgD/qbIA/6my
+        AP+psgD/qbIA/6myAP+qswD/sboA/6y1AM6sswAoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAr7YAI6y0ANmvuQD/qbIA/6myAP+psgD/qbIA/6myAP+psgD/qbIA/6myAP+psgD/qbIA/6my
+        AP+psgD/qbIA/6myAP+psgD/qbIA/6myAP+psgD/r7gA/6y0AN2qsQAnAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAKq7AA+qswDKr7kA/6myAP+psgD/qbIA/6myAP+psgD/qbIA/6myAP+psgD/qbIA/6my
+        AP+psgD/qbIA/6myAP+psgD/qbIA/6myAP+psgD/qbIA/6myAP+psgD/r7gA/6qzANCurgATAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAqbEAl7G6AP+psgD/p7EA/6WvAP+lrwD/pq8A/6ixAP+lrwD/pa8A/6Wv
+        AP+osQD/qbIA/6myAP+osQD/pa8A/6WvAP+lrwD/qLEA/6avAP+lrwD/pa8A/6ewAP+psgD/sboA/6my
+        AJ4AAAAAAAAAAAAAAAAAAAAAAAAAAKu0AD2stgD7qrMA/6exAP+6wS3/09h9/9PYff/Jzln/uL8j/9TZ
+        f//T2H3/0tZ2/6+3Dv+osQD/qLEA/663C//R1nT/09h9/9TZf/+5wSj/yc5Y/9PYff/T2H3/vcQy/6ex
+        AP+pswD/rLUA/aizAEYAAAAAAAAAAAAAAACAgAACqbEAt6+4AP+psgD/pa8A/87SYf///////////+7w
+        xP+wuRH/9/ji////////////1dp8/6WvAP+lrwD/09dz////////////+fnn/7K6Ff/v8MT/////////
+        ///T2Gv/pa8A/6myAP+vuAD/qbIAwKqqAAMAAAAAAAAAAKyxADGrtAD6qrMA/6myAP+lrwD/zNFd////
+        ////////7O6+/6WvAP/Kz1j////////////5+uv/s7sa/7G5FP/4+ef////////////N0mL/pq8A/+3v
+        vv///////////9HWZv+lrwD/qbIA/6qzAP+rtAD8qLIAOAAAAAAAAAAAqbMAgrC6AP+psgD/qbIA/6Wv
+        AP/M0V3////////////s7r7/qbEA/6qzBP/t78L////////////c4I//2t6F////////////7/DI/6u0
+        B/+psgD/7e++////////////0dZm/6WvAP+psgD/qbIA/7C6AP+qswCKAAAAAICAAAKqswDCrrcA/6my
+        AP+psgD/pa8A/8zRXf///////////+zuvv+psgD/pq8A/8HIP//+/vv///////7++v/+/vr/////////
+        /v/Eykn/pa8A/6myAP/t777////////////R1mb/pa8A/6myAP+psgD/rbcA/6qzAMmqqgADqrgAEqmy
+        AOertAD/qbIA/6myAP+lrwD/zNFd////////////7O6+/6myAP+psgD/p7EA/+Xoqv//////////////
+        ////////6Oqy/6ixAf+osgD/qbIA/+3vvv///////////9HWZv+lrwD/qbIA/6myAP+rtAD/qbEA7Kax
+        ABeqtwAnqbMA96qzAP+psgD/qbIA/6WvAP/M0V3////////////s7r7/qbIA/6myAP+nsAD/usEq//z8
+        8/////////////v88v+8wzL/prAA/6myAP+psgD/7e++////////////0dZl/6WvAP+psgD/qbIA/6qz
+        AP+qswD6qrUALaexADSqswD+qbIA/6myAP+psgD/pa8A/8zRXf///////////+zuvv+psgD/qbIA/6my
+        AP+lrwD/3OCP////////////8vPQ/6u0Av+psgD/qbIA/6myAP/t777////////////R1mX/pa8A/6my
+        AP+psgD/qbIA/6qzAP+osgA1qrQAM6qzAP6psgD/qbIA/6myAP+lrwD/zNFd////////////7O2+/6my
+        AP+psgD/qLEA/622Cf+zuxf/+Pnn//////////3/ys9X/6WvAP+psgD/qbIA/+3vvv///////////9HV
+        Zf+lrwD/qbIA/6myAP+psgD/qrMA/6iyADWotQAmqbIA96qzAP+psgD/qbIA/6WvAP/M0V3/////////
+        ///r7b7/qbIA/6ixAP+ttgr/6Oux/7G6E//S13D////////////z9Nb/rrYM/6ixAP+psgD/7e++////
+        ////////0dVl/6WvAP+psgD/qbIA/6qzAP+pswD6pLAALaW0ABGqswDmq7QA/6myAP+psgD/pa8A/8zR
+        Xf///////////+vtvv+psgD/pa4A/8/Uav//////29+K/6y0Bv/z9db////////////T13P/pa8A/6my
+        AP/t777////////////R1WX/pa8A/6myAP+psgD/q7QA/6myAOuirgAW//8AAamyAMGutwD/qbIA/6my
+        AP+lrwD/zNFd////////////6+28/6WvAP+xuRP/9/fh///////9/fb/tLsY/8nOVf////////////j5
+        5/+zuxf/p7AA/+3vvP///////////9DVZf+lrwD/qbIA/6myAP+ttwD/qrMAyKqqAAMAAAAAqbEAgLC6
+        AP+psgD/qbIA/6WvAP/M0V3////////////5+uv/5eim/+/xx/////////////Hyzv+ttgz/qbID/+3v
+        wf////////////Dyyv/m6af/+vvr////////////0NVl/6WvAP+psgD/qbIA/7C6AP+psgCIAAAAAAAA
+        AACuswAvq7QA+aqzAP+psgD/pa8A/83SYP//////////////////////////////////////xctJ/6av
+        AP+mrwD/wshB/////f/////////////////////////////////R1mf/pa8A/6myAP+qswD/q7QA+6Wz
+        ADYAAAAAAAAAAP//AAGpsgC1r7gA/6myAP+nsAD/usIv//j55//////////////////////////+/+Pm
+        pf+psgH/qbIA/6myAP+osQD/4OSc/////f//////////////////////+vrp/73EM/+nsAD/qbIA/6+4
+        AP+osgC8//8AAgAAAAAAAAAAAAAAAKmxADurtgD6qrMA/6myAP+osQD/tb0d/7/GPP++xTz/v8U8/7/F
+        PP+9xDb/rLUG/6ixAP+psgD/qbIA/6ixAP+stAX/vcQ1/7/FPP++xTv/vsU7/7/FPP+2vR3/qLEA/6my
+        AP+qswD/rLUA/KqyAEIAAAAAAAAAAAAAAAAAAAAAAAAAAKmyAJGxugD/qbIA/6myAP+nsQD/prAA/6aw
+        AP+msAD/prAA/6ewAP+osQD/qbIA/6myAP+psgD/qbIA/6iyAP+nsAD/prAA/6awAP+msAD/prAA/6ex
+        AP+psgD/qbIA/7G6AP+psgCYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAApLYADqqzAMawuQD/qbIA/6my
+        AP+psgD/qbIA/6myAP+psgD/qbIA/6myAP+psgD/qbIA/6myAP+psgD/qbIA/6myAP+psgD/qbIA/6my
+        AP+psgD/qbIA/6myAP+vuQD/q7QAy6+vABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAArbUAH6u0
+        ANKwuQD/qbIA/6myAP+psgD/qbIA/6myAP+psgD/qbIA/6myAP+psgD/qbIA/6myAP+psgD/qbIA/6my
+        AP+psgD/qbIA/6myAP+psgD/r7kA/6y1ANmqsQAkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAp68AIKy1AMSxugD/qrMA/6myAP+psgD/qbIA/6myAP+psgD/qbIA/6myAP+psgD/qbIA/6my
+        AP+psgD/qbIA/6myAP+psgD/qrMA/7G6AP+rtADJqrEAJAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAApKQADquzAJGrtQD6r7kA/6qzAP+psgD/qbIA/6myAP+psgD/qbIA/6my
+        AP+psgD/qbIA/6myAP+psgD/qrMA/6+4AP+rtAD8qrQAlp+vABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKu0AD2rswCzq7MA+bC6AP+utwD/q7QA/6qz
+        AP+pswD/qbIA/6qzAP+rtAD/rrcA/7C6AP+rtAD6q7UAtKuzAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACstgAxqbMAgKu0
+        AL+qswDlqbIA9qmyAP+psgD/qbMA96qzAOaqtADBrLQAgaq0ADMAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAALS0ABGutQAmp7EANKyxADSqtwAnqrgAEgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/8A///8AB//8AAP/8AAA/+AAAH/AAAA/gAAAH4AAAB8AA
+        AAOAAAABgAAAAYAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAAGAAAABgAAAAcAA
+        AAPgAAAH4AAAB/AAAA/4AAAf/AAAP/8AAP//wAP///gf/ygAAAAwAAAAYAAAAAEAIAAAAAAAgCUAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACxsQANrrkAFrGxABexsQAXprEAF7a2
+        AA7//wABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAv78ABKq1AC2rsgBnqrIAn6q0AMSqswDdqbIA7qmz
+        APCpswDwqbMA7qmyAN+qswDGqrMAoquyAGqssQAxmZkABQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKStAByttABwq7QAyKqzAPiwuQD/r7kA/663
+        AP+stQD/q7QA/6q0AP+qtAD/q7QA/6y1AP+ttwD/r7kA/7C5AP+qswD5qrQAy6u2AHetrQAfAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACqswAbq7UAiauzAOmwuQD/rbcA/6qz
+        AP+psgD/qbIA/6myAP+psgD/qbIA/6myAP+psgD/qbIA/6myAP+psgD/qbIA/6myAP+qswD/rbcA/7C5
+        AP+rtADrrLUAkKWtAB8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA//8AAaq0AGOstQDhsLoA/6u0
+        AP+psgD/qbIA/6myAP+psgD/qbIA/6myAP+psgD/qbIA/6myAP+psgD/qbIA/6myAP+psgD/qbIA/6my
+        AP+psgD/qbIA/6myAP+rtAD/sLkA/6y1AOaqswBsgL8ABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACmsQAXq7QAqa63
+        AP+stQD/qbIA/6myAP+psgD/qbIA/6myAP+psgD/qbIA/6myAP+psgD/qbIA/6myAP+psgD/qbIA/6my
+        AP+psgD/qbIA/6myAP+psgD/qbIA/6myAP+psgD/qbIA/6y1AP+vuAD/q7QAsKqqAB4AAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKyx
+        AC6stQDSsLoA/6myAP+psgD/qbIA/6myAP+psgD/qbIA/6myAP+psgD/qbIA/6myAP+psgD/qbIA/6my
+        AP+psgD/qbIA/6myAP+psgD/qbIA/6myAP+psgD/qbIA/6myAP+psgD/qbIA/6myAP+psgD/sLkA/6y1
+        ANinsQA0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAp7AAN6y1AOOuuAD/qbIA/6myAP+psgD/qbIA/6myAP+psgD/qbIA/6myAP+psgD/qbIA/6my
+        AP+psgD/qbIA/6myAP+psgD/qbIA/6myAP+psgD/qbIA/6myAP+psgD/qbIA/6myAP+psgD/qbIA/6my
+        AP+psgD/qbIA/663AP+stQDnp7MAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAACotAAsq7QA5K63AP+psgD/qbIA/6myAP+psgD/qbIA/6myAP+psgD/qbIA/6my
+        AP+psgD/qbIA/6myAP+psgD/qbIA/6myAP+psgD/qbIA/6myAP+psgD/qbIA/6myAP+psgD/qbIA/6my
+        AP+psgD/qbIA/6myAP+psgD/qbIA/6myAP+ttwD/rLUA56qvADMAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAKqqABWqswDTr7gA/6myAP+psgD/qbIA/6myAP+psgD/qbIA/6my
+        AP+psgD/qbIA/6myAP+psgD/qbIA/6myAP+psgD/qbIA/6myAP+psgD/qbIA/6myAP+psgD/qbIA/6my
+        AP+psgD/qbIA/6myAP+psgD/qbIA/6myAP+psgD/qbIA/6myAP+psgD/rrcA/6uzANqnsAAdAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/4AAAqmzAKewuQD/qbIA/6myAP+psgD/qbIA/6my
+        AP+psgD/qbIA/6myAP+psgD/qbIA/6myAP+psgD/qbIA/6myAP+psgD/qbIA/6myAP+psgD/qbIA/6my
+        AP+psgD/qbIA/6myAP+psgD/qbIA/6myAP+psgD/qbIA/6myAP+psgD/qbIA/6myAP+psgD/qbIA/7C5
+        AP+qswCxv78ABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAqbEAX663AP+psgD/qbIA/6my
+        AP+osQD/pq8A/6avAP+mrwD/pq8A/6ewAP+psgD/pq8A/6avAP+mrwD/pq8A/6avAP+psgD/qbIA/6my
+        AP+psgD/qbIA/6myAP+mrwD/pq8A/6avAP+mrwD/pq8A/6ixAP+nsAD/pq8A/6avAP+mrwD/pq8A/6ix
+        AP+psgD/qbIA/6myAP+vuAD/qbAAawAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACqtgAVqrMA4ay2
+        AP+psgD/qbIA/6ixAP+yuhP/yM5b/8jOW//Izlv/yM5b/7vCL/+vuAr/yM5b/8jOW//Izlv/yM5b/8bM
+        Uf+stAP/qbIA/6myAP+psgD/qbIA/6u0Af/Fy0//yM5b/8jOW//Izlv/yc5d/7C5Dv+7wi//yM5b/8jO
+        W//Izlv/yM5b/7S8GP+osQD/qbIA/6myAP+stQD/qrIA6aewAB0AAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AACpsQCAsLoA/6myAP+psgD/qbIA/6awAP/ByDf//////////////////////97hjv+qswT/8PLJ////
+        ///////////////////L0Vr/pq8A/6myAP+psgD/pq8A/8fNS///////////////////////9PXX/6y1
+        Cf/f447//////////////////////8nPRf+mrwD/qbIA/6myAP+psgD/sLoA/6uyAJEAAAAAAAAAAAAA
+        AAAAAAAAAAAAAKaxABepsgDnrLUA/6myAP+psgD/qbIA/6awAP/AxzX//////////////////////9zg
+        iv+jrQD/w8lA///+/P/////////////////09df/r7cM/6ixAP+osQD/rbUJ//Hyzv//////////////
+        //////3/xsxK/6OtAP/e4or//////////////////////8jOQv+mrwD/qbIA/6myAP+psgD/q7QA/6q0
+        AO2nsAAdAAAAAAAAAAAAAAAAAAAAAKqxAGmwuQD/qbIA/6myAP+psgD/qbIA/6awAP/AxzX/////////
+        /////////////9zgiv+mrwD/qLEA/+Xopv//////////////////////1Nlw/6WvAP+mrwD/0NVk////
+        ///////////////////p7Lf/qbIB/6awAP/e4or//////////////////////8jOQv+mrwD/qbIA/6my
+        AP+psgD/qbIA/7C5AP+psQB2AAAAAAAAAAAAAAAAgP8AAqmyAMGutwD/qbIA/6myAP+psgD/qbIA/6aw
+        AP/AxzX//////////////////////9zgiv+mrwD/p7AA/7vCKP/8/fL/////////////////+fnn/7O7
+        GP+vuA3/9/fe//////////////////39+P++xjn/pq8A/6awAP/e4or//////////////////////8jO
+        Qv+mrwD/qbIA/6myAP+psgD/qbIA/622AP+qsgDLzMwABQAAAAAAAAAArrUAJqqyAPWqswD/qbIA/6my
+        AP+psgD/qbIA/6awAP/AxzX//////////////////////9zgiv+mrwD/qbIA/6awAP/d4Y//////////
+        /////////////9rfhP/X23j//////////////////////+Hkmf+nsAD/qbIA/6awAP/e4or/////////
+        /////////////8jOQv+mrwD/qbIA/6myAP+psgD/qbIA/6qzAP+qswD5qq8AMAAAAAAAAAAAqLAAXq+4
+        AP+psgD/qbIA/6myAP+psgD/qbIA/6awAP/AxzX//////////////////////9zgiv+mrwD/qbIA/6ex
+        AP+0vBn/+fnl//////////////////3+9//9/fb/////////////////+/vv/7e/Iv+nsAD/qbIA/6aw
+        AP/e4or//////////////////////8jNQv+mrwD/qbIA/6myAP+psgD/qbIA/6myAP+wuQD/qLIAagAA
+        AAAAAAAAqbIAlbC5AP+psgD/qbIA/6myAP+psgD/qbIA/6awAP/AxzX//////////////////////9zg
+        iv+mrwD/qbIA/6myAP+mrwD/1dlw////////////////////////////////////////////2d2D/6av
+        AP+psgD/qbIA/6awAP/e4or//////////////////////8jNQv+mrwD/qbIA/6myAP+psgD/qbIA/6my
+        AP+vuQD/qLIAogAAAAAAAAAAqbIAva63AP+psgD/qbIA/6myAP+psgD/qbIA/6awAP/AxzX/////////
+        /////////////9zgiv+mrwD/qbIA/6myAP+osQD/r7gN//X11///////////////////////////////
+        ///3+OH/sroS/6exAP+psgD/qbIA/6awAP/e4or//////////////////////8jNQv+mrwD/qbIA/6my
+        AP+psgD/qbIA/6myAP+utwD/qrIAxoD/AAKqqgAJqbIA1qy2AP+psgD/qbIA/6myAP+psgD/qbIA/6aw
+        AP/AxzX//////////////////////9zgiv+mrwD/qbIA/6myAP+psgD/pa8A/8vRVv//////////////
+        ///////////////////Q1Wn/pq8A/6myAP+psgD/qbIA/6awAP/e4or//////////////////////8jN
+        Qv+mrwD/qbIA/6myAP+psgD/qbIA/6myAP+stQD/qbIA3rHEAA2ltAARqLIA5ay1AP+psgD/qbIA/6my
+        AP+psgD/qbIA/6awAP/AxzX//////////////////////9zgiv+mrwD/qbIA/6myAP+psgD/qLEA/6u0
+        Av/u8MH///////////////////////Dyyf+stQf/qLEA/6myAP+psgD/qbIA/6awAP/e4or/////////
+        /////////////8jNQv+mrwD/qbIA/6myAP+psgD/qbIA/6myAP+qtAD/qbIA7q6uABaxsQAXqbEA8Kq0
+        AP+psgD/qbIA/6myAP+psgD/qbIA/6awAP/AxzX//////////////////////9zgiv+mrwD/qbIA/6my
+        AP+psgD/qbIA/6WvAP/EykH//v77//////////////////Dyyf+ttQX/qLEA/6myAP+psgD/qbIA/6aw
+        AP/e4or//////////////////////8jNQv+mrwD/qbIA/6myAP+psgD/qbIA/6myAP+qtAD/qbEA8LGx
+        ABexsQAXqrIA76q0AP+psgD/qbIA/6myAP+psgD/qbIA/6awAP/AxzX//////////////////////9zf
+        iv+mrwD/qbIA/6myAP+psgD/qLIA/6ixAP+osQD/5uim///////////////////////R1WX/pa8A/6my
+        AP+psgD/qbIA/6awAP/e4or//////////////////////8jNQv+mrwD/qbIA/6myAP+psgD/qbIA/6my
+        AP+qtAD/qbEA8LGxABevvwAQqbIA5Ky1AP+psgD/qbIA/6myAP+psgD/qbIA/6awAP/AxzX/////////
+        /////////////9zfiv+mrwD/qbIA/6myAP+osQD/sroR/9DWYf+lrwD/vMMp//z99P//////////////
+        ///3+OD/sroU/6ixAP+psgD/qbIA/6awAP/e4or//////////////////////8jNQv+mrwD/qbIA/6my
+        AP+psgD/qbIA/6myAP+qtAD/qbIA7q6uABafnwAIqLIA1K22AP+psgD/qbIA/6myAP+psgD/qbIA/6aw
+        AP/AxzX//////////////////////9zfiv+mrwD/qbIA/6myAP+lrwD/1Nl2//7+9/+6wSf/pK4A/97h
+        j///////////////////////2t2B/6avAP+psgD/qbIA/6awAP/e4or//////////////////////8fN
+        Qv+mrwD/qbIA/6myAP+psgD/qbIA/6myAP+stQD/qLIA3bGxAA0AAAAAqrMAu664AP+psgD/qbIA/6my
+        AP+psgD/qbIA/6awAP/AxzX//////////////////////9zfiv+mrwD/qbIA/6exAP+0vBv/+Pno////
+        ///l6KL/prAA/7S8Gf/5+eX/////////////////+/zt/7jAI/+nsAD/qbIA/6awAP/e4or/////////
+        /////////////8fNQv+mrwD/qbIA/6myAP+psgD/qbIA/6myAP+utwD/qrMAxYD/AAIAAAAAqbIAkrC5
+        AP+psgD/qbIA/6myAP+psgD/qbIA/6awAP/AxzX//////////////////////9zfiv+mrwD/qbIA/6aw
+        AP/e4Y7////////////+/vr/w8k+/6OtAP/V2nP//////////////////////+Llnv+nsQD/qbIA/6aw
+        AP/e4or//////////////////////8fNQv+mrwD/qbIA/6myAP+psgD/qbIA/6myAP+vuQD/qbMAngAA
+        AAAAAAAAq7MAW6+4AP+psgD/qbIA/6myAP+psgD/qbIA/6awAP/AxzX//////////////////////9re
+        hf+jrAD/pK0A/7vCK//8/fL/////////////////6eyx/6ixAP+vtw3/9PXW//////////////////7+
+        +f+/xjP/o60A/6OtAP/d4YX//////////////////////8fNQf+mrwD/qbIA/6myAP+psgD/qbIA/6my
+        AP+vuQD/q7IAZwAAAAAAAAAAqLYAI6mzAPSqswD/qbIA/6myAP+psgD/qbIA/6awAP/AxzX/////////
+        /////////////+7vwv/T12n/1Nlr/+7wwv//////////////////////1Nly/6ewAP+mrwD/y9FW////
+        ///////////////////w8sv/1tpt/9baa//w8cP//////////////////////8fNQf+mrwD/qbIA/6my
+        AP+psgD/qbIA/6qzAP+qswD4qLQALAAAAAAAAAAAgIAAAqmzAL6utwD/qbIA/6myAP+psgD/qbIA/6aw
+        AP/AxzX////////////////////////////////////////////////////////////y9M3/rrYJ/6ix
+        AP+osQD/q7QE/+7vwv///////////////////////////////////////////////////////////8fM
+        Qf+mrwD/qbIA/6myAP+psgD/qbIA/623AP+psgDJzMwABQAAAAAAAAAAAAAAAKmzAGWvuAD/qbIA/6my
+        AP+psgD/qbIA/6awAP/ByDf/////////////////////////////////////////////////////////
+        ///Izk7/pq8A/6myAP+psgD/pq8A/8PJQP////z/////////////////////////////////////////
+        /////////////8jOQv+mrwD/qbIA/6myAP+psgD/qbIA/7C5AP+rtABwAAAAAAAAAAAAAAAAAAAAAKaz
+        ABSpsgDkrLUA/6myAP+psgD/qbIA/6exAP+2viD//Pzy////////////////////////////////////
+        /////////////+vtuf+qswL/qLIA/6myAP+psgD/qbIA/6ixAP/m6ab/////////////////////////
+        /////////////////////////f72/7rAJf+nsAD/qbIA/6myAP+psgD/q7QA/6qzAOqnsQAaAAAAAAAA
+        AAAAAAAAAAAAAAAAAACqsgB+sLkA/6myAP+psgD/qbIA/6myAP+nsQD/yM5R//Hzy//29+D/9ffe//b3
+        3v/2997/9vfe//b33v/2997/6eux/7a+Hv+nsAD/qbIA/6myAP+psgD/qbIA/6ewAP+0vBv/5umr//X3
+        3f/1997/9ffe//X23v/19t7/9fbe//b33//x88v/zNFV/6ixAP+psgD/qbIA/6myAP+psgD/sLoA/6mz
+        AIkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAChrgATqrMA3a22AP+psgD/qbIA/6myAP+psgD/p7AA/6y1
+        BP+vuA//r7cO/6+3Dv+vtw7/r7cO/6+3D/+vuA7/qrMA/6ewAP+psgD/qbIA/6myAP+psgD/qbIA/6my
+        AP+nsQD/qbIA/6+3Dv+vtw//r7cO/6+3Dv+vtw7/r7cO/6+4D/+ttQT/p7AA/6myAP+psgD/qbIA/6my
+        AP+stQD/qrMA5K24ABkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAq7QAWK22AP+qswD/qbIA/6my
+        AP+psgD/qbIA/6ixAP+osQD/qLEA/6ixAP+osQD/qLEA/6ixAP+osQD/qbIA/6myAP+psgD/qbIA/6my
+        AP+psgD/qbIA/6myAP+psgD/qbIA/6ixAP+osQD/qLEA/6ixAP+osQD/qLEA/6ixAP+osQD/qbIA/6my
+        AP+psgD/qbIA/6myAP+utwD/q7MAYQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKuz
+        AKCxugD/qbIA/6myAP+psgD/qbIA/6myAP+psgD/qbIA/6myAP+psgD/qbIA/6myAP+psgD/qbIA/6my
+        AP+psgD/qbIA/6myAP+psgD/qbIA/6myAP+psgD/qbIA/6myAP+psgD/qbIA/6myAP+psgD/qbIA/6my
+        AP+psgD/qbIA/6myAP+psgD/qbIA/7C6AP+psQCrgIAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAKq4ABKqswDMr7gA/6myAP+psgD/qbIA/6myAP+psgD/qbIA/6myAP+psgD/qbIA/6my
+        AP+psgD/qbIA/6myAP+psgD/qbIA/6myAP+psgD/qbIA/6myAP+psgD/qbIA/6myAP+psgD/qbIA/6my
+        AP+psgD/qbIA/6myAP+psgD/qbIA/6myAP+psgD/r7gA/6q0ANOqtgAVAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACotQAmqrQA3K64AP+psgD/qbIA/6myAP+psgD/qbIA/6my
+        AP+psgD/qbIA/6myAP+psgD/qbIA/6myAP+psgD/qbIA/6myAP+psgD/qbIA/6myAP+psgD/qbIA/6my
+        AP+psgD/qbIA/6myAP+psgD/qbIA/6myAP+psgD/qbIA/6myAP+utwD/q7QA5ayxAC4AAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAArLIAK6u0ANuvuAD/qbIA/6my
+        AP+psgD/qbIA/6myAP+psgD/qbIA/6myAP+psgD/qbIA/6myAP+psgD/qbIA/6myAP+psgD/qbIA/6my
+        AP+psgD/qbIA/6myAP+psgD/qbIA/6myAP+psgD/qbIA/6myAP+psgD/qbIA/664AP+stQDjp7AANwAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKqx
+        ACestQDKsboA/6qzAP+psgD/qbIA/6myAP+psgD/qbIA/6myAP+psgD/qbIA/6myAP+psgD/qbIA/6my
+        AP+psgD/qbIA/6myAP+psgD/qbIA/6myAP+psgD/qbIA/6myAP+psgD/qbIA/6myAP+psgD/sLkA/6y1
+        ANGqsAAtAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAACqqgASqrQAn622AP+ttgD/qbIA/6myAP+psgD/qbIA/6myAP+psgD/qbIA/6my
+        AP+psgD/qbIA/6myAP+psgD/qbIA/6myAP+psgD/qbIA/6myAP+psgD/qbIA/6myAP+psgD/qbIA/6y1
+        AP+utwD/qrMAqKKuABYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKqzAFqstQDasLkA/6y1AP+psgD/qbIA/6my
+        AP+psgD/qbIA/6myAP+psgD/qbIA/6myAP+psgD/qbIA/6myAP+psgD/qbIA/6myAP+psgD/qbIA/6my
+        AP+stQD/sLkA/6y1AN6ttQBg//8AAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACuvAATq7UAf6qz
+        AOKvuAD/rrcA/6qzAP+psgD/qbIA/6myAP+psgD/qbIA/6myAP+psgD/qbIA/6myAP+psgD/qbIA/6my
+        AP+qswD/rrcA/7C5AP+rtADkq7MAgK6uABYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAALOzABSsswBlq7MAvauzAPKvuAD/sLkA/664AP+ttgD/q7QA/6u0AP+qtAD/q7QA/6y2
+        AP+utwD/sLkA/6+4AP+qtAD0q7QAv6y2AGmxsQAXAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKqxACSrswBbq7QAkqmzALupswDTqrMA46qy
+        AO+psQDwqrMA5KqyANWqsgC9qbQAlaizAF6qsQAnAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAC/vwAIpbQAEaaxABexsQAXtLQAEarGAAkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD///gP//8AAP//
+        AAD//wAA//wAAD//AAD/8AAAD/8AAP/AAAAD/wAA/4AAAAH/AAD/AAAAAP8AAP4AAAAAfwAA/AAAAAA/
+        AAD4AAAAAB8AAPAAAAAADwAA8AAAAAAPAADgAAAAAAcAAOAAAAAABwAAwAAAAAADAADAAAAAAAMAAIAA
+        AAAAAQAAgAAAAAABAACAAAAAAAEAAIAAAAAAAQAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAAAAAAAAAIAAAAAAAQAAgAAAAAABAACAAAAAAAEAAIAA
+        AAAAAQAAwAAAAAADAADAAAAAAAMAAOAAAAAABwAA4AAAAAAHAADwAAAAAA8AAPgAAAAADwAA+AAAAAAf
+        AAD8AAAAAD8AAP4AAAAAfwAA/wAAAAD/AAD/gAAAAf8AAP/gAAAD/wAA//AAAA//AAD//AAAP/8AAP//
+        gAH//wAA///4H///AAA=
+</value>
+  </data>
+</root>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HspGuiSourceV301/HSPGui/HID.cs	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,1788 @@
+using System;
+using System.Collections;
+using System.Threading;
+using System.IO;
+using System.Runtime.InteropServices;
+using System.Windows.Forms;
+using Microsoft.Win32.SafeHandles;
+
+//------------------------------------------------------------------------------------------
+// OS24EVK-59 split into HeartRateApp EXE and MAX30101 DLL.
+// Moved all MAX30101 DLL classes into namespace Maxim.MAX30101GUI
+// Moved all HeartRateApp GUI classes into namespace Maxim.MAX30101
+// OS24EVK-59 Create separate project that builds Maxim.MAX30101GUI DLL library
+
+// OS24EVK-59 moved class HID into namespace Maxim.MAX30101 instead of namespace HeartRateApp
+namespace Maxim.MAX30101
+{
+#pragma warning disable 1574
+    /// <summary>
+    /// USB Human Interface Device functions to connect to EV kit without requiring a custom device driver
+    /// </summary>
+#pragma warning restore 1574
+    public class HID
+    {
+        private IntPtr EventObject;
+        private System.Threading.NativeOverlapped managedOverlapped;
+        private IntPtr nonManagedOverlapped;
+        private IntPtr nonManagedBuffer;
+        public SafeFileHandle writeHandle;
+        public ArrayList writeHandleArray = new ArrayList();
+        public SafeFileHandle readHandle;
+        public ArrayList readHandleArray = new ArrayList();
+        public ArrayList desiredHIDPathNameArray = new ArrayList();
+        public String deviceID = System.String.Format("Vid_{0:x4}&Pid_{1:x4}", support.DEFAULT_VENDOR_ID, support.DEFAULT_PRODUCT_ID);
+
+        private bool explicit_report_id = true;
+        private const byte DEFAULT_REPORT_ID = 0;
+        private const byte SHORT_REPORT_ID = 1;
+        public const byte HID_REPORT_ID_1 = 1; // MAX30101 optical data, 3 bytes per channel, up to 3 channels per sample
+        public const byte HID_REPORT_ID_2 = 2; // LIS2DH accelerometer data, 2 bytes per channel, 3 channels per sample
+        public const byte HID_REPORT_ID_3 = 3; // reserved
+        private const byte USB_OVERFLOW = 8;
+        private const byte USB_WRITE_ERROR = 4;
+        private const byte USB_READ_ERROR = 2;
+        public const byte I2C_NACK_ERROR = 1;
+        private const byte API_FAIL = 0;     //API functions return non-0 upon success, to easily denote 'true' for C programs
+        private const byte I2C_SUCCESS = 3;  //we'll also use a non-0 value to denote success, since returning a '0' would lead to trouble when mixed with API's returns.
+        private const byte GP_SUCCESS = 3;
+        private const byte GP_FAIL = 0;
+        private const byte REPORT_SIZE = 64;
+
+        // verify: https://jira.maxim-ic.com/browse/OS24EVK-57 mutex lock HID.IOBuf[] before FlushQueue()
+        // mutexGuardIOBuf.WaitOne();   // Wait until it is safe to enter.
+        // mutexGuardIOBuf.ReleaseMutex();    // Release the Mutex.
+        public static Mutex mutexGuardIOBuf = new Mutex();
+        // TODO1: OS24EVK-57 2015-04-01 myHID.readHID2() needs to return result into IOBuf. But IOBuf = new byte[64], do we replace with IOBuf = new byte[128]? Does this affect readHID()?
+        public byte[] IOBuf = new byte[REPORT_SIZE];
+
+        private const int IOtimeout = 10000;
+
+        // API declarations relating to device management (SetupDixxx and 
+        // RegisterDeviceNotification functions).   
+
+        // from dbt.h
+
+        internal const Int32 DBT_DEVNODES_CHANGED = 7; 
+        internal const Int32 DBT_DEVICEARRIVAL = 0X8000;
+        internal const Int32 DBT_DEVICEREMOVECOMPLETE = 0X8004;
+        internal const Int32 DBT_DEVTYP_DEVICEINTERFACE = 5;
+        internal const Int32 DBT_DEVTYP_HANDLE = 6;
+        internal const Int32 DEVICE_NOTIFY_ALL_INTERFACE_CLASSES = 4;
+        internal const Int32 DEVICE_NOTIFY_SERVICE_HANDLE = 1;
+        internal const Int32 DEVICE_NOTIFY_WINDOW_HANDLE = 0;
+        internal const Int32 WM_DEVICECHANGE = 0X219;
+        internal const Int32 SPDRP_HARDWAREID = 1;
+
+        // from setupapi.h
+
+        internal const Int32 DIGCF_PRESENT = 2;
+        internal const Int32 DIGCF_DEVICEINTERFACE = 0X10;
+
+        // Two declarations for the DEV_BROADCAST_DEVICEINTERFACE structure.
+
+        // Use this one in the call to RegisterDeviceNotification() and
+        // in checking dbch_devicetype in a DEV_BROADCAST_HDR structure:
+
+        [StructLayout(LayoutKind.Sequential)]
+        internal class DEV_BROADCAST_DEVICEINTERFACE
+        {
+            internal Int32 dbcc_size;
+            internal Int32 dbcc_devicetype;
+            internal Int32 dbcc_reserved;
+            internal Guid dbcc_classguid;
+            internal Int16 dbcc_name;
+        }
+
+        // Use this to read the dbcc_name String and classguid:
+
+        [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
+        internal class DEV_BROADCAST_DEVICEINTERFACE_1
+        {
+            internal Int32 dbcc_size;
+            internal Int32 dbcc_devicetype;
+            internal Int32 dbcc_reserved;
+            [MarshalAs(UnmanagedType.ByValArray, ArraySubType = UnmanagedType.U1, SizeConst = 16)]
+            internal Byte[] dbcc_classguid;
+            [MarshalAs(UnmanagedType.ByValArray, SizeConst = 255)]
+            internal Char[] dbcc_name;
+        }
+
+        [StructLayout(LayoutKind.Sequential)]
+        internal class DEV_BROADCAST_HDR
+        {
+            internal Int32 dbch_size;
+            internal Int32 dbch_devicetype;
+            internal Int32 dbch_reserved;
+        }
+
+        internal struct SP_DEVICE_INTERFACE_DATA        
+        {
+            internal Int32 cbSize;
+            internal System.Guid InterfaceClassGuid;
+            internal Int32 Flags;
+            internal IntPtr Reserved;
+        }
+
+        //[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
+        //internal struct SP_DEVICE_INTERFACE_DETAIL_DATA
+        //{
+        //    internal Int32 cbSize;
+        //    //internal String DevicePath;            
+        //    internal Char[] DevicePath;
+        //}
+
+// warning CS0649: Field 'Maxim.MAX30101.HID.SP_DEVINFO_DATA.cbSize' is never assigned to, and will always have its default value 0
+#pragma warning disable 0649
+        internal struct SP_DEVINFO_DATA
+        {
+            internal Int32 cbSize;
+            internal System.Guid ClassGuid;
+            internal Int32 DevInst;
+            internal Int32 Reserved;
+        }
+#pragma warning restore 0649
+
+        //HDEVINFO SetupDiGetClassDevs(const GUID *ClassGuid, PCTSTR Enumerator, HWND hwndParent, DWORD Flags);
+        [DllImport("setupapi.dll", SetLastError = true, CharSet = CharSet.Auto)]
+        internal static extern IntPtr SetupDiGetClassDevs(ref System.Guid ClassGuid, IntPtr Enumerator, IntPtr hwndParent, Int32 Flags);
+
+        //BOOL SetupDiDestroyDeviceInfoList(HDEVINFO DeviceInfoSet);
+        [DllImport("setupapi.dll", SetLastError = true)]
+        internal static extern Boolean SetupDiDestroyDeviceInfoList(IntPtr DeviceInfoSet);
+
+        //BOOL SetupDiEnumDeviceInterfaces(HDEVINFO DeviceInfoSet, PSP_DEVINFO_DATA DeviceInfoData, const GUID *InterfaceClassGuid, DWORD MemberIndex, PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData);
+        [DllImport("setupapi.dll", SetLastError = true)]
+        internal static extern Boolean SetupDiEnumDeviceInterfaces(IntPtr DeviceInfoSet, ref SP_DEVINFO_DATA DeviceInfoData, ref System.Guid InterfaceClassGuid, Int32 MemberIndex, ref SP_DEVICE_INTERFACE_DATA DeviceInterfaceData);
+        [DllImport("setupapi.dll", SetLastError = true)]
+        // required to pass DeviceInfoData=null
+        internal static extern Boolean SetupDiEnumDeviceInterfaces(IntPtr DeviceInfoSet, IntPtr DeviceInfoData, ref System.Guid InterfaceClassGuid, Int32 MemberIndex, ref SP_DEVICE_INTERFACE_DATA DeviceInterfaceData);
+
+        //BOOL SetupDiGetDeviceInterfaceDetail(HDEVINFO DeviceInfoSet, PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData, PSP_DEVICE_INTERFACE_DETAIL_DATA DeviceInterfaceDetailData, DWORD DeviceInterfaceDetailDataSize, PDWORD RequiredSize, PSP_DEVINFO_DATA DeviceInfoData);
+        //[DllImport("setupapi.dll", SetLastError = true, CharSet = CharSet.Auto)]
+        //internal  extern Boolean SetupDiGetDeviceInterfaceDetail(IntPtr DeviceInfoSet, ref SP_DEVICE_INTERFACE_DATA DeviceInterfaceData, ref SP_DEVICE_INTERFACE_DETAIL_DATA DeviceInterfaceDetailData, Int32 DeviceInterfaceDetailDataSize, ref Int32 RequiredSize, ref SP_DEVINFO_DATA DeviceInfoData);
+        //[DllImport("setupapi.dll", SetLastError = true, CharSet = CharSet.Auto)]
+        //// required to pass DeviceInfoData=null
+        //internal  extern Boolean SetupDiGetDeviceInterfaceDetail(IntPtr DeviceInfoSet, ref SP_DEVICE_INTERFACE_DATA DeviceInterfaceData, ref SP_DEVICE_INTERFACE_DETAIL_DATA DeviceInterfaceDetailData, Int32 DeviceInterfaceDetailDataSize, ref Int32 RequiredSize, IntPtr DeviceInfoData);
+        // cannot get SP_DEVICE_INTERFACE_DETAIL_DATA's DevicePath field to work properly, so use IntPtr instead of ref SP_DEVICE_INTERFACE_DATA
+        [DllImport("setupapi.dll", SetLastError = true, CharSet = CharSet.Auto)]
+        // required to pass DeviceInterfaceDetailData=null
+        internal static extern Boolean SetupDiGetDeviceInterfaceDetail(IntPtr DeviceInfoSet, ref SP_DEVICE_INTERFACE_DATA DeviceInterfaceData, IntPtr DeviceInterfaceDetailData, Int32 DeviceInterfaceDetailDataSize, ref Int32 RequiredSize, ref SP_DEVINFO_DATA DeviceInfoData); 
+        [DllImport("setupapi.dll", SetLastError = true, CharSet = CharSet.Auto)]
+        // required to pass DeviceInterfaceDetailData=null, DeviceInfoData=null
+        internal static extern Boolean SetupDiGetDeviceInterfaceDetail(IntPtr DeviceInfoSet, ref SP_DEVICE_INTERFACE_DATA DeviceInterfaceData, IntPtr DeviceInterfaceDetailData, Int32 DeviceInterfaceDetailDataSize, ref Int32 RequiredSize, IntPtr DeviceInfoData); 
+
+        //BOOL SetupDiEnumDeviceInfo(HDEVINFO DeviceInfoSet, DWORD MemberIndex, PSP_DEVINFO_DATA DeviceInfoData);
+        [DllImport("setupapi.dll", SetLastError = true)]
+        internal static extern Boolean SetupDiEnumDeviceInfo(IntPtr DeviceInfoSet, Int32 MemberIndex, ref SP_DEVINFO_DATA DevInfoData);
+
+        //BOOL SetupDiGetDeviceRegistryProperty(HDEVINFO DeviceInfoSet, PSP_DEVINFO_DATA DeviceInfoData, DWORD Property, PDWORD PropertyRegDataType, PBYTE PropertyBuffer, DWORD PropertyBufferSize, PDWORD RequiredSize);
+        [DllImport("setupapi.dll", SetLastError = true, CharSet = CharSet.Auto)]
+        internal static extern Boolean SetupDiGetDeviceRegistryProperty(IntPtr DeviceInfoSet, ref SP_DEVINFO_DATA DevInfoData, Int32 Property, IntPtr PropertyRegDataType, IntPtr PropertyBuffer, Int32 PropertyBufferSize, ref Int32 RequiredSize);
+        
+        [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
+        internal static extern IntPtr RegisterDeviceNotification(IntPtr hRecipient, IntPtr NotificationFilter, Int32 Flags);
+
+        [DllImport("user32.dll", SetLastError = true)]
+        internal static extern Boolean UnregisterDeviceNotification(IntPtr Handle);
+
+        //  API declarations for HID communications.
+
+        //  from hidpi.h
+        //  Typedef enum defines a set of integer constants for HidP_Report_Type
+
+        internal const Int16 HidP_Input = 0;
+        internal const Int16 HidP_Output = 1;
+        internal const Int16 HidP_Feature = 2;
+
+        [StructLayout(LayoutKind.Sequential)]
+        internal struct HIDD_ATTRIBUTES
+        {
+            internal Int32 Size;
+            internal UInt16 VendorID;
+            internal UInt16 ProductID;
+            internal UInt16 VersionNumber;
+        }
+
+        [DllImport("hid.dll", SetLastError = true)]
+        internal static extern Boolean HidD_FlushQueue(SafeFileHandle HidDeviceObject);
+
+        [DllImport("hid.dll", SetLastError = true)]
+        internal static extern Boolean HidD_GetAttributes(SafeFileHandle HidDeviceObject, ref HIDD_ATTRIBUTES Attributes);
+
+        [DllImport("hid.dll", SetLastError = true)]
+        internal static extern void HidD_GetHidGuid(ref System.Guid HidGuid);
+
+        public void getHidGuid(ref System.Guid hidGuid)
+        {
+            DebugMessage = string.Format("{0} entered", System.Reflection.MethodInfo.GetCurrentMethod().Name);
+#if DEBUG
+            HidD_GetHidGuid(ref hidGuid);
+#else
+            try
+            {
+                HidD_GetHidGuid(ref hidGuid);
+            }
+            catch (Exception ex)
+            {
+                throw new Exception(ex.Message + Environment.NewLine + new System.Diagnostics.StackFrame().GetMethod().Name);
+            }
+#endif
+            DebugMessage = string.Format("{0} exited", System.Reflection.MethodInfo.GetCurrentMethod().Name);
+        }
+
+        public string DebugMessage;
+        //public void TraceMessage(string message,
+        //[System.Runtime.CompilerServices.CallerMemberName] string memberName = "",
+        //[System.Runtime.CompilerServices.CallerFilePath] string sourceFilePath = "",
+        //[System.Runtime.CompilerServices.CallerLineNumber] int sourceLineNumber = 0)
+        //{
+        //    Console.WriteLine("message: " + message);
+        //    Console.WriteLine("member name: " + memberName);
+        //    Console.WriteLine("source file path: " + sourceFilePath);
+        //    Console.WriteLine("source line number: " + sourceLineNumber);
+        //}
+
+        /// <summary>
+        /// FindDesiredHIDPathNamesFromGuid() only appends to desiredHIDPathNameArray. 
+        /// Desired HIDs that have been removed from the system are removed from desiredHIDPathNameArray in openHIDhandles
+        /// </summary>
+        /// <param name="myGuid"></param>
+        private void FindDesiredHIDPathNamesFromGuid(System.Guid myGuid)
+        {
+            DebugMessage = string.Format("{0} entered", System.Reflection.MethodInfo.GetCurrentMethod().Name);
+            // VERIFY: https://jira.maxim-ic.com/browse/OS24EVK-59 (intermittent) Matlab Exception Message: Arithmetic operation resulted in an overflow.
+            // But I never see this kind of exception thrown from within the C# GUI.
+            // HID.findHIDs() still raises the exception in Matlab, 
+            // Message: Arithmetic operation resulted in an overflow.
+            //
+            //    % Required: connect to MAX30101EVKIT hardware
+            //    fprintf('Connecting to MAX30101EVKIT hardware...\n');
+            //    for trial=0:2000
+            //        try
+            //            %pause(1) % delay at least 1 second
+            //            myMAX30101.myHID.findHIDs();
+            //            % Sometimes we get Error using MAX30101Example
+            //            %   If this happens, try clearing the workspace and run again.
+            //            % Message: Arithmetic operation resulted in an overflow.
+            //            % FindDesiredHIDPathNamesFromGuid
+            //            % findHIDs
+            //            % Source: MAX30101
+            //            % HelpLink:    
+            //            if (myMAX30101.myHID.isConnected())
+            //                break
+            //            end
+            //        catch me
+            //            % disp(me)
+            //        end
+            //    end
+            //
+            // If matlab does successfully connect to USB, it is able to get 
+            // streaming data through the PartialArrayIntAvailable event 
+            // handler -- even though it can't understand 
+            // System.Collections.ArrayList data, it does at least understand 
+            // Array<System.Int32> or int[] data.
+            //
+            Int32 memberIndex = 0;
+            Int32 bufferSize = 0;
+            IntPtr deviceInfoSet = new System.IntPtr();
+            SP_DEVICE_INTERFACE_DATA DeviceInterfaceData = new SP_DEVICE_INTERFACE_DATA();
+            IntPtr deviceInterfaceDetailDataBuffer = IntPtr.Zero;
+
+            // VERIFY: https://jira.maxim-ic.com/browse/OS24EVK-59 (intermittent) Matlab Exception Message: Arithmetic operation resulted in an overflow.
+            // diagnostic: trying to avoid "Arithmetic overflow" from matlab. Limit the number of HID devices to be checked.
+            const int memberIndexLimit = 100;
+            
+#if DEBUG
+#else
+            try
+            {
+#endif
+            DebugMessage = string.Format("{0} first deviceInfoSet = SetupDiGetClassDevs(ref myGuid, IntPtr.Zero, IntPtr.Zero, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);", System.Reflection.MethodInfo.GetCurrentMethod().Name);
+            deviceInfoSet = SetupDiGetClassDevs(ref myGuid, IntPtr.Zero, IntPtr.Zero, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);
+
+                memberIndex = 0;
+
+                // The cbSize element of the DeviceInterfaceData structure must be set to the structure's size in bytes. 
+                // The size is 28 bytes for 32-bit code and 32 bits for 64-bit code.
+                DeviceInterfaceData.cbSize = Marshal.SizeOf(DeviceInterfaceData);
+
+                while (memberIndex < memberIndexLimit)
+                {
+                    // Begin with memberIndex = 0 and increment through the device information set until no more devices are available.
+                    DebugMessage = string.Format("{0} memberIndex={1} first SetupDiEnumDeviceInterfaces ", System.Reflection.MethodInfo.GetCurrentMethod().Name, memberIndex);
+                    if (!SetupDiEnumDeviceInterfaces(deviceInfoSet, IntPtr.Zero, ref myGuid, memberIndex, ref DeviceInterfaceData))
+                    {
+                        break;
+                    }
+
+                    DebugMessage = string.Format("{0} memberIndex={1} first SetupDiGetDeviceInterfaceDetail ", System.Reflection.MethodInfo.GetCurrentMethod().Name, memberIndex);
+                    SetupDiGetDeviceInterfaceDetail(deviceInfoSet, ref DeviceInterfaceData, IntPtr.Zero, 0, ref bufferSize, IntPtr.Zero);
+                    //tempLastError = GetLastError();
+                    //if (tempLastError != ERROR_INSUFFICIENT_BUFFER)  // ERROR_INSUFFICIENT_BUFFER is expected on this first call
+                    //    break;
+                    //FIXME add error check
+
+                    // Allocate memory for the SP_DEVICE_INTERFACE_DETAIL_DATA structure using the returned buffer size.
+                    DebugMessage = string.Format("{0} memberIndex={1} Marshal.AllocHGlobal(bufferSize) ", System.Reflection.MethodInfo.GetCurrentMethod().Name, memberIndex);
+                    deviceInterfaceDetailDataBuffer = Marshal.AllocHGlobal(bufferSize);
+                    // Returns a System.IntPtr pointer to the newly allocated global heap memory.
+                    // This memory must be released using the Marshal.FreeHGlobal method.
+                    // Marshal.AllocHGlobal(numBytes) could throw OutOfMemoryException ?
+
+                    // Store cbSize in the first bytes of the array. The number of bytes varies with 32- and 64-bit systems.
+                    DebugMessage = string.Format("{0} memberIndex={1} Marshal.WriteInt32 ", System.Reflection.MethodInfo.GetCurrentMethod().Name, memberIndex);
+                    Marshal.WriteInt32(deviceInterfaceDetailDataBuffer, (IntPtr.Size == 4) ? (4 + Marshal.SystemDefaultCharSize) : 8);
+
+                    // Call SetupDiGetDeviceInterfaceDetail again.
+                    // This time, pass a pointer to DetailDataBuffer and the returned required buffer size.
+                    DebugMessage = string.Format("{0} memberIndex={1} second SetupDiGetDeviceInterfaceDetail ", System.Reflection.MethodInfo.GetCurrentMethod().Name, memberIndex);
+                    if (!SetupDiGetDeviceInterfaceDetail(deviceInfoSet, ref DeviceInterfaceData, deviceInterfaceDetailDataBuffer, bufferSize, ref bufferSize, IntPtr.Zero))
+                        break;
+
+                    // Skip over cbsize (4 bytes) to get the address of the devicePathName.
+                    // VERIFY: https://jira.maxim-ic.com/browse/OS24EVK-59 (intermittent) Matlab Exception Message
+                    DebugMessage = string.Format("{0} memberIndex={1} IntPtr pDevicePathName = IntPtr.Add(deviceInterfaceDetailDataBuffer, 4); ", System.Reflection.MethodInfo.GetCurrentMethod().Name, memberIndex);
+                    IntPtr pDevicePathName = IntPtr.Add(deviceInterfaceDetailDataBuffer, 4);
+                    // DebugMessage = string.Format("{0} memberIndex={1} new IntPtr(deviceInterfaceDetailDataBuffer.ToInt32() + 4); ", System.Reflection.MethodInfo.GetCurrentMethod().Name, memberIndex);
+                    // BAD CODE. IntPtr pDevicePathName = new IntPtr(deviceInterfaceDetailDataBuffer.ToInt32() + 4);
+                    // BAD CODE. assumes the pointer is a 32-bit address, intermittently fails from 64-bit matlab client.
+
+                    // Get the String containing the devicePathName.
+                    DebugMessage = string.Format("{0} memberIndex={1} Marshal.PtrToStringAuto(pDevicePathName); ", System.Reflection.MethodInfo.GetCurrentMethod().Name, memberIndex);
+                    string tempPathName = Marshal.PtrToStringAuto(pDevicePathName);
+
+                    // match any device pathname that contains deviceID (case-insensitive match) "Vid_{0:x4}&Pid_{1:x4}"
+                    DebugMessage = string.Format("{0} memberIndex={1} if (tempPathName.ToLower().IndexOf(deviceID.ToLower()) != -1) ", System.Reflection.MethodInfo.GetCurrentMethod().Name, memberIndex);
+                    if (tempPathName.ToLower().IndexOf(deviceID.ToLower()) != -1)
+                    {
+                        DebugMessage = string.Format("{0} memberIndex={1} desiredHIDPathNameArray.Add(tempPathName); ", System.Reflection.MethodInfo.GetCurrentMethod().Name, memberIndex);
+                        desiredHIDPathNameArray.Add(tempPathName);
+                    }
+
+                    DebugMessage = string.Format("{0} memberIndex={1} memberIndex = memberIndex + 1; ", System.Reflection.MethodInfo.GetCurrentMethod().Name, memberIndex);
+
+                    // VERIFY: https://jira.maxim-ic.com/browse/OS24EVK-59 (intermittent) Matlab Exception Message
+                    // why didn't they call Marshal.FreeHGlobal here, inside the while loop? Isn't this a memory leak?
+                    // Free the memory allocated previously by AllocHGlobal.
+                    if (deviceInterfaceDetailDataBuffer != IntPtr.Zero)
+                    {
+                        Marshal.FreeHGlobal(deviceInterfaceDetailDataBuffer);
+                        deviceInterfaceDetailDataBuffer = IntPtr.Zero;
+                    }
+                    
+                    memberIndex = memberIndex + 1;
+                }
+#if DEBUG
+                // Free the memory allocated previously by AllocHGlobal.
+                if (deviceInterfaceDetailDataBuffer != IntPtr.Zero)
+                    Marshal.FreeHGlobal(deviceInterfaceDetailDataBuffer);
+
+                if (deviceInfoSet != IntPtr.Zero)
+                    SetupDiDestroyDeviceInfoList(deviceInfoSet);
+#else
+            }
+            catch (Exception ex)
+            {
+                throw new Exception(ex.Message + Environment.NewLine + new System.Diagnostics.StackFrame().GetMethod().Name);
+            }
+            finally
+            {
+                // Free the memory allocated previously by AllocHGlobal.
+                if (deviceInterfaceDetailDataBuffer != IntPtr.Zero)
+                    Marshal.FreeHGlobal(deviceInterfaceDetailDataBuffer);
+
+                if (deviceInfoSet != IntPtr.Zero)
+                    SetupDiDestroyDeviceInfoList(deviceInfoSet);
+            }
+#endif
+                DebugMessage = string.Format("{0} exited", System.Reflection.MethodInfo.GetCurrentMethod().Name);
+        }
+
+        private void FindAllHIDPathNamesFromGuid(System.Guid myGuid, ArrayList allHIDPathNameArray)
+        {
+            DebugMessage = string.Format("{0} entered", System.Reflection.MethodInfo.GetCurrentMethod().Name);
+            // VERIFY: https://jira.maxim-ic.com/browse/OS24EVK-59 (intermittent) Matlab Exception Message: Arithmetic operation resulted in an overflow.
+            // But I never see this kind of exception thrown from within the C# GUI.
+            // HID.findHIDs() still raises the exception in Matlab, 
+            // Message: Arithmetic operation resulted in an overflow.
+            Int32 memberIndex = 0; 
+            Int32 bufferSize = 0;
+            IntPtr deviceInfoSet = new System.IntPtr();
+            SP_DEVICE_INTERFACE_DATA DeviceInterfaceData = new SP_DEVICE_INTERFACE_DATA(); 
+            IntPtr deviceInterfaceDetailDataBuffer = IntPtr.Zero;
+
+            // VERIFY: https://jira.maxim-ic.com/browse/OS24EVK-59 (intermittent) Matlab Exception Message: Arithmetic operation resulted in an overflow.
+            // diagnostic: trying to avoid "Arithmetic overflow" from matlab. Limit the number of HID devices to be checked.
+            const int memberIndexLimit = 100;
+            
+            
+#if DEBUG
+#else
+            try
+            {
+#endif
+            DebugMessage = string.Format("{0} first deviceInfoSet = SetupDiGetClassDevs(ref myGuid, IntPtr.Zero, IntPtr.Zero, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);", System.Reflection.MethodInfo.GetCurrentMethod().Name);
+            deviceInfoSet = SetupDiGetClassDevs(ref myGuid, IntPtr.Zero, IntPtr.Zero, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);
+
+                memberIndex = 0;
+
+                // The cbSize element of the DeviceInterfaceData structure must be set to the structure's size in bytes. 
+                // The size is 28 bytes for 32-bit code and 32 bits for 64-bit code.
+                DeviceInterfaceData.cbSize = Marshal.SizeOf(DeviceInterfaceData);
+
+                // VERIFY: https://jira.maxim-ic.com/browse/OS24EVK-59 (intermittent) Matlab Exception Message: Arithmetic operation resulted in an overflow.
+                while (memberIndex < memberIndexLimit)
+                {
+                    DebugMessage = string.Format("{0} memberIndex={1} first SetupDiEnumDeviceInterfaces ", System.Reflection.MethodInfo.GetCurrentMethod().Name, memberIndex);
+                    if (!SetupDiEnumDeviceInterfaces(deviceInfoSet, IntPtr.Zero, ref myGuid, memberIndex, ref DeviceInterfaceData))
+                    {
+                        break;
+                    }
+
+                    DebugMessage = string.Format("{0} memberIndex={1} first SetupDiGetDeviceInterfaceDetail ", System.Reflection.MethodInfo.GetCurrentMethod().Name, memberIndex);
+                    SetupDiGetDeviceInterfaceDetail(deviceInfoSet, ref DeviceInterfaceData, IntPtr.Zero, 0, ref bufferSize, IntPtr.Zero);
+
+                    // Allocate memory for the SP_DEVICE_INTERFACE_DETAIL_DATA structure using the returned buffer size.
+                    DebugMessage = string.Format("{0} memberIndex={1} Marshal.AllocHGlobal(bufferSize) ", System.Reflection.MethodInfo.GetCurrentMethod().Name, memberIndex);
+                    deviceInterfaceDetailDataBuffer = Marshal.AllocHGlobal(bufferSize);
+
+                    // Store cbSize in the first bytes of the array. The number of bytes varies with 32- and 64-bit systems.
+                    DebugMessage = string.Format("{0} memberIndex={1} Marshal.WriteInt32 ", System.Reflection.MethodInfo.GetCurrentMethod().Name, memberIndex);
+                    Marshal.WriteInt32(deviceInterfaceDetailDataBuffer, (IntPtr.Size == 4) ? (4 + Marshal.SystemDefaultCharSize) : 8);
+
+                    // Call SetupDiGetDeviceInterfaceDetail again.
+                    // This time, pass a pointer to deviceInterfaceDetailDataBuffer and the returned required buffer size.
+                    DebugMessage = string.Format("{0} memberIndex={1} second SetupDiGetDeviceInterfaceDetail ", System.Reflection.MethodInfo.GetCurrentMethod().Name, memberIndex);
+                    if (!SetupDiGetDeviceInterfaceDetail(deviceInfoSet, ref DeviceInterfaceData, deviceInterfaceDetailDataBuffer, bufferSize, ref bufferSize, IntPtr.Zero))
+                        break;
+
+                    // Skip over cbsize (4 bytes) to get the address of the devicePathName.
+                    // VERIFY: https://jira.maxim-ic.com/browse/OS24EVK-59 (intermittent) Matlab Exception Message
+                    DebugMessage = string.Format("{0} memberIndex={1} IntPtr pDevicePathName = IntPtr.Add(deviceInterfaceDetailDataBuffer, 4); ", System.Reflection.MethodInfo.GetCurrentMethod().Name, memberIndex);
+                    // example: IntPtr right way to add an offset (portable to 64-bit clients)
+                    IntPtr pDevicePathName = IntPtr.Add(deviceInterfaceDetailDataBuffer, 4);
+                    // DebugMessage = string.Format("{0} memberIndex={1} IntPtr pDevicePathName = new IntPtr(deviceInterfaceDetailDataBuffer.ToInt32() + 4); ", System.Reflection.MethodInfo.GetCurrentMethod().Name, memberIndex);
+                    // BAD CODE. IntPtr pDevicePathName = new IntPtr(deviceInterfaceDetailDataBuffer.ToInt32() + 4);
+                    // BAD CODE. assumes the pointer is a 32-bit address, intermittently fails from 64-bit matlab client.
+
+                    // Get the String containing the devicePathName.
+                    DebugMessage = string.Format("{0} memberIndex={1} Marshal.PtrToStringAuto(pDevicePathName); ", System.Reflection.MethodInfo.GetCurrentMethod().Name, memberIndex);
+                    allHIDPathNameArray.Add(Marshal.PtrToStringAuto(pDevicePathName));
+
+                    // VERIFY: https://jira.maxim-ic.com/browse/OS24EVK-59 (intermittent) Matlab Exception Message
+                    // why didn't they call Marshal.FreeHGlobal here, inside the while loop? Isn't this a memory leak?
+                    // Free the memory allocated previously by AllocHGlobal.
+                    if (deviceInterfaceDetailDataBuffer != IntPtr.Zero)
+                    {
+                        Marshal.FreeHGlobal(deviceInterfaceDetailDataBuffer);
+                        deviceInterfaceDetailDataBuffer = IntPtr.Zero;
+                    }
+                   
+                    memberIndex = memberIndex + 1;
+                }
+#if DEBUG
+                // Free the memory allocated previously by AllocHGlobal.
+                if (deviceInterfaceDetailDataBuffer != IntPtr.Zero)
+                    Marshal.FreeHGlobal(deviceInterfaceDetailDataBuffer);
+
+                if (deviceInfoSet != IntPtr.Zero)
+                    SetupDiDestroyDeviceInfoList(deviceInfoSet);
+#else
+            }
+            catch (Exception ex)
+            {
+                throw new Exception(ex.Message + Environment.NewLine + new System.Diagnostics.StackFrame().GetMethod().Name);
+            }
+            finally
+            {
+                // Free the memory allocated previously by AllocHGlobal.
+                if (deviceInterfaceDetailDataBuffer != IntPtr.Zero)                    
+                    Marshal.FreeHGlobal(deviceInterfaceDetailDataBuffer);                
+
+                if (deviceInfoSet != IntPtr.Zero)
+                    SetupDiDestroyDeviceInfoList(deviceInfoSet);
+            }
+#endif
+            DebugMessage = string.Format("{0} exited", System.Reflection.MethodInfo.GetCurrentMethod().Name);
+        }
+
+        public bool isConnected()
+        {
+            try
+            {
+                return desiredHIDPathNameArray.Count != 0 ? true : false;
+            }
+            catch (Exception ex)
+            {
+                throw new Exception(ex.Message + Environment.NewLine + new System.Diagnostics.StackFrame().GetMethod().Name);
+            }
+        }
+
+
+        /// <summary>
+        /// Called when a WM_DEVICECHANGE message has arrived,
+        /// indicating that a device has been attached or removed.
+        /// 
+        /// </summary>
+        /// <param name="m"> a message with information about the device </param>
+        /// <returns>true on HID device arrival or remove complete</returns>
+        public bool HandleWMDeviceChangeMessage(Message m)
+        {
+            // Example code:
+            // 
+            // <code>
+            // protected override void WndProc(ref Message m)
+            // {
+            //     if (myHID != null)
+            //     {
+            //         if (myHID.HandleWMDeviceChangeMessage(m) /* m.Msg == HID.WM_DEVICECHANGE */ )
+            //         {
+            //             // optional: handle newly arrived connection or surprise disconnect
+            //         }
+            //     }
+            //     // Let the base form process the message.
+            //     base.WndProc(ref m);
+            // }
+            // </code>
+            // 
+            // https://jira.maxim-ic.com/browse/OS24EVK-59 WndProc if HID.WM_DEVICECHANGE do HID.OnDeviceChange(Message m)
+            try
+            {
+                if (m.Msg == HID.WM_DEVICECHANGE)
+                {
+                    //if ((int)m.WParam == HID.DBT_DEVNODES_CHANGED)  //this always occurs when any USB device is attached/detached. Use this if not registering for device notifications.
+                    if (
+                            (   m.WParam.ToInt32() == HID.DBT_DEVICEARRIVAL 
+                            ||  m.WParam.ToInt32() == HID.DBT_DEVICEREMOVECOMPLETE
+                            ) 
+                        && 
+                            (m.LParam.ToInt32() != 0) 
+                        && 
+                            DeviceIDMatch(m)
+                       )
+                    {
+                        closeHIDhandles();
+                        findHIDs();
+                        // cboEVB_init();
+                        return true;
+                    }
+                }
+                return false;
+            }
+            catch (Exception ex)
+            {
+                throw new Exception(ex.Message + Environment.NewLine + new System.Diagnostics.StackFrame().GetMethod().Name);
+            }
+        }
+
+        /// <summary>
+        /// findHIDs() called upon startup or if a desired HID has been inserted or removed
+        /// </summary>
+        public void findHIDs()
+        {
+            DebugMessage = string.Format("{0} entered", System.Reflection.MethodInfo.GetCurrentMethod().Name);
+            ArrayList allHIDPathNameArray = new ArrayList();
+            System.Guid hidGuid = new System.Guid();
+
+            // https://jira.maxim-ic.com/browse/OS24EVK-59 (intermittent) Matlab Exception Message: Arithmetic operation resulted in an overflow.
+#if DEBUG
+#else
+            try
+            {
+#endif
+                HidD_GetHidGuid(ref hidGuid);
+                // FindDesiredHIDPathNamesFromGuid() builds desiredHIDPathNameArray which is a list of all desired HIDs in the system
+                // desiredHIDPathNameArray is a global list and is used to maintain the order of desired HIDs in the selection list. 
+                // USB ports have different priorities, and the user could have attached the first desired HID to a lower priority port. 
+                // Hence, when another desired HID is attached to a higher priority port, it will come earlier in allHIDPathNameArray, but it will be maintained in the same attachment order in desiredHIDPathNameArray.
+                // Note that desiredHIDPathNameArray is only appended to or deleted from; it is never recreated in whole.
+                // FIXME desiredHIDPathNameArray will get duplicate pathnames for desired HIDs that were already attached, but these will be removed by openHIDhandles() since they're in allHIDPathNameArray only once. 
+                // These duplicates pathnames are appended after the initial list, so they won't affect order.
+                FindDesiredHIDPathNamesFromGuid(hidGuid);
+                // FindAllHIDPathNamesFromGuid() builds allHIDPathNameArray which is a list of all HIDs in the system. It is recreated every time a desired HID is attached or removed.
+                FindAllHIDPathNamesFromGuid(hidGuid, allHIDPathNameArray);
+                // openHIDhandles() gets handles for all desired HIDs
+                // openHIDhandles() loops through all attached HIDs and checks for a match of each item in desiredHIDPathNameArray. This maintains the attachement order.
+                // If a previously attached HID has been removed, it won't be found in allHIDPathNameArray and it will be removed from desiredHIDPathNameArray.
+                openHIDhandles(allHIDPathNameArray);
+                if (desiredHIDPathNameArray.Count != 0)
+                {
+                    prepareForOverlappedTransfer();
+                }
+#if DEBUG
+#else
+            }
+            catch (Exception ex)
+            {
+                throw new Exception(ex.Message + Environment.NewLine + new System.Diagnostics.StackFrame().GetMethod().Name);
+            }
+#endif
+            DebugMessage = string.Format("{0} exited", System.Reflection.MethodInfo.GetCurrentMethod().Name);
+        }
+
+        private void openHIDhandles(ArrayList allHIDPathNameArray)
+        {
+            DebugMessage = string.Format("{0} entered", System.Reflection.MethodInfo.GetCurrentMethod().Name);
+            int desiredHIDPathNameArrayCounter;
+            int allHIDPathNameArrayCounter;
+            bool found_installed_device;
+            try
+            {
+                desiredHIDPathNameArrayCounter = 0;
+                while (desiredHIDPathNameArrayCounter < desiredHIDPathNameArray.Count) // count will change if a previously installed device has been removed, so don't use a for loop
+                {
+                    found_installed_device = false;
+                    allHIDPathNameArrayCounter = 0;
+                    while (allHIDPathNameArrayCounter < allHIDPathNameArray.Count)
+                    {
+                        if ((string)allHIDPathNameArray[allHIDPathNameArrayCounter] == (string)desiredHIDPathNameArray[desiredHIDPathNameArrayCounter])
+                        {
+                            writeHandle = FileIO.CreateFile((string)desiredHIDPathNameArray[desiredHIDPathNameArrayCounter], FileIO.GENERIC_READ | FileIO.GENERIC_WRITE, FileIO.FILE_SHARE_READ | FileIO.FILE_SHARE_WRITE, IntPtr.Zero, FileIO.OPEN_EXISTING, 0, 0);
+                            if (!(writeHandle.IsInvalid))
+                            {
+                                readHandle = FileIO.CreateFile((string)desiredHIDPathNameArray[desiredHIDPathNameArrayCounter], FileIO.GENERIC_READ | FileIO.GENERIC_WRITE, FileIO.FILE_SHARE_READ | FileIO.FILE_SHARE_WRITE, IntPtr.Zero, FileIO.OPEN_EXISTING, FileIO.FILE_FLAG_OVERLAPPED, 0);
+                                if (!(readHandle.IsInvalid))
+                                {
+                                    writeHandleArray.Add(writeHandle);
+                                    readHandleArray.Add(readHandle);
+                                    allHIDPathNameArray.RemoveAt(allHIDPathNameArrayCounter); // remove it so we don't repeatedly add it when we check for new devices (after we finish checking for previously installed devices)
+                                    found_installed_device = true;
+                                }
+                                else
+                                {
+                                    writeHandle.Close();
+                                    writeHandle = null;
+                                    readHandle = null;
+                                }
+                            }
+                            else
+                            {
+                                writeHandle = null;
+                                readHandle = null; 
+                            }
+                            break;
+                        }
+                        allHIDPathNameArrayCounter++;
+                    }
+                    if (found_installed_device == false)    // no match in all allHIDPathNameArray elements; the device has been removed so remove its pathname from desiredHIDPathNameArray. Don't use counter at max count to check if not found, since max count can change.
+                        desiredHIDPathNameArray.RemoveAt(desiredHIDPathNameArrayCounter);   // decrements count by 1; don't increment desiredHIDPathNameArrayCounter
+                    else
+                        desiredHIDPathNameArrayCounter++;
+                }
+            }
+            catch (Exception ex)
+            {
+                DebugMessage = string.Format("{0} exception {1}", System.Reflection.MethodInfo.GetCurrentMethod().Name, ex.Message + Environment.NewLine + new System.Diagnostics.StackFrame().GetMethod().Name);
+                throw new Exception(ex.Message + Environment.NewLine + new System.Diagnostics.StackFrame().GetMethod().Name);
+            }
+            DebugMessage = string.Format("{0} exited", System.Reflection.MethodInfo.GetCurrentMethod().Name);
+        }
+
+        public void closeHIDhandles()
+        {
+            try
+            {
+                if (desiredHIDPathNameArray.Count != 0)
+                {
+                    foreach (Object obj in writeHandleArray)
+                        ((SafeFileHandle)obj).Close();
+                    writeHandleArray.Clear();
+                    writeHandle = null;
+                    foreach (Object obj in readHandleArray)
+                        ((SafeFileHandle)obj).Close();
+                    readHandleArray.Clear();
+                    readHandle = null;
+                }
+            }
+            catch (Exception ex)
+            {
+                throw new Exception(ex.Message + Environment.NewLine + new System.Diagnostics.StackFrame().GetMethod().Name);
+            }
+        }
+
+        private void prepareForOverlappedTransfer()
+        {
+            try
+            {
+                EventObject = FileIO.CreateEvent(IntPtr.Zero, false, false, String.Empty);
+                managedOverlapped.OffsetLow = 0;
+                managedOverlapped.OffsetHigh = 0;
+                managedOverlapped.EventHandle = EventObject; // HIDOverlapped is the overlapped structure used in ReadFile; EventObject will be signaled upon completion of ReadFile
+                nonManagedOverlapped = Marshal.AllocHGlobal(Marshal.SizeOf(managedOverlapped));
+                Marshal.StructureToPtr(managedOverlapped, nonManagedOverlapped, false);
+
+                nonManagedBuffer = Marshal.AllocHGlobal(REPORT_SIZE);
+            }
+            catch (Exception ex)
+            {
+                throw new Exception(ex.Message + Environment.NewLine + new System.Diagnostics.StackFrame().GetMethod().Name);
+            }
+        }
+
+        public void FlushQueue()
+        {
+            try
+            {
+                if (writeHandle == null)
+                {
+                    return;
+                }
+                if (readHandle == null)
+                {
+                    return;
+                }
+
+                HidD_FlushQueue(writeHandle);
+                HidD_FlushQueue(readHandle);
+            }
+            catch
+            {
+                throw new Exception(new System.Diagnostics.StackFrame().GetMethod().Name);
+            }
+        }
+
+        public void writeReadHID()
+        {
+            try
+            {
+                if (writeHandle == null)
+                {
+                    return;
+                }
+                if (readHandle == null)
+                {
+                    return;
+                }
+
+                writeHID();
+                readHID();
+            }
+            catch (Exception ex)
+            {
+                throw new Exception(ex.Message + Environment.NewLine + new System.Diagnostics.StackFrame().GetMethod().Name);
+            }
+        }
+
+        public void writeHID()
+        {
+            if (writeHandle == null)
+            {
+                return;
+            }
+            if (readHandle == null)
+            {
+                return;
+            }
+
+            int BytesSucceed;
+            bool api_status;
+
+            try
+            {
+                BytesSucceed = 0;
+                Marshal.Copy(IOBuf, 0, nonManagedBuffer, REPORT_SIZE);
+                api_status = FileIO.WriteFile(writeHandle, nonManagedBuffer, REPORT_SIZE, ref BytesSucceed, IntPtr.Zero);
+                //endpoint in interrupt at uC occurs after this WriteFile call since the in data is ready and the host takes it; endpoint in interrupt does not occur after ReadFile call
+
+                if (api_status == false)
+                {
+                    //MessageBox.Show(Err.LastDllError);
+                    throw new Exception(support.ResultOfAPICall("API WriteFile error"));
+                }
+            }
+            catch (Exception ex)
+            {
+                throw new Exception(ex.Message + new System.Diagnostics.StackFrame().GetMethod().Name);
+            }
+        }
+
+        public void readHID()
+        {
+            if (writeHandle == null)
+            {
+                return;
+            }
+            if (readHandle == null)
+            {
+                return;
+            }
+
+            int BytesSucceed;
+            bool api_status;
+            int status;
+
+            try
+            {
+                Array.Clear(IOBuf, 0, IOBuf.Length);
+
+                BytesSucceed = 0;
+
+                api_status = FileIO.ReadFile(readHandle, nonManagedBuffer, REPORT_SIZE, ref BytesSucceed, nonManagedOverlapped);
+                
+                if (api_status == false) 
+                {
+                    //MsgBox(Err.LastDllError)
+                    status = FileIO.WaitForSingleObject(EventObject, IOtimeout);                    
+
+                    if (status != FileIO.WAIT_OBJECT_0) 
+                    {
+                        api_status = FileIO.CancelIo(readHandle);
+                        throw new Exception(support.ResultOfAPICall("API ReadFile error"));
+                    }
+                    FileIO.GetOverlappedResult(readHandle, nonManagedOverlapped, ref BytesSucceed, false);
+                }
+
+                // TODO1: OS24EVK-57 2015-04-01 myHID.readHID2() needs to return result into IOBuf. But IOBuf = new byte[64], do we replace with IOBuf = new byte[128]? Does this affect readHID()?
+                if (BytesSucceed > IOBuf.Length)
+                {
+                    IOBuf = new byte[BytesSucceed];
+                    Array.Clear(IOBuf, 0, IOBuf.Length);
+                }
+                Marshal.Copy(nonManagedBuffer, IOBuf, 0, BytesSucceed);
+            }
+            catch (Exception ex)
+            {
+                throw new Exception(ex.Message + Environment.NewLine + new System.Diagnostics.StackFrame().GetMethod().Name);
+            }
+        }
+
+        public void readHID2() // this function is for testing multiple report read on a single ReadFile()
+        {
+            if (writeHandle == null)
+            {
+                return;
+            }
+            if (readHandle == null)
+            {
+                return;
+            }
+
+            int BytesSucceed;
+            bool api_status;
+            int status;
+
+            try
+            {
+                int size = 128;
+                //byte[] buf = new byte[size];
+                IntPtr nonManagedBuf = Marshal.AllocHGlobal(size);
+                //Array.Clear(buf, 0, size);
+
+                BytesSucceed = 0;
+
+                api_status = FileIO.ReadFile(readHandle, nonManagedBuf, size, ref BytesSucceed, nonManagedOverlapped);
+
+                if (api_status == false)
+                {
+                    //MsgBox(Err.LastDllError)
+                    status = FileIO.WaitForSingleObject(EventObject, IOtimeout);
+
+                    if (status != FileIO.WAIT_OBJECT_0)
+                    {
+                        api_status = FileIO.CancelIo(readHandle);
+                        throw new Exception(support.ResultOfAPICall("API ReadFile error"));
+                    }
+                    FileIO.GetOverlappedResult(readHandle, nonManagedOverlapped, ref BytesSucceed, false);
+                }
+
+                // TODO1: OS24EVK-57 2015-04-01 myHID.readHID2() needs to return result into IOBuf. But IOBuf = new byte[64], do we replace with IOBuf = new byte[128]? Does this affect readHID()?
+                if (BytesSucceed > IOBuf.Length)
+                {
+                    IOBuf = new byte[BytesSucceed];
+                    Array.Clear(IOBuf, 0, IOBuf.Length);
+                }
+                Marshal.Copy(nonManagedBuf, IOBuf, 0, BytesSucceed);
+                
+                if (nonManagedBuf != IntPtr.Zero)
+                    Marshal.FreeHGlobal(nonManagedBuffer);
+            }
+            catch (Exception ex)
+            {
+                throw new Exception(ex.Message + Environment.NewLine + new System.Diagnostics.StackFrame().GetMethod().Name);
+            }
+        }
+        public void freeHeap()
+        {
+            try
+            {
+                if (nonManagedBuffer != IntPtr.Zero)
+                    Marshal.FreeHGlobal(nonManagedBuffer);
+                if (nonManagedOverlapped != IntPtr.Zero)
+                    Marshal.FreeHGlobal(nonManagedOverlapped);
+            }
+            catch (Exception ex)
+            {
+                throw new Exception(ex.Message + Environment.NewLine + new System.Diagnostics.StackFrame().GetMethod().Name);
+            }
+        }
+
+        ///  <summary>
+        ///  Requests to receive a notification when a device is attached or removed.
+        ///  </summary>
+        ///  
+        ///  <param name="formHandle"> handle to the window that will receive device events. </param>
+        ///  <param name="classGuid"> device interface GUID. </param>
+        ///  <param name="deviceNotificationHandle"> returned device notification handle. </param>
+        ///  
+        ///  <returns>
+        ///  True on success.
+        ///  </returns>
+        ///  
+        public Boolean RegisterForDeviceNotifications(IntPtr formHandle, Guid classGuid, ref IntPtr deviceNotificationHandle)
+        {
+            DEV_BROADCAST_DEVICEINTERFACE devBroadcastDeviceInterface = new DEV_BROADCAST_DEVICEINTERFACE();
+            IntPtr devBroadcastDeviceInterfaceBuffer = IntPtr.Zero;
+            Int32 size = 0;
+
+            try
+            {
+                size = Marshal.SizeOf(devBroadcastDeviceInterface);
+                devBroadcastDeviceInterface.dbcc_size = size;
+                devBroadcastDeviceInterface.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE;
+                devBroadcastDeviceInterface.dbcc_reserved = 0;
+                devBroadcastDeviceInterface.dbcc_classguid = classGuid;
+                
+                // Allocate memory for the buffer that holds the DEV_BROADCAST_DEVICEINTERFACE structure.
+                devBroadcastDeviceInterfaceBuffer = Marshal.AllocHGlobal(size);
+
+                // Copy the DEV_BROADCAST_DEVICEINTERFACE structure to the buffer.
+                // Set fDeleteOld True to prevent memory leaks.
+                Marshal.StructureToPtr(devBroadcastDeviceInterface, devBroadcastDeviceInterfaceBuffer, true);
+
+                // ***
+                //  API function
+
+                //  summary
+                //  Request to receive notification messages when a device in an interface class
+                //  is attached or removed.
+
+                //  parameters 
+                //  Handle to the window that will receive device events.
+                //  Pointer to a DEV_BROADCAST_DEVICEINTERFACE to specify the type of 
+                //  device to send notifications for.
+                //  DEVICE_NOTIFY_WINDOW_HANDLE indicates the handle is a window handle.
+
+                //  Returns
+                //  Device notification handle or NULL on failure.
+                // ***
+
+                deviceNotificationHandle = RegisterDeviceNotification(formHandle, devBroadcastDeviceInterfaceBuffer, DEVICE_NOTIFY_WINDOW_HANDLE);
+
+                // Marshal data from the unmanaged block devBroadcastDeviceInterfaceBuffer to the managed object devBroadcastDeviceInterface
+                // why?
+                Marshal.PtrToStructure(devBroadcastDeviceInterfaceBuffer, devBroadcastDeviceInterface);
+
+                return deviceNotificationHandle.ToInt32() == IntPtr.Zero.ToInt32() ? false : true;
+            }
+            catch (Exception ex)
+            {
+                throw new Exception(ex.Message + Environment.NewLine + new System.Diagnostics.StackFrame().GetMethod().Name);
+            }
+            finally
+            {
+                // Free the memory allocated previously by AllocHGlobal.
+                if (devBroadcastDeviceInterfaceBuffer != IntPtr.Zero)
+                    Marshal.FreeHGlobal(devBroadcastDeviceInterfaceBuffer);                
+            }
+        }
+
+        ///  <summary>
+        ///  Requests to stop receiving notification messages when a device in an
+        ///  interface class is attached or removed.
+        ///  </summary>
+        ///  
+        ///  <param name="deviceNotificationHandle"> handle returned previously by
+        ///  RegisterDeviceNotification. </param>
+
+        public void StopReceivingDeviceNotifications(IntPtr deviceNotificationHandle)
+        {
+            try
+            {
+               UnregisterDeviceNotification(deviceNotificationHandle);
+            }
+            catch (Exception ex)
+            {
+                throw new Exception(ex.Message + Environment.NewLine + new System.Diagnostics.StackFrame().GetMethod().Name);
+            }
+        }
+
+        public Boolean DeviceIDMatch(Message m)
+        {
+            Int32 stringSize;
+
+            try
+            {
+                DEV_BROADCAST_HDR devBroadcastHeader = new DEV_BROADCAST_HDR(); 
+                DEV_BROADCAST_DEVICEINTERFACE_1 devBroadcastDeviceInterface = new DEV_BROADCAST_DEVICEINTERFACE_1();
+
+                // The LParam parameter of Message is a pointer to a DEV_BROADCAST_HDR structure.
+                Marshal.PtrToStructure(m.LParam, devBroadcastHeader);
+                if ((devBroadcastHeader.dbch_devicetype == DBT_DEVTYP_DEVICEINTERFACE))
+                {
+                    // The dbch_devicetype parameter indicates that the event applies to a device interface.
+                    // So the structure in LParam is actually a DEV_BROADCAST_INTERFACE structure, 
+                    // which begins with a DEV_BROADCAST_HDR.
+
+                    // Obtain the number of characters in dbch_name by subtracting the 32 bytes
+                    // in the strucutre that are not part of dbch_name and dividing by 2 because there are 
+                    // 2 bytes per character.
+
+                    stringSize = System.Convert.ToInt32((devBroadcastHeader.dbch_size - 32) / 2);
+
+                    // The dbcc_name parameter of devBroadcastDeviceInterface contains the device name. 
+                    // Trim dbcc_name to match the size of the String.         
+
+                    devBroadcastDeviceInterface.dbcc_name = new Char[stringSize + 1];
+
+                    // Marshal data from the unmanaged block pointed to by m.LParam 
+                    // to the managed object devBroadcastDeviceInterface.
+
+                    Marshal.PtrToStructure(m.LParam, devBroadcastDeviceInterface);
+
+                    // Store the device name in a String.
+
+                    String DeviceNameString = new String(devBroadcastDeviceInterface.dbcc_name, 0, stringSize);
+
+                    // Compare the name of the newly attached device with the name of the device 
+                    // the application is accessing (deviceID).
+                    // Set ignorecase True.
+
+                    return (DeviceNameString.ToLower().IndexOf(deviceID.ToLower()) == -1) ? false : true;
+                }
+                else
+                    return false;
+            }
+            catch (Exception ex)
+            {
+                throw new Exception(ex.Message + Environment.NewLine + new System.Diagnostics.StackFrame().GetMethod().Name);
+            }
+        }
+
+        public void reportID()
+        {
+            try
+            {
+                if (explicit_report_id)
+                    IOBuf[0] = SHORT_REPORT_ID;     // explicit out report ID in HID's descriptor
+                else
+                    IOBuf[0] = DEFAULT_REPORT_ID;   // default report ID; this byte is dropped in transfer, so we don't really waste a byte transmitting it
+            }
+            catch (Exception ex)
+            {
+                throw new Exception(ex.Message + Environment.NewLine + new System.Diagnostics.StackFrame().GetMethod().Name);
+            }
+        }
+
+        public int readI2C(byte deviceAddress, byte numDataBytes, byte numRegBytes, byte[] readData, byte[] reg, bool ignoreNACK = false)
+        {
+            //readData is passed back to caller with the read data
+            int status;
+            int i;
+
+            try
+            {
+                if (numDataBytes > REPORT_SIZE - 2) {
+                    throw new Exception("USB buffer overflow");
+                }
+
+                // verify: https://jira.maxim-ic.com/browse/OS24EVK-57 mutex lock HID.IOBuf[] in readI2C
+                mutexGuardIOBuf.WaitOne();   // Wait until it is safe to enter.
+                FlushQueue();
+                Array.Clear(IOBuf, 0, IOBuf.Length);
+
+                reportID();
+                IOBuf[1] = 6;	// I2C transaction -- see F3xx_USB0_ReportHandler.c void OUT_REPORT_HANDLER(int internalCall) 
+                IOBuf[2] = (byte)(deviceAddress | 1);     // set read bit
+                IOBuf[3] = numDataBytes;
+                IOBuf[4] = numRegBytes;
+                // TODO1: OS24EVK-57 HID readI2C no validation that numRegBytes == reg.Length ?
+                for (i = 0; i < numRegBytes; i++) {
+                    IOBuf[i + 5] = reg[i];
+                }
+
+                writeHID();
+                mutexGuardIOBuf.ReleaseMutex();    // Release the Mutex.
+
+                status = checkNACK();
+
+                // checkNACK also reads the data, assuming NACK didn't occur
+                if (status == I2C_NACK_ERROR && ignoreNACK == false) {
+                    throw new Exception("invalid I2C address");
+                }
+
+                for (i = 0; i < numDataBytes; i++) {
+                    readData[i] = IOBuf[i + 2];
+                }
+
+                return status;      // the caller will not need the return value if an exception is thrown
+            }
+            catch (Exception ex)
+            {
+                throw new Exception(ex.Message + Environment.NewLine + new System.Diagnostics.StackFrame().GetMethod().Name);
+            }
+        }
+
+        public void writeI2C(byte deviceAddress, byte numDataBytes, byte numRegBytes, byte[] data, byte[] reg, bool ignoreNACK = false)
+        {
+            int i;
+
+            try
+            {
+                if (numDataBytes > REPORT_SIZE - 5) {
+                    throw new Exception("USB buffer overflow");
+                }
+
+                // verify: https://jira.maxim-ic.com/browse/OS24EVK-57 mutex lock HID.IOBuf[] in writeI2C
+                mutexGuardIOBuf.WaitOne();   // Wait until it is safe to enter.
+                FlushQueue();
+                Array.Clear(IOBuf, 0, IOBuf.Length);
+
+                //send data to tell uC to do I2C read from slave
+                reportID();
+                IOBuf[1] = 6;	// I2C transaction -- see F3xx_USB0_ReportHandler.c void OUT_REPORT_HANDLER(int internalCall) 
+                IOBuf[2] = deviceAddress;
+                IOBuf[3] = numDataBytes;
+                IOBuf[4] = numRegBytes;
+                for (i = 0; i < numRegBytes; i++) {
+                    IOBuf[i + 5] = reg[i];
+                }
+                for (i = 0; i < numDataBytes; i++) {
+                    IOBuf[i + 5 + numRegBytes] = data[i];
+                }
+
+                writeHID();
+                mutexGuardIOBuf.ReleaseMutex();    // Release the Mutex.
+
+                if (checkNACK() == I2C_NACK_ERROR && ignoreNACK == false) {
+                    throw new Exception("invalid I2C address");
+                }
+            }
+            catch (Exception ex)
+            {
+                throw new Exception(ex.Message + Environment.NewLine + new System.Diagnostics.StackFrame().GetMethod().Name);
+            }
+        }
+
+        private int checkNACK()
+        {
+            // Check if I2C write was really succesful or a NACK occurred, since this is independent of USB success
+            // This function also reads all the data from the report. If NACK occured, the data is invalid.
+            try
+            {
+                readHID();
+                return (IOBuf[1] == 0 ? I2C_SUCCESS : I2C_NACK_ERROR);    // the caller will not need the return value if an exception is thrown
+            }
+            catch (Exception ex)
+            {
+                throw new Exception(ex.Message + Environment.NewLine + new System.Diagnostics.StackFrame().GetMethod().Name);
+            }
+        }
+
+        // only allows 2 byte data
+        public void setBitI2C(byte deviceAddress, int reg, byte range, int data, bool ignoreNACK = false)
+        {
+            int i;
+            
+            try
+            {
+                int LSb = range & 0xF;
+                int MSb = (range & 0xF0) >> 4;
+                if (MSb < LSb)
+                    throw new Exception("invalid bit range");
+                //if (numDataBytes > REPORT_SIZE - 5)
+                //    throw new Exception("USB buffer overflow");
+
+                // verify: https://jira.maxim-ic.com/browse/OS24EVK-57 mutex lock HID.IOBuf[] in setBitI2C
+                mutexGuardIOBuf.WaitOne();   // Wait until it is safe to enter.
+                FlushQueue();
+
+                Array.Clear(IOBuf, 0, IOBuf.Length);
+
+                //send data to tell uC to do I2C read from slave
+                reportID();
+                IOBuf[1] = 6;	// I2C transaction -- see F3xx_USB0_ReportHandler.c void OUT_REPORT_HANDLER(int internalCall) 
+                IOBuf[2] = deviceAddress;
+                byte numDataBytes = (byte)(MSb > 7 ? 2 : 1);
+                IOBuf[3] = numDataBytes;
+                byte numRegBytes = (byte)Math.Ceiling(reg / 255.0);
+                IOBuf[4] = numRegBytes;
+                for (i = 0; i < numRegBytes; i++)                
+                    IOBuf[i + 5] = (byte)((reg>>(8*i)) & 0xFF);                
+                //for (i = 0; i < numDataBytes; i++)
+                //    IOBuf[i + 5 + numRegBytes] = data[i];
+
+                writeHID();
+                mutexGuardIOBuf.ReleaseMutex();    // Release the Mutex.
+
+                if (checkNACK() == I2C_NACK_ERROR && ignoreNACK == false)
+                    throw new Exception("invalid I2C address");
+            }
+            catch (Exception ex)
+            {
+                throw new Exception(ex.Message + Environment.NewLine + new System.Diagnostics.StackFrame().GetMethod().Name);
+            }
+        }
+
+        /// <summary>
+        /// <para>Firmware command code 0 IN = Firmware version</para>
+        /// 
+        /// </summary>
+        /// <param name="VerMajor"></param>
+        /// <param name="VerMinor"></param>
+        /// <param name="verYearHundreds"></param>
+        /// <param name="verYear"></param>
+        /// <param name="verMonth"></param>
+        /// <param name="verDay"></param>
+        public void FirmwareVersion(out byte VerMajor, out byte VerMinor, out byte verYearHundreds, out byte verYear, out byte verMonth, out byte verDay)
+        {
+            if (FirmwareINT0Enabled != 0)
+            {
+                // firmware is busy streaming out HID reports,
+                // so return a previously retrieved firmware version.
+                VerMajor = _VerMajor;
+                VerMinor = _VerMinor;
+                verYearHundreds = _verYearHundreds;
+                verYear = _verYear;
+                verMonth = _verMonth;
+                verDay = _verDay;
+                return;
+            }
+            // https://jira.maxim-ic.com/browse/OS24EVK-24 Refactor: HID report enum and wrappers
+            // verify: https://jira.maxim-ic.com/browse/OS24EVK-57 mutex lock HID.IOBuf[] in FirmwareVersion
+            mutexGuardIOBuf.WaitOne();   // Wait until it is safe to enter.
+            FlushQueue();
+            Array.Clear(IOBuf, 0, IOBuf.Length);
+            reportID();
+            IOBuf[1] = 0; // Firmware version -- see F3xx_USB0_ReportHandler.c void OUT_REPORT_HANDLER(int internalCall) 
+            writeReadHID();
+            VerMajor = IOBuf[2];
+            VerMinor = IOBuf[3];
+            verYearHundreds = IOBuf[4];
+            verYear = IOBuf[5];
+            verMonth = IOBuf[6];
+            verDay = IOBuf[7];
+            //
+            // save the recently read values
+            _VerMajor = VerMajor;
+            _VerMinor = VerMinor;
+            _verYearHundreds = verYearHundreds;
+            _verYear = verYear;
+            _verMonth = verMonth;
+            _verDay = verDay;
+            mutexGuardIOBuf.ReleaseMutex();    // Release the Mutex.
+        }
+        private byte _VerMajor = 0;
+        private byte _VerMinor = 0;
+        private byte _verYearHundreds = 0;
+        private byte _verYear = 0;
+        private byte _verMonth = 0;
+        private byte _verDay = 0;
+
+        /// <summary>
+        /// <para>Firmware command code 1 OUT = LED (C51F321 P2.2=red, P2.1=green) </para>
+        /// 
+        /// </summary>
+        /// <param name="xxxxxxP22P21">0x02=P2.2 Red, 0x01=P2.1 Green</param>
+        public void LEDSet(byte xxxxxxP22P21)
+        {
+            // https://jira.maxim-ic.com/browse/OS24EVK-24 Refactor: HID report enum and wrappers LEDSet(byte xxxxxxP22P21)
+            // verify: https://jira.maxim-ic.com/browse/OS24EVK-57 mutex lock HID.IOBuf[] in LEDSet
+            mutexGuardIOBuf.WaitOne();   // Wait until it is safe to enter.
+            FlushQueue();
+            Array.Clear(IOBuf, 0, IOBuf.Length);
+            reportID();
+            IOBuf[1] = 1; // case (1): //LED (C51F321 P2.2=red, P2.1=green) -- see F3xx_USB0_ReportHandler.c void OUT_REPORT_HANDLER(int internalCall) 
+            IOBuf[2] = 0; //    case (0):	// write
+            IOBuf[3] = xxxxxxP22P21; 
+            // Led2 = IO_BUFFER.Ptr[2+gOffset] & 1; // sbit Led2 = P2^1;
+            // Led1 = (IO_BUFFER.Ptr[2+gOffset] & 2) >> 1; // sbit Led1 = P2^2;
+            writeHID();
+            mutexGuardIOBuf.ReleaseMutex();    // Release the Mutex.
+        }
+
+        /// <summary>
+        /// <para>Firmware command code 1 IN = GPIOP0Get read I/O pins P0.6, P0.7</para>
+        /// 
+        /// </summary>
+        /// <param name="xxxxxxP06P07"></param>
+        public void GPIOP0Get(out byte xxxxxxP06P07)
+        {
+            // todo: verify: https://jira.maxim-ic.com/browse/OS24EVK-24 Refactor: HID report enum and wrappers GPIOP0Get(out byte xxxxxxP06P07)
+            // https://jira.maxim-ic.com/browse/OS24EVK-24 Refactor: Rename LEDGet(out byte xxxxxxP06P07) to GPIOP0Get(out byte xxxxxxP06P07)
+            // verify: https://jira.maxim-ic.com/browse/OS24EVK-57 mutex lock HID.IOBuf[] in GPIOP0Get
+            mutexGuardIOBuf.WaitOne();   // Wait until it is safe to enter.
+            FlushQueue();
+            Array.Clear(IOBuf, 0, IOBuf.Length);
+            reportID();
+            IOBuf[1] = 1; // case (1): //LED (C51F321 P2.2=red, P2.1=green) -- see F3xx_USB0_ReportHandler.c void OUT_REPORT_HANDLER(int internalCall) 
+            IOBuf[2] = 1; //    case (1):	// read
+            writeReadHID();
+            // IO_BUFFER.Ptr[0] = SHORT_REPORT_ID;
+            // IO_BUFFER.Ptr[0 + gOffset] = 0; // error status
+            // IO_BUFFER.Ptr[1 + gOffset] = ((P0 & 0x80) >> 7) + ((P0 & 0x40) >> 5);
+            xxxxxxP06P07 = IOBuf[2];
+            mutexGuardIOBuf.ReleaseMutex();    // Release the Mutex.
+        }
+
+        /// <summary>
+        /// <para>Firmware command code 2 OUT = GPIO configuration (C51F321 P1 and P2) </para>
+        /// 
+        /// </summary>
+        /// <param name="P1MDOUT"></param>
+        /// <param name="P2MDOUT"></param>
+        /// <param name="weakPullupDisable"></param>
+        public void GPIOP1P2ConfigSet(byte P1MDOUT, byte P2MDOUT, byte weakPullupDisable)
+        {
+            // verify: https://jira.maxim-ic.com/browse/OS24EVK-24 Refactor: HID report enum and wrappers GPIOP1P2ConfigSet(byte P1MDOUT, byte P2MDOUT, byte weakPullupDisable)
+            // verify: https://jira.maxim-ic.com/browse/OS24EVK-57 mutex lock HID.IOBuf[] in GPIOP1P2ConfigSet
+            mutexGuardIOBuf.WaitOne();   // Wait until it is safe to enter.
+            FlushQueue();
+            Array.Clear(IOBuf, 0, IOBuf.Length);
+            reportID();
+            IOBuf[1] = 2; // case (2): //GPIO configuration (C51F321 P1 and P2) -- see F3xx_USB0_ReportHandler.c void OUT_REPORT_HANDLER(int internalCall) 
+            IOBuf[2] = 0; //    case (0):	// write
+            IOBuf[3] = P1MDOUT; // P1MDOUT = IO_BUFFER.Ptr[2+gOffset];	// P1 push-pull (1) or open-collector (0)
+            IOBuf[4] = P2MDOUT; // P2MDOUT = IO_BUFFER.Ptr[3 + gOffset];	// P2 push-pull (1) or open-collector (0)
+            IOBuf[5] = weakPullupDisable; // (IO_BUFFER.Ptr[4 + gOffset] & 1) ? (XBR1 |= 0x80) : (XBR1 &= 0x7F);	// weak pull up disable (open collector only); 1 disabled, 0 enabled
+            writeHID();
+            mutexGuardIOBuf.ReleaseMutex();    // Release the Mutex.
+        }
+
+        /// <summary>
+        /// <para>Firmware command code 2 IN = GPIO configuration (C51F321 P1 and P2) </para>
+        /// 
+        /// </summary>
+        /// <param name="P1MDOUT"></param>
+        /// <param name="P2MDOUT"></param>
+        /// <param name="weakPullupDisable"></param>
+        public void GPIOP1P2ConfigGet(out byte P1MDOUT, out byte P2MDOUT, out byte weakPullupDisable)
+        {
+            // verify: https://jira.maxim-ic.com/browse/OS24EVK-24 Refactor: HID report enum and wrappers GPIOP1P2ConfigGet(out byte P1MDOUT, out byte P2MDOUT, out byte weakPullupDisable)
+            // verify: https://jira.maxim-ic.com/browse/OS24EVK-57 mutex lock HID.IOBuf[] in GPIOP1P2ConfigGet
+            mutexGuardIOBuf.WaitOne();   // Wait until it is safe to enter.
+            FlushQueue();
+            Array.Clear(IOBuf, 0, IOBuf.Length);
+            reportID();
+            IOBuf[1] = 2; // case (2): //GPIO configuration (C51F321 P1 and P2) -- see F3xx_USB0_ReportHandler.c void OUT_REPORT_HANDLER(int internalCall) 
+            IOBuf[2] = 1; //    case (1):	// read
+            writeReadHID();
+            // IO_BUFFER.Ptr[0] = SHORT_REPORT_ID;
+            // IO_BUFFER.Ptr[0 + gOffset] = 0; // error status					
+            // IO_BUFFER.Ptr[1 + gOffset] = P1MDOUT;	// P1 push-pull (1) or open-collector (0)
+            // IO_BUFFER.Ptr[2 + gOffset] = P2MDOUT;	// P2 push-pull (1) or open-collector (0)
+            // IO_BUFFER.Ptr[3 + gOffset] = (XBR1 & 0x80) >> 7; // weakPullupDisable
+            P1MDOUT = IOBuf[2];
+            P2MDOUT = IOBuf[3];
+            weakPullupDisable = IOBuf[4];
+            mutexGuardIOBuf.ReleaseMutex();    // Release the Mutex.
+        }
+
+        /// <summary>
+        /// <para>Firmware command code 3 OUT = GPIO value (C51F321 P1 and P2) </para>
+        /// 
+        /// </summary>
+        /// <param name="P1"></param>
+        /// <param name="P2"></param>
+        public void GPIOP1P2Out(byte P1, byte P2)
+        {
+            // verify: https://jira.maxim-ic.com/browse/OS24EVK-24 Refactor: HID report enum and wrappers GPIOP1P2Out(byte P1, byte P2)
+            // verify: https://jira.maxim-ic.com/browse/OS24EVK-57 mutex lock HID.IOBuf[] in GPIOP1P2Out
+            mutexGuardIOBuf.WaitOne();   // Wait until it is safe to enter.
+            FlushQueue();
+            Array.Clear(IOBuf, 0, IOBuf.Length);
+            reportID();
+            IOBuf[1] = 3; // case (3): //GPIO value (C51F321 P1 and P2) -- see F3xx_USB0_ReportHandler.c void OUT_REPORT_HANDLER(int internalCall) 
+            IOBuf[2] = 0; //    case (0):	// write
+            IOBuf[3] = P1; // P1 = IO_BUFFER.Ptr[2 + gOffset];		// P1 HI (1) or LO (0); set P1==1 and P1MDOUT==1 for HI-Z
+            IOBuf[4] = P2; // P2 = IO_BUFFER.Ptr[3 + gOffset];		// P2 HI (1) or LO (0); set P2==1 and P1MDOUT==2 for HI-Z
+            writeHID();
+            mutexGuardIOBuf.ReleaseMutex();    // Release the Mutex.
+        }
+
+        /// <summary>
+        /// <para>Firmware command code 3 IN = GPIO value (C51F321 P1 and P2) </para>
+        /// 
+        /// </summary>
+        /// <param name="P1"></param>
+        /// <param name="P2"></param>
+        public void GPIOP1P2In(out byte P1, out byte P2)
+        {
+            // verify: https://jira.maxim-ic.com/browse/OS24EVK-24 Refactor: HID report enum and wrappers GPIOP1P2In(out byte P1, out byte P2)
+            // verify: https://jira.maxim-ic.com/browse/OS24EVK-57 mutex lock HID.IOBuf[] in GPIOP1P2In
+            mutexGuardIOBuf.WaitOne();   // Wait until it is safe to enter.
+            FlushQueue();
+            Array.Clear(IOBuf, 0, IOBuf.Length);
+            reportID();
+            IOBuf[1] = 3; // case (3): //GPIO value (C51F321 P1 and P2) -- see F3xx_USB0_ReportHandler.c void OUT_REPORT_HANDLER(int internalCall) 
+            IOBuf[2] = 1; //    case (1):	// read
+            writeReadHID();
+            // temp = XBR1;
+            // if (IO_BUFFER.Ptr[2+gOffset] & 1)	// enable weak pullups in case GP pins are open-collector and not connected to anything (which would falsely give '0')
+            // {
+            // 	XBR1 &= 0x7F;
+            // 	Timer0_Init(HALFMS);
+            // 	T0_Wait(2);
+            // }
+            // IO_BUFFER.Ptr[0] = SHORT_REPORT_ID;
+            // IO_BUFFER.Ptr[0+gOffset] = 0; 		// error status
+            // IO_BUFFER.Ptr[1+gOffset] = P1;		// P1 HI (1) or LO (0)
+            // IO_BUFFER.Ptr[2+gOffset] = P2;		// P2 HI (1) or LO (0)
+            // XBR1 = temp;
+            // SendPacket(); // no need to check for internal call since only the GUI will request a read through this function
+            P1 = IOBuf[2];
+            P2 = IOBuf[3];
+            mutexGuardIOBuf.ReleaseMutex();    // Release the Mutex.
+        }
+
+        /// <summary>
+        /// <para>Firmware command code 4 OUT = I2C configuration </para>
+        ///  (IO_BUFFER.Ptr[3+gOffset] &amp; 1) ? (SMB0CF |= 0x10) : (SMB0CF &amp;= 0xEF)
+        /// </summary>
+        /// <param name="gI2Cflags">bit0 == 1: repeated start</param>
+        /// <param name="EXTHOLD">set EXTHOLD bit (SMBus setup / hold time extension)</param>
+        /// <param name="ClearSDAbyTogglingSCL">clear SDA by toggling SCL</param>
+        public void I2CConfigSet(byte gI2Cflags, byte EXTHOLD, byte ClearSDAbyTogglingSCL)
+        {
+            // verify: https://jira.maxim-ic.com/browse/OS24EVK-24 Refactor: HID report enum and wrappers I2CConfigSet(byte gI2Cflags, byte EXTHOLD, byte ClearSDAbyTogglingSCL)
+            // verify: https://jira.maxim-ic.com/browse/OS24EVK-57 mutex lock HID.IOBuf[] in I2CConfigSet
+            mutexGuardIOBuf.WaitOne();   // Wait until it is safe to enter.
+            FlushQueue();
+            Array.Clear(IOBuf, 0, IOBuf.Length);
+            reportID();
+            IOBuf[1] = 4; // case (4): //I2C configuration -- see F3xx_USB0_ReportHandler.c void OUT_REPORT_HANDLER(int internalCall) 
+            IOBuf[2] = 0; //    case (0):	// write
+            IOBuf[3] = gI2Cflags;   // gI2Cflags = IO_BUFFER.Ptr[2+gOffset];
+                                    // // bit0 == 1: repeated start (versus stop/start) after write before read (applies to random read only)
+                                    // // bit1 == 1: start random read with a write, but end the write right away without sending reg address (emulate Jungo dongle for debug purposes)
+                                    // // bit2 == 1: repeat transaction if slave NACKs (suggest not to use this)
+                                    // // all flags are OR'd
+            IOBuf[4] = EXTHOLD;    // (IO_BUFFER.Ptr[3+gOffset] & 1) ? (SMB0CF |= 0x10) : (SMB0CF &= 0xEF);	// set EXTHOLD bit (SMBus setup / hold time extension)
+            IOBuf[5] = ClearSDAbyTogglingSCL;   // if (IO_BUFFER.Ptr[4+gOffset] & 1)	// clear SDA by toggling SCL
+                                // {s
+                                // 	IO_BUFFER.Ptr[0] = SHORT_REPORT_ID;
+                                // 	IO_BUFFER.Ptr[0+gOffset] = 0; 	// transaction error status
+                                // 	IO_BUFFER.Ptr[1+gOffset] = clearSDA();	// clearSDA error status
+                                // 	SendPacket();			// send status of clearing SDA to host
+                                // }
+            writeHID();
+            mutexGuardIOBuf.ReleaseMutex();    // Release the Mutex.
+        }
+
+        /// <summary>
+        /// <para>Firmware command code 4 IN = I2C configuration </para>
+        /// (IO_BUFFER.Ptr[3+gOffset] &amp; 1) ? (SMB0CF |= 0x10) : (SMB0CF &amp;= 0xEF)
+        /// </summary>
+        /// <param name="gI2Cflags">bit0 == 1: repeated start</param>
+        /// <param name="EXTHOLD">SMB0CF &amp; 0x10</param>
+        public void I2CConfigGet(out byte gI2Cflags, out byte EXTHOLD)
+        {
+            // verify: https://jira.maxim-ic.com/browse/OS24EVK-24 Refactor: HID report enum and wrappers I2CConfigGet(out byte gI2Cflags, out byte EXTHOLD)
+            // verify: https://jira.maxim-ic.com/browse/OS24EVK-57 mutex lock HID.IOBuf[] in I2CConfigGet
+            mutexGuardIOBuf.WaitOne();   // Wait until it is safe to enter.
+            FlushQueue();
+            Array.Clear(IOBuf, 0, IOBuf.Length);
+            reportID();
+            IOBuf[1] = 4; // case (4): //I2C configuration -- see F3xx_USB0_ReportHandler.c void OUT_REPORT_HANDLER(int internalCall) 
+            IOBuf[2] = 1; //    case (1):	// read
+            writeReadHID();
+            // IO_BUFFER.Ptr[0] = SHORT_REPORT_ID;
+            // IO_BUFFER.Ptr[0+gOffset] = 0; // error status					
+            // IO_BUFFER.Ptr[1+gOffset] = gI2Cflags;
+            // IO_BUFFER.Ptr[2+gOffset] = (SMB0CF & 0x10) >> 4; // EXTHOLD
+            gI2Cflags = IOBuf[2];
+            EXTHOLD = IOBuf[3];
+            mutexGuardIOBuf.ReleaseMutex();    // Release the Mutex.
+        }
+
+        /// <summary>
+        /// <para>Firmware command code 5 OUT = I2C clock rate (number of counts to overflow) </para>
+        /// <para>SCL_kHz = TimerClockMHz * 1000 / ReloadTH1</para>
+        /// </summary>
+        /// <param name="ReloadTH1">SMBus timer's count value: ReloadTH1 = (byte)(0.5 + (TimerClockMHz * 1000 / SCL_kHz))</param>
+        public void I2CClockSet(byte ReloadTH1)
+        {
+            // verify: https://jira.maxim-ic.com/browse/OS24EVK-24 Refactor: HID report enum and wrappers I2CClockSet(byte ReloadTH1)
+            // verify: https://jira.maxim-ic.com/browse/OS24EVK-57 mutex lock HID.IOBuf[] in I2CClockSet
+            mutexGuardIOBuf.WaitOne();   // Wait until it is safe to enter.
+            FlushQueue();
+            Array.Clear(IOBuf, 0, IOBuf.Length);
+            reportID();
+            IOBuf[1] = 5; // case (5): //I2C clock rate (number of counts to overflow) -- see F3xx_USB0_ReportHandler.c void OUT_REPORT_HANDLER(int internalCall) 
+            IOBuf[2] = 0; //    case (0):	// write
+            IOBuf[3] = ReloadTH1;
+            // gSMBusClkFreq = gTimer1ClkFreq / 3.0 / IO_BUFFER.Ptr[2+gOffset];	//GUI sends the number of counts to overflow; HID must calculate the desired SMBus clock frequency
+            // TR1 = 0;
+            // Timer1_Init();
+            writeHID();
+            mutexGuardIOBuf.ReleaseMutex();    // Release the Mutex.
+        }
+
+        /// <summary>
+        /// <para>Firmware command code 5 IN = I2C clock rate (number of counts to overflow) </para>
+        /// <para>SCL_kHz = TimerClockMHz * 1000 / ReloadTH1</para>
+        /// </summary>
+        /// <param name="TimerClockMHz">SMBus timer's clock frequency (in MHz); expect constant 8</param>
+        /// <param name="ReloadTH1">SMBus timer's count value: SCL_kHz = TimerClockMHz * 1000 / ReloadTH1</param>
+        public void I2CClockGet(out byte TimerClockMHz, out byte ReloadTH1)
+        {
+            // verify: https://jira.maxim-ic.com/browse/OS24EVK-24 Refactor: HID report enum and wrappers I2CClockGet(out byte TimerClockMHz, out byte ReloadTH1)
+            // verify: https://jira.maxim-ic.com/browse/OS24EVK-57 mutex lock HID.IOBuf[] in I2CClockGet
+            mutexGuardIOBuf.WaitOne();   // Wait until it is safe to enter.
+            FlushQueue();
+            Array.Clear(IOBuf, 0, IOBuf.Length);
+            reportID();
+            IOBuf[1] = 5; // case (5): //I2C clock rate (number of counts to overflow) -- see F3xx_USB0_ReportHandler.c void OUT_REPORT_HANDLER(int internalCall) 
+            IOBuf[2] = 1; //    case (1):	// read
+            writeReadHID();
+            // case (1): 	// read -- myHID.I2CClockGet(out TimerClockMHz, out ReloadTH1)
+            // IO_BUFFER.Ptr[0] = SHORT_REPORT_ID;
+            // IO_BUFFER.Ptr[0+gOffset] = 0; // error status
+            // IO_BUFFER.Ptr[1+gOffset] = gTimer1ClkFreq / 1000000 / 3;	//return the SMBus timer's clock frequency (in MHz)
+            // IO_BUFFER.Ptr[2+gOffset] = 256-TH1;						//and return the SMBus timer's count value in order to calculate the SMBus clock frequency; TH1 is the reload value that gets loaded into TL0 upon overflow; the reload value is 256-TH1 since (0)-TH1 gives the proper number of counts to overflow
+            // SendPacket(); // no need to check for internal call since only the GUI will request a read through this function
+            // break;
+            TimerClockMHz = IOBuf[2];
+            ReloadTH1 = IOBuf[3];
+            // todo: OS24EVK-24 how determine SCL from TimerClockMHZ? Observed I2CClockGet() TimerClockMHz = 8 when SCL = 400kHz.
+            mutexGuardIOBuf.ReleaseMutex();    // Release the Mutex.
+        }
+
+        /// <summary>
+        /// <para>Firmware command code 6 OUT = I2C transaction </para>
+        /// 
+        /// </summary>
+        /// <param name="deviceAddress">I2C device address, 8-bit left-justified (LSB=R/w bit)</param>
+        /// <param name="numDataBytes"></param>
+        /// <param name="numRegBytes"></param>
+        /// <param name="data"></param>
+        /// <param name="reg"></param>
+        /// <param name="ignoreNACK"></param>
+        public void I2CWrite(byte deviceAddress, byte numDataBytes, byte numRegBytes, byte[] data, byte[] reg, bool ignoreNACK = false)
+        {
+            // https://jira.maxim-ic.com/browse/OS24EVK-24 Refactor: HID report enum and wrappers
+            // alias of existing function
+            // IOBuf[1] = 6; // case (6):	// I2C transaction -- HID.cs void writeI2C() readI2C() -- see F3xx_USB0_ReportHandler.c void OUT_REPORT_HANDLER(int internalCall) 
+            writeI2C(deviceAddress, numDataBytes, numRegBytes, data, reg, ignoreNACK);
+        }
+
+        /// <summary>
+        /// <para>Firmware command code 6 IN = I2C transaction </para>
+        /// 
+        /// </summary>
+        /// <param name="deviceAddress">I2C device address, 8-bit left-justified (LSB=R/w bit)</param>
+        /// <param name="numDataBytes"></param>
+        /// <param name="numRegBytes"></param>
+        /// <param name="readData"></param>
+        /// <param name="reg"></param>
+        /// <param name="ignoreNACK"></param>
+        /// <returns>status value; may be HID.I2C_NACK_ERROR if ignoreNACK parameter is true</returns>
+        public int I2CRead(byte deviceAddress, byte numDataBytes, byte numRegBytes, byte[] readData, byte[] reg, bool ignoreNACK = false)
+        {
+            // https://jira.maxim-ic.com/browse/OS24EVK-24 Refactor: HID report enum and wrappers
+            // alias of existing function
+            // IOBuf[1] = 6; // case (6):	// I2C transaction -- HID.cs void writeI2C() readI2C() -- see F3xx_USB0_ReportHandler.c void OUT_REPORT_HANDLER(int internalCall) 
+            return readI2C(deviceAddress, numDataBytes, numRegBytes, readData, reg, ignoreNACK);
+        }
+
+        /// <summary>
+        /// <para>Firmware command code 7 OUT = SPI config </para>
+        /// ((SPI0CFG &amp; 0x30) &gt;&gt; 4) + (SPI0CN &amp; 4)
+        /// </summary>
+        /// <param name="config"></param>
+        public void SPIConfigSet(byte config)
+        {
+            // todo: https://jira.maxim-ic.com/browse/OS24EVK-24 Refactor: HID report enum and wrappers SPIConfigSet(byte config)
+            // Although the MAX30101EVKIT firmware will accept HID SPI commands, this firmware doesn't support SPI interface.
+            // IOBuf[1] = 7; // case (7):	// SPI config -- HID.cs void writeI2C() readI2C() -- see F3xx_USB0_ReportHandler.c void OUT_REPORT_HANDLER(int internalCall) 
+        }
+
+        /// <summary>
+        /// <para>Firmware command code 7 IN = SPI config </para>
+        /// ((SPI0CFG &amp; 0x30) &gt;&gt; 4) + (SPI0CN &amp; 4)
+        /// </summary>
+        /// <param name="config"></param>
+        public void SPIConfigGet(out byte config)
+        {
+            // todo: https://jira.maxim-ic.com/browse/OS24EVK-24 Refactor: HID report enum and wrappers SPIConfigGet(out byte config)
+            // Although the MAX30101EVKIT firmware will accept HID SPI commands, this firmware doesn't support SPI interface.
+            // IOBuf[1] = 7; // case (7):	// SPI config -- HID.cs void writeI2C() readI2C() -- see F3xx_USB0_ReportHandler.c void OUT_REPORT_HANDLER(int internalCall) 
+            config = 0;
+        }
+
+        /// <summary>
+        /// <para>Firmware command code 8 OUT = SPI clock rate </para>
+        /// </summary>
+        /// <param name="SPI0CKR"></param>
+        public void SPIClockSet(byte SPI0CKR)
+        {
+            // todo: https://jira.maxim-ic.com/browse/OS24EVK-24 Refactor: HID report enum and wrappers SPIClockSet(byte SPI0CKR)
+            // Although the MAX30101EVKIT firmware will accept HID SPI commands, this firmware doesn't support SPI interface.
+            // IOBuf[1] = 8; // case (8): 	// SPI clock rate -- see F3xx_USB0_ReportHandler.c void OUT_REPORT_HANDLER(int internalCall) 
+        }
+
+        /// <summary>
+        /// <para>Firmware command code 8 IN = SPI clock rate </para>
+        /// </summary>
+        /// <param name="SPI0CKR"></param>
+        public void SPIClockGet(out byte SPI0CKR)
+        {
+            // todo: https://jira.maxim-ic.com/browse/OS24EVK-24 Refactor: HID report enum and wrappers SPIClockGet(out byte SPI0CKR)
+            // Although the MAX30101EVKIT firmware will accept HID SPI commands, this firmware doesn't support SPI interface.
+            // IOBuf[1] = 8; // case (8): 	// SPI clock rate -- see F3xx_USB0_ReportHandler.c void OUT_REPORT_HANDLER(int internalCall) 
+            SPI0CKR = 0;
+        }
+
+        /// <summary>
+        /// <para>Firmware command code 9 = SPI transaction </para>
+        /// </summary>
+        /// <param name="mosiData">SPI MOSI (Master-Out, Slave-In) data to write into slave device</param>
+        /// <param name="misoBuffer">SPI MISO (Master-In, Slave-Out) data buffer containing data bytes received from slave device
+        /// (size will be allocated same size as mosiData)</param>
+        public void SPITransfer(byte[] mosiData, out byte[] misoBuffer)
+        {
+            // verify: https://jira.maxim-ic.com/browse/OS24EVK-24 SPITransfer(byte[] mosiData, out byte[] misoBuffer)
+            // Although the MAX30101EVKIT firmware will accept HID SPI commands, this firmware doesn't support SPI interface.
+            // verify: https://jira.maxim-ic.com/browse/OS24EVK-57 mutex lock HID.IOBuf[] in I2CConfigSet
+            mutexGuardIOBuf.WaitOne();   // Wait until it is safe to enter.
+            FlushQueue();
+            Array.Clear(IOBuf, 0, IOBuf.Length);
+            reportID();
+            // assign default out values in case of failure
+            int byteCount = mosiData.Length;
+            byte num_bytes = (byte)(byteCount & 0xFF);
+            misoBuffer = new byte[byteCount];
+            for (int byteIndex = 0; byteIndex < byteCount; byteIndex++)
+            {
+                // initial dummy data
+                misoBuffer[byteIndex] = 0x55;
+            }
+            IOBuf[1] = 9; // case (9):	// SPI transaction -- see F3xx_USB0_ReportHandler.c void OUT_REPORT_HANDLER(int internalCall) 
+            //IOBuf[8] = x; // IO_BUFFER.Ptr[7+gOffset] -- first byte of data starts on the (7 + offset) byte
+            for (uint byteIndex = 0; byteIndex < num_bytes; byteIndex++)
+            {
+                IOBuf[8 + byteIndex] = (byte)(mosiData[byteIndex]);
+            }
+            //switch (SPImode)
+            //{
+            //    case 0:
+                    IOBuf[2] = 0; // IO_BUFFER.Ptr[1+gOffset] -- 0 for SPI_mode0: multi-byte SPI transfer.
+                    IOBuf[3] = 0; // IO_BUFFER.Ptr[2+gOffset] -- not used
+                    IOBuf[4] = 0; // IO_BUFFER.Ptr[3+gOffset] -- phase_change // !=0 enable changing the clock phase. some slaves change phase between write/read
+                    IOBuf[5] = 0; // IO_BUFFER.Ptr[4+gOffset] -- phase_change_byte // byte index where phase change should happen
+                    IOBuf[6] = num_bytes; // IO_BUFFER.Ptr[5+gOffset] -- num_bytes
+                    IOBuf[7] = 0; // IO_BUFFER.Ptr[6+gOffset] -- not used
+                    // IO_BUFFER.Ptr[7+gOffset] -- first byte of data starts on the (7 + offset) byte
+                    // SPI_mode0(IO_BUFFER.Ptr[3 + gOffset], IO_BUFFER.Ptr[4 + gOffset], IO_BUFFER.Ptr[5 + gOffset], IO_BUFFER.Ptr);
+                //    break;
+                //case 1:
+                //    IOBuf[2] = 1; // IO_BUFFER.Ptr[1+gOffset] -- 1 for SPI_mode1: two-byte SPI transfer. read flag: enable changing the clock phase on first byte and changing phase between first and second byte
+                //    IOBuf[3] = 0; // IO_BUFFER.Ptr[2+gOffset] -- read flag
+                //    // IO_BUFFER.Ptr[3+gOffset] -- not used
+                //    // IO_BUFFER.Ptr[4+gOffset] -- not used
+                //    // IO_BUFFER.Ptr[5+gOffset] -- not used; num_bytes = 2
+                //    // IO_BUFFER.Ptr[6+gOffset] -- not used
+                //    // IO_BUFFER.Ptr[7+gOffset] -- first byte of data starts on the (7 + offset) byte
+                //    // SPI_mode1(temp, IO_BUFFER.Ptr);
+                //    break;
+                //case 2:
+                //    IOBuf[2] = 2; // IO_BUFFER.Ptr[1+gOffset] --2 for SPI_mode2: two-byte SPI transfer. read flag: enable changing the clock phase on first byte and sampling the LSb after the second byte read
+                //    IOBuf[3] = 0; // IO_BUFFER.Ptr[2+gOffset] -- read flag
+                //    // IO_BUFFER.Ptr[3+gOffset] -- not used
+                //    // IO_BUFFER.Ptr[4+gOffset] -- not used
+                //    // IO_BUFFER.Ptr[5+gOffset] -- not used; num_bytes = 2
+                //    // IO_BUFFER.Ptr[6+gOffset] -- not used
+                //    // IO_BUFFER.Ptr[7+gOffset] -- first byte of data starts on the (7 + offset) byte
+                //    // SPI_mode2(temp, IO_BUFFER.Ptr);
+                //    break;
+            //}
+            writeHID();
+            // IO_BUFFER.Ptr[0] = SHORT_REPORT_ID;
+            // IO_BUFFER.Ptr[0+gOffset] = 0; // error status					
+            // IO_BUFFER.Ptr[1+gOffset] = gI2Cflags;
+            // IO_BUFFER.Ptr[2+gOffset] = (SMB0CF & 0x10) >> 4; // EXTHOLD
+            //gI2Cflags = IOBuf[2];
+            //EXTHOLD = IOBuf[3];
+            for (uint byteIndex = 0; byteIndex < byteCount; byteIndex++)
+            {
+                misoBuffer[byteIndex] = IOBuf[byteIndex + 2];
+            }
+            mutexGuardIOBuf.ReleaseMutex();    // Release the Mutex.
+        }
+
+        /// <summary>
+        /// <para>Firmware command code 23 OUT = enable INT0 (or Mock HID FIFO data diagnostic) </para>
+        /// <para>
+        /// - INT0Enable(0) disabled (EX0=0)
+        /// - INT0Enable(1) real hardware (EX0=1)
+        /// - INT0Enable(2) Mock HID x1 channel    101, 102, 103, ...
+        /// - INT0Enable(3) Mock HID x2 channels   101, 201, 102, 202, 103, 203, ...
+        /// - INT0Enable(4) Mock HID x3 channels   101, 201, 301, 102, 202, 302, 103, 203, 303, ...
+        /// - INT0Enable(5) Mock HID x4 channels   101, 201, 301, 401, 102, 202, 302, 402, 103, 203, 303, 403, ...
+        /// </para>
+        /// </summary>
+        /// <param name="EX0"></param>
+        public void INT0Enable(byte EX0)
+        {
+            // https://jira.maxim-ic.com/browse/OS24EVK-24 Refactor: HID report enum and wrappers
+            // reset report counter in the HID and enable INT0
+            // verify: https://jira.maxim-ic.com/browse/OS24EVK-57 mutex lock HID.IOBuf[] in INT0Enable
+            mutexGuardIOBuf.WaitOne();   // Wait until it is safe to enter.
+            FlushQueue();
+            Array.Clear(IOBuf, 0, IOBuf.Length);
+            reportID();
+            IOBuf[1] = 23; // enable INT0 -- see F3xx_USB0_ReportHandler.c void OUT_REPORT_HANDLER(int internalCall) 
+            IOBuf[2] = EX0; // reportTypeFlag; // 1;
+            writeHID();
+            _firmwareINT0Enabled = EX0;
+            mutexGuardIOBuf.ReleaseMutex();    // Release the Mutex.
+        }
+        private byte _firmwareINT0Enabled = 0;
+        public byte FirmwareINT0Enabled { get { return _firmwareINT0Enabled; } }
+
+        /// <summary>
+        /// Search for a device attached to I2C bus, 
+        /// given a list of poossible device addresses, 
+        /// and a constant device ID register to test.
+        /// </summary>
+        /// <param name="I2C_DeviceAddressList_8bitLeftJustified">List of possible I2C device addresses to test. I2C device addresses are 8-bit left-justified (LSB=R/w bit)</param>
+        /// <param name="DeviceId_RegAddress">device register address of a constant "Device ID" register</param>
+        /// <param name="DeviceId_RegValue_Expect">register value of the constant "Device ID" register</param>
+        /// <returns>I2C device addresses, or 0 if not found</returns>
+        public byte SearchI2CdeviceAddressList(byte[] I2C_DeviceAddressList_8bitLeftJustified, byte DeviceId_RegAddress, byte DeviceId_RegValue_Expect)
+        {
+            // https://jira.maxim-ic.com/browse/OS24EVK-57 accelerometer support: SearchI2CdeviceAddressList optional I2C device
+            foreach (byte test_I2C_Address in I2C_DeviceAddressList_8bitLeftJustified)
+            {
+                //try
+                //{
+                    byte[] data = new byte[2];
+                    byte[] reg = new byte[1];
+                    reg[0] = (byte)DeviceId_RegAddress;
+                    // readI2C should already take care of mutex lock / unlock
+                    // https://jira.maxim-ic.com/browse/OS24EVK-59 avoid NACK exception in SearchI2CdeviceAddressList
+                    bool ignoreNACK = true;
+                    int status = readI2C(test_I2C_Address, 2, 1, data, reg, ignoreNACK);
+                    if (status == HID.I2C_NACK_ERROR)
+                    {
+                        continue;
+                    }
+                    else
+                    {
+                        byte DeviceId_RegValue_Actual = data[0];
+                        if (DeviceId_RegValue_Actual == DeviceId_RegValue_Expect)
+                        {
+                            return test_I2C_Address;
+                        }
+                    }
+                //}
+                //catch (Exception)
+                //{
+                //    // myHID.readI2C can throw Exception("invalid I2C address");
+                //}
+            }
+            return 0;
+        }
+
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HspGuiSourceV301/HSPGui/HSPGui.csproj	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,403 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <PropertyGroup>
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <Platform Condition=" '$(Platform)' == '' ">x86</Platform>
+    <ProductVersion>8.0.30703</ProductVersion>
+    <SchemaVersion>2.0</SchemaVersion>
+    <ProjectGuid>{CEF8731E-362F-407C-86A7-F65ACE2A1ACB}</ProjectGuid>
+    <OutputType>WinExe</OutputType>
+    <AppDesignerFolder>Properties</AppDesignerFolder>
+    <RootNamespace>HealthSensorPlatform</RootNamespace>
+    <AssemblyName>hSensorDemo</AssemblyName>
+    <TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
+    <TargetFrameworkProfile>
+    </TargetFrameworkProfile>
+    <FileAlignment>512</FileAlignment>
+    <IsWebBootstrapper>false</IsWebBootstrapper>
+    <NuGetPackageImportStamp>
+    </NuGetPackageImportStamp>
+    <PublishUrl>publish\</PublishUrl>
+    <Install>true</Install>
+    <InstallFrom>Disk</InstallFrom>
+    <UpdateEnabled>false</UpdateEnabled>
+    <UpdateMode>Foreground</UpdateMode>
+    <UpdateInterval>7</UpdateInterval>
+    <UpdateIntervalUnits>Days</UpdateIntervalUnits>
+    <UpdatePeriodically>false</UpdatePeriodically>
+    <UpdateRequired>false</UpdateRequired>
+    <MapFileExtensions>true</MapFileExtensions>
+    <ApplicationRevision>0</ApplicationRevision>
+    <ApplicationVersion>1.0.0.%2a</ApplicationVersion>
+    <UseApplicationTrust>false</UseApplicationTrust>
+    <BootstrapperEnabled>true</BootstrapperEnabled>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
+    <PlatformTarget>x86</PlatformTarget>
+    <DebugSymbols>true</DebugSymbols>
+    <DebugType>full</DebugType>
+    <Optimize>false</Optimize>
+    <OutputPath>bin\Debug\</OutputPath>
+    <DefineConstants>DEBUG;TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
+    <PlatformTarget>x86</PlatformTarget>
+    <DebugType>pdbonly</DebugType>
+    <Optimize>true</Optimize>
+    <OutputPath>bin\Release\</OutputPath>
+    <DefineConstants>TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+    <RunCodeAnalysis>false</RunCodeAnalysis>
+  </PropertyGroup>
+  <PropertyGroup>
+    <ApplicationIcon>MI_icon.ico</ApplicationIcon>
+  </PropertyGroup>
+  <ItemGroup>
+    <Reference Include="Magick.NET-Q8-AnyCPU">
+      <HintPath>..\packages\Magick.NET-Q8-AnyCPU.7.0.2.400\lib\net40-client\Magick.NET-Q8-AnyCPU.dll</HintPath>
+    </Reference>
+    <Reference Include="MaximStyle">
+      <HintPath>.\MaximStyle.dll</HintPath>
+    </Reference>
+    <Reference Include="nunit.framework, Version=2.6.4.14350, Culture=neutral, PublicKeyToken=96d09a1eb7f44a77, processorArchitecture=MSIL">
+      <SpecificVersion>False</SpecificVersion>
+      <HintPath>..\packages\NUnit.2.6.4\lib\nunit.framework.dll</HintPath>
+    </Reference>
+    <Reference Include="OpenTK, Version=1.1.0.0, Culture=neutral, PublicKeyToken=bad199fe84eb3df4, processorArchitecture=MSIL">
+      <SpecificVersion>False</SpecificVersion>
+      <HintPath>..\packages\Lyncee.OpenTK.1.1.1173.43181\lib\OpenTK.dll</HintPath>
+    </Reference>
+    <Reference Include="OpenTK.Compatibility, Version=1.1.0.0, Culture=neutral, PublicKeyToken=bad199fe84eb3df4, processorArchitecture=MSIL">
+      <SpecificVersion>False</SpecificVersion>
+      <HintPath>..\packages\Lyncee.OpenTK.Compatibility.1.1.1173.43181\lib\OpenTK.Compatibility.dll</HintPath>
+    </Reference>
+    <Reference Include="OpenTK.GLControl, Version=1.1.0.0, Culture=neutral, PublicKeyToken=bad199fe84eb3df4, processorArchitecture=MSIL">
+      <SpecificVersion>False</SpecificVersion>
+      <HintPath>..\packages\OpenTK.GLControl.1.1.2349.61993\lib\NET40\OpenTK.GLControl.dll</HintPath>
+    </Reference>
+    <Reference Include="System" />
+    <Reference Include="System.Core" />
+    <Reference Include="System.Management" />
+    <Reference Include="System.Windows.Forms.DataVisualization" />
+    <Reference Include="System.Xml.Linq" />
+    <Reference Include="System.Data.DataSetExtensions" />
+    <Reference Include="Microsoft.CSharp" />
+    <Reference Include="System.Data" />
+    <Reference Include="System.Deployment" />
+    <Reference Include="System.Drawing" />
+    <Reference Include="System.Windows.Forms" />
+    <Reference Include="System.Xml" />
+  </ItemGroup>
+  <ItemGroup>
+    <Compile Include="Algorithm\InterfaceRedIRGreenLEDdataConsumer.cs" />
+    <Compile Include="Algorithm\MaximAlgorithmClass.cs" />
+    <Compile Include="Algorithm\MaximSKAlgorithmClass.cs" />
+    <Compile Include="Algorithm\SKA.cs" />
+    <Compile Include="BioZChannel.cs">
+      <SubType>Form</SubType>
+    </Compile>
+    <Compile Include="BioZLoad.cs">
+      <SubType>Form</SubType>
+    </Compile>
+    <Compile Include="BioZMux.cs">
+      <SubType>Form</SubType>
+    </Compile>
+    <Compile Include="CustomControls\DoubleBufferTableLayoutPanel.cs">
+      <SubType>Component</SubType>
+    </Compile>
+    <Compile Include="CustomControls\DoubleBufferTableLayoutPanel.Designer.cs">
+      <DependentUpon>DoubleBufferTableLayoutPanel.cs</DependentUpon>
+    </Compile>
+    <Compile Include="CustomControls\EcgView.cs">
+      <SubType>UserControl</SubType>
+    </Compile>
+    <Compile Include="CustomControls\EcgView.Designer.cs">
+      <DependentUpon>EcgView.cs</DependentUpon>
+    </Compile>
+    <Compile Include="CustomControls\IDataLoggingView.cs" />
+    <Compile Include="CustomControls\IDeviceView.cs" />
+    <Compile Include="CustomControls\IEcgView.cs" />
+    <Compile Include="CustomControls\IFileLogView.cs" />
+    <Compile Include="CustomControls\InitArgs.cs" />
+    <Compile Include="CustomControls\ITemperatureView.cs" />
+    <Compile Include="CustomControls\LoggingView.cs">
+      <SubType>UserControl</SubType>
+    </Compile>
+    <Compile Include="CustomControls\LoggingView.Designer.cs">
+      <DependentUpon>LoggingView.cs</DependentUpon>
+    </Compile>
+    <Compile Include="CustomControls\OpticalView.cs">
+      <SubType>UserControl</SubType>
+    </Compile>
+    <Compile Include="CustomControls\OpticalView.Designer.cs">
+      <DependentUpon>OpticalView.cs</DependentUpon>
+    </Compile>
+    <Compile Include="CustomControls\PrimitivesView.cs">
+      <SubType>UserControl</SubType>
+    </Compile>
+    <Compile Include="CustomControls\PrimitivesView.Designer.cs">
+      <DependentUpon>PrimitivesView.cs</DependentUpon>
+    </Compile>
+    <Compile Include="CustomControls\RegisterExportView.cs">
+      <SubType>UserControl</SubType>
+    </Compile>
+    <Compile Include="CustomControls\RegisterExportView.Designer.cs">
+      <DependentUpon>RegisterExportView.cs</DependentUpon>
+    </Compile>
+    <Compile Include="CustomControls\RegisterView.cs">
+      <SubType>UserControl</SubType>
+    </Compile>
+    <Compile Include="CustomControls\RegisterView.designer.cs">
+      <DependentUpon>RegisterView.cs</DependentUpon>
+    </Compile>
+    <Compile Include="CustomControls\StreamingStartStopEventArgs.cs" />
+    <Compile Include="CustomControls\TemperatureView.cs">
+      <SubType>UserControl</SubType>
+    </Compile>
+    <Compile Include="CustomControls\TemperatureView.Designer.cs">
+      <DependentUpon>TemperatureView.cs</DependentUpon>
+    </Compile>
+    <Compile Include="DeviceDescriptions\MAX30001Info.cs" />
+    <Compile Include="DeviceDescriptions\MAX14720Info.cs" />
+    <Compile Include="DeviceDescriptions\MAX30003Info.cs" />
+    <Compile Include="DeviceDescriptions\MAX30205Info.cs" />
+    <Compile Include="DeviceDescriptions\Device.cs" />
+    <Compile Include="DeviceDescriptions\DeviceController.cs" />
+    <Compile Include="DeviceDescriptions\LIS2DHInfo.cs" />
+    <Compile Include="DeviceDescriptions\MAX30101Info.cs" />
+    <Compile Include="ECGInputMux.cs">
+      <SubType>Form</SubType>
+    </Compile>
+    <Compile Include="ECGChannel.cs">
+      <SubType>Form</SubType>
+    </Compile>
+    <Compile Include="FirFilter.cs" />
+    <Compile Include="Form1.cs">
+      <SubType>Form</SubType>
+    </Compile>
+    <Compile Include="Form1.Designer.cs">
+      <DependentUpon>Form1.cs</DependentUpon>
+    </Compile>
+    <Compile Include="FormConnection.cs">
+      <SubType>Form</SubType>
+    </Compile>
+    <Compile Include="FormConnection.Designer.cs">
+      <DependentUpon>FormConnection.cs</DependentUpon>
+    </Compile>
+    <Compile Include="IRegisterFieldView.cs" />
+    <Compile Include="MaximColor.cs" />
+    <Compile Include="Model\ACLeadOff.cs" />
+    <Compile Include="Model\DataLogModel.cs" />
+    <Compile Include="Model\IDataLogModel.cs" />
+    <Compile Include="Model\ITemperatureModel.cs" />
+    <Compile Include="Model\DCLeadOff.cs" />
+    <Compile Include="Model\MAX30001.cs" />
+    <Compile Include="Model\MAX30205Model.cs" />
+    <Compile Include="Model\PaceData.cs" />
+    <Compile Include="Presenter\DataLogPresenter.cs" />
+    <Compile Include="Presenter\OpticalAlgorithmPresenter.cs" />
+    <Compile Include="Presenter\RawFileLogPresenter.cs" />
+    <Compile Include="Presenter\RegisterExportPresenter.cs" />
+    <Compile Include="Presenter\RToRCalculator.cs" />
+    <Compile Include="PaceChannel.cs">
+      <SubType>Form</SubType>
+    </Compile>
+    <Compile Include="Model\FifoStruct.cs" />
+    <Compile Include="Model\PaceEventArgs.cs" />
+    <Compile Include="Model\EcgEventArgs.cs" />
+    <Compile Include="Model\BioZEventArgs.cs" />
+    <Compile Include="Model\RToREventArgs.cs" />
+    <Compile Include="Presenter\EcgDelay.cs" />
+    <Compile Include="Presenter\OpticalFileLogPresenter.cs" />
+    <Compile Include="Presenter\StreamPresenter.cs" />
+    <Compile Include="Presenter\TemperaturePresenter.cs" />
+    <Compile Include="Properties\Resources.Designer.cs">
+      <AutoGen>True</AutoGen>
+      <DesignTime>True</DesignTime>
+      <DependentUpon>Resources.resx</DependentUpon>
+    </Compile>
+    <Compile Include="Temperature\TemperatureValue.cs" />
+    <Compile Include="View\DataFormatEventArgs.cs" />
+    <Compile Include="View\FileLogView\FileLogHeader.cs" />
+    <Compile Include="View\IOpticalAlgorithmView.cs" />
+    <Compile Include="View\RegisterExportForm.cs">
+      <SubType>Form</SubType>
+    </Compile>
+    <Compile Include="View\RegisterExportForm.Designer.cs">
+      <DependentUpon>RegisterExportForm.cs</DependentUpon>
+    </Compile>
+    <Compile Include="View\CompleteEventArgs.cs" />
+    <Compile Include="View\EnableEventArgs.cs" />
+    <Compile Include="Program.cs" />
+    <Compile Include="Properties\AssemblyInfo.cs" />
+    <Compile Include="RegisterField.cs" />
+    <Compile Include="SplashScreen.cs">
+      <SubType>Form</SubType>
+    </Compile>
+    <Compile Include="SplashScreen.Designer.cs">
+      <DependentUpon>SplashScreen.cs</DependentUpon>
+    </Compile>
+    <Compile Include="View\FileLogView\IRawFileLogView.cs" />
+    <Compile Include="View\FileLogView\RawFileLogView.cs" />
+    <Compile Include="View\IFormView.cs" />
+    <Compile Include="View\IHspSetting.cs" />
+    <Compile Include="View\IRegisterExportView.cs" />
+    <Compile Include="View\StatusForm.cs">
+      <SubType>Form</SubType>
+    </Compile>
+    <Compile Include="View\StatusForm.Designer.cs">
+      <DependentUpon>StatusForm.cs</DependentUpon>
+    </Compile>
+    <EmbeddedResource Include="CustomControls\EcgView.resx">
+      <DependentUpon>EcgView.cs</DependentUpon>
+    </EmbeddedResource>
+    <EmbeddedResource Include="CustomControls\LoggingView.resx">
+      <DependentUpon>LoggingView.cs</DependentUpon>
+    </EmbeddedResource>
+    <EmbeddedResource Include="CustomControls\OpticalView.resx">
+      <DependentUpon>OpticalView.cs</DependentUpon>
+    </EmbeddedResource>
+    <EmbeddedResource Include="CustomControls\PrimitivesView.resx">
+      <DependentUpon>PrimitivesView.cs</DependentUpon>
+    </EmbeddedResource>
+    <EmbeddedResource Include="CustomControls\RegisterExportView.resx">
+      <DependentUpon>RegisterExportView.cs</DependentUpon>
+    </EmbeddedResource>
+    <EmbeddedResource Include="CustomControls\RegisterView.resx">
+      <DependentUpon>RegisterView.cs</DependentUpon>
+    </EmbeddedResource>
+    <EmbeddedResource Include="CustomControls\TemperatureView.resx">
+      <DependentUpon>TemperatureView.cs</DependentUpon>
+    </EmbeddedResource>
+    <EmbeddedResource Include="Form1.resx">
+      <DependentUpon>Form1.cs</DependentUpon>
+    </EmbeddedResource>
+    <EmbeddedResource Include="FormConnection.resx">
+      <DependentUpon>FormConnection.cs</DependentUpon>
+    </EmbeddedResource>
+    <EmbeddedResource Include="Properties\Resources.resx">
+      <Generator>ResXFileCodeGenerator</Generator>
+      <SubType>Designer</SubType>
+      <LastGenOutput>Resources.Designer.cs</LastGenOutput>
+    </EmbeddedResource>
+    <EmbeddedResource Include="View\RegisterExportForm.resx">
+      <DependentUpon>RegisterExportForm.cs</DependentUpon>
+    </EmbeddedResource>
+    <EmbeddedResource Include="SplashScreen.resx">
+      <DependentUpon>SplashScreen.cs</DependentUpon>
+    </EmbeddedResource>
+    <EmbeddedResource Include="View\StatusForm.resx">
+      <DependentUpon>StatusForm.cs</DependentUpon>
+    </EmbeddedResource>
+    <None Include="app.config" />
+    <None Include="Properties\Settings.settings">
+      <Generator>SettingsSingleFileGenerator</Generator>
+      <LastGenOutput>Settings.Designer.cs</LastGenOutput>
+    </None>
+    <Compile Include="Properties\Settings.Designer.cs">
+      <AutoGen>True</AutoGen>
+      <DependentUpon>Settings.settings</DependentUpon>
+      <DesignTimeSharedInput>True</DesignTimeSharedInput>
+    </Compile>
+  </ItemGroup>
+  <ItemGroup>
+    <ProjectReference Include="..\GuiDLLs\ChartHelper\ChartHelper\ChartHelper.csproj">
+      <Project>{3a90ebb9-82c1-4928-88ac-a79abc7f1de9}</Project>
+      <Name>ChartHelper</Name>
+    </ProjectReference>
+    <ProjectReference Include="..\GuiDLLs\FileLog\FileLog\FileLog.csproj">
+      <Project>{53b0d46e-43fd-425e-b316-98b8708d161f}</Project>
+      <Name>FileLog</Name>
+    </ProjectReference>
+    <ProjectReference Include="..\GuiDLLs\MaximGlobal\Maxim.Global.csproj">
+      <Project>{57e4e43c-871b-4113-950e-d649ac6d386a}</Project>
+      <Name>Maxim.Global</Name>
+    </ProjectReference>
+    <ProjectReference Include="..\GuiDLLs\RPCSupport\RPCSupport.csproj">
+      <Project>{170A27F5-0680-485D-8B90-EA736719016E}</Project>
+      <Name>RPCSupport</Name>
+    </ProjectReference>
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="Resources\bio-impedance_block.png" />
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="Resources\ecg_channel_block.png" />
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="Resources\ecg_lead_config.png" />
+  </ItemGroup>
+  <ItemGroup>
+    <BootstrapperPackage Include=".NETFramework,Version=v4.0">
+      <Visible>False</Visible>
+      <ProductName>Microsoft .NET Framework 4 %28x86 and x64%29</ProductName>
+      <Install>true</Install>
+    </BootstrapperPackage>
+    <BootstrapperPackage Include="Microsoft.Net.Client.3.5">
+      <Visible>False</Visible>
+      <ProductName>.NET Framework 3.5 SP1 Client Profile</ProductName>
+      <Install>false</Install>
+    </BootstrapperPackage>
+    <BootstrapperPackage Include="Microsoft.Net.Framework.3.5.SP1">
+      <Visible>False</Visible>
+      <ProductName>.NET Framework 3.5 SP1</ProductName>
+      <Install>false</Install>
+    </BootstrapperPackage>
+    <BootstrapperPackage Include="Microsoft.Windows.Installer.4.5">
+      <Visible>False</Visible>
+      <ProductName>Windows Installer 4.5</ProductName>
+      <Install>true</Install>
+    </BootstrapperPackage>
+  </ItemGroup>
+  <ItemGroup>
+    <Content Include="MI_icon.ico" />
+    <Content Include="SKA.dll">
+      <CopyToOutputDirectory>Always</CopyToOutputDirectory>
+    </Content>
+    <None Include="Resources\ecg_lead_config_closed_swOnly.png" />
+    <None Include="Resources\open.png" />
+    <None Include="Resources\ecg_lead_config1.png" />
+    <None Include="Resources\bioz_input_mux1.png" />
+    <None Include="Resources\bioz_input_muxloff1.png" />
+    <None Include="Resources\bioz_input_muxlb1.png" />
+    <None Include="Resources\bioz_input_muxlb2.png" />
+    <None Include="Resources\bioz_input_muxcal1.png" />
+    <None Include="Resources\bioz_input_muxcal2.png" />
+    <Content Include="Resources\bioz_input_muxloff2.png" />
+    <None Include="Resources\bioz_input_muxlon.png" />
+    <None Include="Resources\bioz_input_muxsw1.png" />
+    <None Include="Resources\bioz_input_muxsw2.png" />
+    <None Include="Resources\bioz_load_cal1.png" />
+    <None Include="Resources\bioz_load_cal2.png" />
+    <None Include="Resources\bioz_load_lb1.png" />
+    <None Include="Resources\bioz_load_lb2.png" />
+    <None Include="Resources\bioz_load_leadon.png" />
+    <None Include="Resources\bioz_load_resload.png" />
+    <None Include="Resources\bioz_load_sw1.png" />
+    <None Include="Resources\bioz_load_sw2.png" />
+    <None Include="Resources\bioz_loadloff1.png" />
+    <None Include="Resources\bioz_loadloff2.png" />
+    <None Include="Resources\bioz_loadrz.png" />
+    <Content Include="Resources\pace_falling.png" />
+    <Content Include="Resources\pace_rising.png" />
+    <None Include="Resources\sw1.png" />
+    <None Include="Resources\sw5.png" />
+    <None Include="Resources\sw1rz.png" />
+    <Content Include="Resources\system_block_diagram_max30003.png" />
+    <None Include="Resources\system_block_diagram.png" />
+    <None Include="Resources\bioz_load.png" />
+    <None Include="Resources\bioz_input_mux.png" />
+    <Content Include="Resources\pace_block_diagrams.png" />
+  </ItemGroup>
+  <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+  <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 
+       Other similar extension points exist, see Microsoft.Common.targets.
+  <Target Name="BeforeBuild">
+  </Target>
+  <Target Name="AfterBuild">
+  </Target>
+  -->
+</Project>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HspGuiSourceV301/HSPGui/IRegisterFieldView.cs	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,48 @@
+/*******************************************************************************
+* Copyright (C) 2016 Maxim Integrated Products, Inc., All rights Reserved.
+* 
+* This software is protected by copyright laws of the United States and
+* of foreign countries. This material may also be protected by patent laws
+* and technology transfer regulations of the United States and of foreign
+* countries. This software is furnished under a license agreement and/or a
+* nondisclosure agreement and may only be used or reproduced in accordance
+* with the terms of those agreements. Dissemination of this information to
+* any party or parties not specified in the license agreement and/or
+* nondisclosure agreement is expressly prohibited.
+*
+* The above copyright notice and this permission notice shall be included
+* in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+* OTHER DEALINGS IN THE SOFTWARE.
+*
+* Except as contained in this notice, the name of Maxim Integrated
+* Products, Inc. shall not be used except as stated in the Maxim Integrated
+* Products, Inc. Branding Policy.
+*
+* The mere transfer of this software does not imply any licenses
+* of trade secrets, proprietary technology, copyrights, patents,
+* trademarks, maskwork rights, or any other form of intellectual
+* property whatsoever. Maxim Integrated Products, Inc. retains all
+* ownership rights.
+*******************************************************************************
+*/
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace HealthSensorPlatform
+{
+    interface IRegisterFieldView
+    {
+        int ReadField();
+        void WriteField(int data);
+    }
+}
Binary file HspGuiSourceV301/HSPGui/MI_icon.ico has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HspGuiSourceV301/HSPGui/MaximColor.cs	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,138 @@
+/*******************************************************************************
+* Copyright (C) 2016 Maxim Integrated Products, Inc., All rights Reserved.
+* 
+* This software is protected by copyright laws of the United States and
+* of foreign countries. This material may also be protected by patent laws
+* and technology transfer regulations of the United States and of foreign
+* countries. This software is furnished under a license agreement and/or a
+* nondisclosure agreement and may only be used or reproduced in accordance
+* with the terms of those agreements. Dissemination of this information to
+* any party or parties not specified in the license agreement and/or
+* nondisclosure agreement is expressly prohibited.
+*
+* The above copyright notice and this permission notice shall be included
+* in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+* OTHER DEALINGS IN THE SOFTWARE.
+*
+* Except as contained in this notice, the name of Maxim Integrated
+* Products, Inc. shall not be used except as stated in the Maxim Integrated
+* Products, Inc. Branding Policy.
+*
+* The mere transfer of this software does not imply any licenses
+* of trade secrets, proprietary technology, copyrights, patents,
+* trademarks, maskwork rights, or any other form of intellectual
+* property whatsoever. Maxim Integrated Products, Inc. retains all
+* ownership rights.
+*******************************************************************************
+*/
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Drawing;
+
+namespace MaximStyle
+{
+    public struct MaximColor
+    {
+        static Color teal = Color.FromArgb(0x00, 0xB2, 0xA9);
+        static Color purple = Color.FromArgb(0x6E, 0x25, 0x85);
+        static Color green = Color.FromArgb(0x99, 0xC6, 0x4C);
+        static Color red = Color.FromArgb(0xFF, 0x00, 0x00);
+        static Color yellow = Color.FromArgb(0xFF, 0xC2, 0x20);
+        static Color lightBlue = Color.FromArgb(0x93, 0xc3, 0xde);
+        static Color orange = Color.FromArgb(241, 92, 34);
+
+        // Generic Names for Colors
+        public static Color Teal { get { return teal; } }
+        public static Color Purple { get { return purple; } }
+        public static Color Green { get { return green; } }
+        public static Color Red { get { return red; } }
+        public static Color Yellow { get { return yellow; } }
+        public static Color LightBlue { get { return lightBlue; } }
+        public static Color Orange { get { return orange; } }
+
+        // SET Look & Feel Names
+        public static Color Background
+        {
+            get
+            {
+                return Color.White;
+            }
+        }
+        public static Color AlternateBackground 
+        {
+            get 
+            {
+                return Color.FromArgb(0xdd, 0xdd, 0xdd);
+            }
+        }
+        public static Color Outline 
+        {
+            get
+            {
+                return Color.FromArgb(0xce, 0xce, 0xce);
+            }
+        }
+        public static Color InactiveSection 
+        {
+            get
+            {
+                return Color.FromArgb(0xad, 0xad, 0xad);
+            }
+        }
+        public static Color Borders = Color.FromArgb(0x6c, 0x6f, 0x70);
+        public static Color MainText = Color.Black;
+        public Color Links
+        {
+            get
+            {
+                return teal;
+            }
+        }
+        public static Color MouseoverLinkActiveElements
+        {
+            get
+            {
+                return purple;
+            }
+        }
+        public static Color FollowedLink 
+        {
+            get
+            {
+                return Color.FromArgb(0x96, 0x96, 0x96);
+            }
+        }
+        public static Color Warning
+        {
+            get
+            {
+                return yellow;
+            }
+        }
+        public static Color GoOK
+        {
+            get
+            {
+                return green;
+            }
+        }
+        public static Color Error
+        {
+            get
+            {
+                return red;
+            }
+        }
+
+    }
+}
Binary file HspGuiSourceV301/HSPGui/MaximStyle.dll has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HspGuiSourceV301/HSPGui/MedicalChartHelper.cs	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,705 @@
+//using System;
+//using System.Collections;
+//using System.Collections.Generic;
+//using System.ComponentModel;
+//using System.Linq;
+//using System.Text;
+//using System.Windows.Forms;
+//using Microsoft.Win32.SafeHandles;
+
+namespace Maxim.MAX30101
+{
+#pragma warning disable 1574
+    /// <summary>
+    /// MedicalChartHelper class, an invisible "helper" class, 
+    /// helps manage an existing standard chart object.
+    /// 
+    /// Initializes the standard 
+    /// System.Windows.Forms.DataVisualization.Charting.Chart chart
+    /// with a maximum of 3 chart areas vertically aligned with each other.
+    ///
+    /// When data is appended to the chart, the chart series data
+    /// is initially aligned with the left. Once the X axis reaches the
+    /// right side of the screen, the chart begins scrolling so that
+    /// newest data is aligned to the right edge.
+    ///
+    /// </summary>
+#pragma warning restore 1574
+    public class MedicalChartHelper
+    {
+        private System.Windows.Forms.DataVisualization.Charting.Chart _chart;
+        private string _chartArea1Name;
+        private string _chartArea2Name;
+        private string _chartArea3Name;
+        private string _series1Name;
+        private string _series2Name;
+        private string _series3Name;
+        private string _chartArea1AxisYTitle;
+        private string _chartArea2AxisYTitle;
+        private string _chartArea3AxisYTitle;
+        
+        /// <summary>
+        /// Constructor 
+        /// </summary>
+        /// <param name="chart"></param>
+        /// <param name="chartArea1Name"></param>
+        /// <param name="series1Name"></param>
+        /// <param name="chartArea1AxisYTitle"></param>
+        /// <param name="chartArea2Name"></param>
+        /// <param name="series2Name"></param>
+        /// <param name="chartArea2AxisYTitle"></param>
+        /// <param name="chartArea3Name"></param>
+        /// <param name="series3Name"></param>
+        /// <param name="chartArea3AxisYTitle"></param>
+        public MedicalChartHelper(System.Windows.Forms.DataVisualization.Charting.Chart chart,
+            string chartArea1Name = "ChartArea1Red", string series1Name = "SeriesRed", string chartArea1AxisYTitle = "Red ADC Code",
+            string chartArea2Name = "ChartArea2IR", string series2Name = "SeriesIR", string chartArea2AxisYTitle = "IR ADC Code",
+            string chartArea3Name = "ChartArea3Green", string series3Name = "SeriesGreen", string chartArea3AxisYTitle = "Green ADC Code",
+            DataFormats dataFormat = DataFormats.FormatUnsigned
+        )
+        {
+            // implementation: see InitCharting()
+            // default X axis length should be 10 seconds of data
+            _chart = chart;
+            _chartArea1Name = chartArea1Name;
+            _chartArea2Name = chartArea2Name;
+            _chartArea3Name = chartArea3Name;
+            _series1Name = series1Name;
+            _series2Name = series2Name;
+            _series3Name = series3Name;
+            _chartArea1AxisYTitle = chartArea1AxisYTitle;
+            _chartArea2AxisYTitle = chartArea2AxisYTitle;
+            _chartArea3AxisYTitle = chartArea3AxisYTitle;
+
+            DataFormat = dataFormat;
+
+            // VERIFY: OS24EVK-75 replace _xCount with _xCount1, _xCount2, _xCount3
+            //_xCount = 0;
+            _xCount1 = 0;
+            _xCount2 = 0;
+            _xCount3 = 0;
+
+            _chart.Titles[0].Visible = false;
+
+            _chart.ChartAreas[_chartArea2Name].AlignWithChartArea = _chartArea1Name;
+            _chart.ChartAreas[_chartArea3Name].AlignWithChartArea = _chartArea1Name;
+
+            _chart.ChartAreas[_chartArea1Name].AxisY.Title = chartArea1AxisYTitle;
+            _chart.ChartAreas[_chartArea2Name].AxisY.Title = chartArea2AxisYTitle;
+            _chart.ChartAreas[_chartArea3Name].AxisY.Title = chartArea3AxisYTitle;
+
+            //_chart.ChartAreas[_chartArea1Name].AxisX.LabelStyle.Enabled = !_plotXAxisNoLabels;
+            //_chart.ChartAreas[_chartArea2Name].AxisX.LabelStyle.Enabled = !_plotXAxisNoLabels;
+            //_chart.ChartAreas[_chartArea3Name].AxisX.LabelStyle.Enabled = !_plotXAxisNoLabels;
+
+            _chart.ChartAreas[_chartArea1Name].Visible = true; // valid_Red;
+            _chart.ChartAreas[_chartArea2Name].Visible = true; // valid_IR;
+            _chart.ChartAreas[_chartArea3Name].Visible = true; // valid_Green;
+
+            _chart.Series[_series1Name].MarkerSize = 1; // Charting.Series.MarkerSize=0 makes no points visible
+            _chart.Series[_series1Name].BorderWidth = 1; // Charting.Series.BorderWidth is actually the line thickness
+            _chart.Series[_series1Name].XValueType = System.Windows.Forms.DataVisualization.Charting.ChartValueType.UInt32;
+            _chart.Series[_series1Name].YValueType = System.Windows.Forms.DataVisualization.Charting.ChartValueType.Int32;
+
+            _chart.Series[_series2Name].MarkerSize = 1; // Charting.Series.MarkerSize=0 makes no points visible
+            _chart.Series[_series2Name].BorderWidth = 1; // Charting.Series.BorderWidth is actually the line thickness
+            _chart.Series[_series2Name].XValueType = System.Windows.Forms.DataVisualization.Charting.ChartValueType.UInt32;
+            _chart.Series[_series2Name].YValueType = System.Windows.Forms.DataVisualization.Charting.ChartValueType.Int32;
+
+            _chart.Series[_series3Name].MarkerSize = 1; // Charting.Series.MarkerSize=0 makes no points visible
+            _chart.Series[_series3Name].BorderWidth = 1; // Charting.Series.BorderWidth is actually the line thickness
+            _chart.Series[_series3Name].XValueType = System.Windows.Forms.DataVisualization.Charting.ChartValueType.UInt32;
+            _chart.Series[_series3Name].YValueType = System.Windows.Forms.DataVisualization.Charting.ChartValueType.Int32;
+        }
+
+        /// <summary>
+        /// Clear chart data, reset _xCount, reset _plotPointsToSkip
+        /// </summary>
+        public void Clear()
+        {
+            _chart.Series[_series1Name].Points.Clear();
+            _chart.Series[_series2Name].Points.Clear();
+            _chart.Series[_series3Name].Points.Clear();
+            // VERIFY: OS24EVK-75 replace _xCount with _xCount1, _xCount2, _xCount3
+            //_xCount = 0;
+            _xCount1 = 0;
+            _xCount2 = 0;
+            _xCount3 = 0;
+            _plotPointsToSkip = 0;
+            // https://jira.maxim-ic.com/browse/OS24EVK-32 replace numPlotTime with menu item Options | Plot Time
+            _plotPoints = (int)_plotWindowTime * _SampleRate_Hz / SampleAverage_n;
+            if (_plotPoints > _maxPlotPoints)
+            {
+                _plotPointsToSkip = _plotPoints / _maxPlotPoints - 1;
+                _plotPoints = _maxPlotPoints;
+            }
+        }
+
+        /// <summary>
+        /// Replacement for plotXAxisNoLabelsToolStripMenuItem.Checked
+        /// </summary>
+        public bool plotXAxisNoLabels { 
+            get { return _plotXAxisNoLabels; }
+            set
+            {
+                _plotXAxisNoLabels = value;
+                _chart.ChartAreas[_chartArea1Name].AxisX.LabelStyle.Enabled = !_plotXAxisNoLabels;
+                _chart.ChartAreas[_chartArea2Name].AxisX.LabelStyle.Enabled = !_plotXAxisNoLabels;
+                _chart.ChartAreas[_chartArea3Name].AxisX.LabelStyle.Enabled = !_plotXAxisNoLabels;
+            }
+        }
+        private bool _plotXAxisNoLabels = true; // VERIFY: default plotXAxisNoLabelsToolStripMenuItem.Checked
+
+        /// <summary>
+        /// Replacement for plotXAxisTimeToolStripMenuItem.Checked
+        /// </summary>
+        public bool plotXAxisTime
+        {
+            get { return _plotXAxisTime; }
+            set
+            {
+                _plotXAxisTime = value;
+            }
+        }
+        private bool _plotXAxisTime = true; // VERIFY: default plotXAxisTimeToolStripMenuItem.Checked
+
+        private int _SampleRate_Hz = 100;
+        /// <summary>
+        /// Sample rate. Replacement for int.Parse(cboSampleRate.Text)
+        /// </summary>
+        public int SampleRate_Hz
+        {
+            get { return _SampleRate_Hz; } 
+            set 
+            { 
+                _SampleRate_Hz = value;
+
+                //_AutoScaleEveryNSamples = 4 * _SampleRate_Hz; // 4 seconds assuming sample rate int.Parse(cboSampleRate.Text) == 100 samples per second
+
+                // VERIFY: OS24EVK-73 Sample Avg 2 breaks chart scrolling
+                // update _plotPoints which depends on myMAX30101.SampleAverage_n
+                _plotPoints = (int)_plotWindowTime * _SampleRate_Hz / SampleAverage_n;
+                if (_plotPoints > _maxPlotPoints)
+                {
+                    _plotPointsToSkip = _plotPoints / _maxPlotPoints - 1;
+                    _plotPoints = _maxPlotPoints;
+                }
+            } 
+        }
+
+        private int _SampleAverage_n = 1;
+        /// <summary>
+        /// Replacement for myMAX30101.SampleAverage_n
+        /// </summary>
+        public int SampleAverage_n
+        {
+            get { return _SampleAverage_n; }
+            set
+            {
+                _SampleAverage_n = value;
+                // VERIFY: OS24EVK-73 Sample Avg 2 breaks chart scrolling
+                // update _plotPoints which depends on myMAX30101.SampleAverage_n
+                _plotPoints = (int)_plotWindowTime * _SampleRate_Hz / SampleAverage_n;
+                if (_plotPoints > _maxPlotPoints)
+                {
+                    _plotPointsToSkip = _plotPoints / _maxPlotPoints - 1;
+                    _plotPoints = _maxPlotPoints;
+                }
+            }
+        }
+
+        // VERIFY: IMPLEMENT OS24EVK-70 Maxim.MAX30101.MedicalChartHelper._xCount int instead of double?
+        // VERIFY: OS24EVK-75 replace _xCount with _xCount1, _xCount2, _xCount3
+        //public double _xCount = 0;
+        public int _xCount1 = 0;
+        public int _xCount2 = 0;
+        public int _xCount3 = 0;
+
+        /// <summary>
+        /// The actual number of points on the plot (&lt;= _maxPlotPoints). The actual number of points may be less than _maxPlotPoints in order to maintain ~numPlotTime.Value of plotted data
+        /// </summary>
+        public int _plotPoints = 500;
+
+        private int _plotWindowTime = 5;    // plot window in seconds
+        public int plotWindowTime 
+        {
+            get 
+            {
+                return _plotWindowTime;
+            }
+            set 
+            {
+                _plotWindowTime = value;
+                _plotPoints = (int)_plotWindowTime * _SampleRate_Hz / SampleAverage_n;
+                if (_plotPoints > _maxPlotPoints)
+                {
+                    _plotPointsToSkip = _plotPoints / _maxPlotPoints - 1;
+                    _plotPoints = _maxPlotPoints;
+                }
+            }
+        }
+
+        private int _maxPlotPoints = 2000;   // maximum allowed number of points that can be plotted per series. Higher Fs will have more than 500 pts for a given numPlotTime.Value, so the number of samples per point will need to be increased accordingly to give maximum _maxPlotPoints
+
+        public int _plotPointsToSkip = 0;
+
+        // https://jira.maxim-ic.com/browse/OS24EVK-34 Autoscale tuning parameters
+        // https://jira.maxim-ic.com/browse/OS24EVK-34 Change _AutoScaleTimeInterval to _AutoScaleEveryNSamples and use sampleNumber to measure time
+        // https://jira.maxim-ic.com/browse/OS24EVK-42 Autoscale tuning (Larry 2014-11-24) _AutoScaleEveryNSamples
+        // - Slow the Autoscale update rate every 4 seconds
+        //private int _AutoScaleEveryNSamples = 400; // 4 seconds assuming sample rate int.Parse(cboSampleRate.Text) == 100 samples per second
+
+        // private double _AutoScaleMarginXLeft; // ignore old data at left of graph
+        // private double _AutoScaleMarginXRight; // ignore new data at right of graph? probably 0 by default
+        
+        /// <summary>
+        /// chartMax empty area above dataMax
+        /// </summary>
+        private static double _AutoScaleMarginYTop = 0.125;
+        
+        /// <summary>
+        /// chartMin empty area below dataMin
+        /// </summary>
+        private static double _AutoScaleMarginYBottom = 0.125;
+        
+        /// <summary>
+        /// Minimum Y span: allow up to 10 counts per division (i.e. 50 LSBs)
+        /// 
+        /// (5 * _AutoScaleYmultiples) minimum allowed span of chartMax-chartMin, 
+        /// to avoid focusing on LSB noise
+        /// </summary>
+        private static double _AutoScaleMinSpanY = 500;
+
+        /// <summary>
+        /// Y axis: No decimals. Round to nearest multiple of 100.
+        /// </summary>
+        private static double _AutoScaleYmultiples = 100;
+
+        // Calculated initial default chart limits _AutoscaleInitialChartMaxY .. _AutoscaleInitialChartMinY
+        int _AutoscaleInitialChartMaxY =
+            (
+                (int)
+                    ((_AutoScaleMinSpanY * (1.0 + _AutoScaleMarginYTop + _AutoScaleMarginYBottom)) / _AutoScaleYmultiples)
+            )
+            * (int)(_AutoScaleYmultiples);
+        int _AutoscaleInitialChartMinY = 0;
+
+        /// <summary>
+        /// Append data to chart area 1 series 1 (Optical: Red. Accelerometer: X)
+        ///
+        /// @post _xCount1 is updated
+        /// </summary>
+        /// <param name="rawIntArrayYData"></param>
+        /// <param name="firstNewXIndex"></param>
+        /// <param name="lastXIndex"></param>
+        public void AppendDataChartArea1(int[] rawIntArrayYData, int firstNewXIndex, int lastXIndex)
+        {
+            // AppendDataChartArea(_chartArea1Name, _series1Name, rawIntArrayYData, firstNewXIndex, lastXIndex);
+            string chartAreaName = _chartArea1Name;
+            string seriesName = _series1Name;
+            
+            for (int index = firstNewXIndex; index <= lastXIndex; index++)
+            {
+                int yData = rawIntArrayYData[index];
+                // VERIFY: OS24EVK-75 replace AutoScaleEvaluate dataFormatIs16bit2sComplement with if (DataFormat == DataFormats.Format16bit2sComplement) 
+                if (DataFormat == DataFormats.Format16bit2sComplement)
+                {
+                    // VERIFY: OS24EVK-57 interpret rawX rawY rawZ as 16-bit 2's complement
+                    if (yData > 0x8000)
+                    {
+                        yData = yData - 0x10000;
+                    }
+                }
+                int count = _chart.Series[seriesName].Points.Count;
+                // VERIFY: OS24EVK-75 replace _xCount with _xCount1, _xCount2, _xCount3
+                double xCoord = _xCount1 * (_plotPointsToSkip + 1) * SampleAverage_n / (plotXAxisTime ? SampleRate_Hz : 1);
+                
+                //_chart.Series[seriesName].Points.AddXY(xCoord, yData);
+                _chart.Series[seriesName].Points.AddY(yData);
+                _chart.ResetAutoValues();
+
+                while (count > _plotPoints)
+                {
+                    _chart.Series[seriesName].Points.RemoveAt(0);
+                    count = _chart.Series[seriesName].Points.Count;
+                }
+                // VERIFY: OS24EVK-75 replace _xCount with _xCount1, _xCount2, _xCount3
+                _xCount1++;
+            }
+            //AutoScaleEvaluate(e.rawRedData, e.sampleNumberOffset, numSamples - 1, _chart, chartAreaName);
+        }
+
+        /// <summary>
+        /// Append data to chart area 2 series 2 (Optical: IR. Accelerometer: Y)
+        ///
+        /// @post _xCount2 is updated
+        /// </summary>
+        /// <param name="rawIntArrayYData"></param>
+        /// <param name="firstNewXIndex"></param>
+        /// <param name="lastXIndex"></param>
+        public void AppendDataChartArea2(int[] rawIntArrayYData, int firstNewXIndex, int lastXIndex)
+        {
+            // AppendDataChartArea(_chartArea2Name, _series2Name, rawIntArrayYData, firstNewXIndex, lastXIndex);
+            string chartAreaName = _chartArea2Name;
+            string seriesName = _series2Name;
+            
+            for (int index = firstNewXIndex; index <= lastXIndex; index++)
+            {
+                int yData = rawIntArrayYData[index];
+                // VERIFY: OS24EVK-75 replace AutoScaleEvaluate dataFormatIs16bit2sComplement with if (DataFormat == DataFormats.Format16bit2sComplement) 
+                if (DataFormat == DataFormats.Format16bit2sComplement)
+                {
+                    // VERIFY: OS24EVK-57 interpret rawX rawY rawZ as 16-bit 2's complement
+                    if (yData > 0x8000)
+                    {
+                        yData = yData - 0x10000;
+                    }
+                }
+                int count = _chart.Series[seriesName].Points.Count;
+                // VERIFY: OS24EVK-75 replace _xCount with _xCount1, _xCount2, _xCount3
+                double xCoord = _xCount2 * (_plotPointsToSkip + 1) * SampleAverage_n / (plotXAxisTime ? SampleRate_Hz : 1);
+                
+                _chart.Series[seriesName].Points.AddXY(xCoord, yData);
+                _chart.ResetAutoValues();
+
+                while (count > _plotPoints)
+                {
+                    _chart.Series[seriesName].Points.RemoveAt(0);
+                    count = _chart.Series[seriesName].Points.Count;
+                }
+                // VERIFY: OS24EVK-75 replace _xCount with _xCount1, _xCount2, _xCount3
+                _xCount2++;
+            }
+            //AutoScaleEvaluate(e.rawRedData, e.sampleNumberOffset, numSamples - 1, _chart, chartAreaName);
+        }
+
+        /// <summary>
+        /// Append data to chart area 3 series 3 (Optical: Green. Accelerometer: Z)
+        ///
+        /// @post _xCount3 is updated
+        /// </summary>
+        /// <param name="rawIntArrayYData"></param>
+        /// <param name="firstNewXIndex"></param>
+        /// <param name="lastXIndex"></param>
+        public void AppendDataChartArea3(int[] rawIntArrayYData, int firstNewXIndex, int lastXIndex)
+        {
+            // AppendDataChartArea(_chartArea3Name, _series3Name, rawIntArrayYData, firstNewXIndex, lastXIndex);
+            string chartAreaName = _chartArea3Name;
+            string seriesName = _series3Name;
+            
+            for (int index = firstNewXIndex; index <= lastXIndex; index++)
+            {
+                int yData = rawIntArrayYData[index];
+                // VERIFY: OS24EVK-75 replace AutoScaleEvaluate dataFormatIs16bit2sComplement with if (DataFormat == DataFormats.Format16bit2sComplement) 
+                if (DataFormat == DataFormats.Format16bit2sComplement)
+                {
+                    // VERIFY: OS24EVK-57 interpret rawX rawY rawZ as 16-bit 2's complement
+                    if (yData > 0x8000)
+                    {
+                        yData = yData - 0x10000;
+                    }
+                }
+                int count = _chart.Series[seriesName].Points.Count;
+                // VERIFY: OS24EVK-75 replace _xCount with _xCount1, _xCount2, _xCount3
+                double xCoord = _xCount3 * (_plotPointsToSkip + 1) * SampleAverage_n / (plotXAxisTime ? SampleRate_Hz : 1);
+                
+                _chart.Series[seriesName].Points.AddXY(xCoord, yData);
+                _chart.ResetAutoValues();
+
+                while (count > _plotPoints)
+                {
+                    _chart.Series[seriesName].Points.RemoveAt(0);
+                    count = _chart.Series[seriesName].Points.Count;
+                }
+                // VERIFY: OS24EVK-75 replace _xCount with _xCount1, _xCount2, _xCount3
+                _xCount3++;
+            }
+            //AutoScaleEvaluate(e.rawRedData, e.sampleNumberOffset, numSamples - 1, _chart, chartAreaName);
+        }
+
+#if PROFILER
+        //// TODO1: OS24EVK-54 profiling: capture max interval, number of intervals, cumulative interval
+        System.Diagnostics.Stopwatch _profilingStopwatchAutoScaleEvaluate = new System.Diagnostics.Stopwatch(); // cumulative timing
+        int _profilingStopwatchAutoScaleEvaluate_NumIntervals;
+#endif // PROFILER
+
+        public void AutoScaleEvaluate1(int[] rawIntArrayYData, int firstNewXIndex, int lastXIndex)
+        {
+            AutoScaleEvaluate(rawIntArrayYData, firstNewXIndex, lastXIndex, _chartArea1Name);
+        }
+
+        public void AutoScaleEvaluate2(int[] rawIntArrayYData, int firstNewXIndex, int lastXIndex)
+        {
+            AutoScaleEvaluate(rawIntArrayYData, firstNewXIndex, lastXIndex, _chartArea2Name);
+        }
+
+        public void AutoScaleEvaluate3(int[] rawIntArrayYData, int firstNewXIndex, int lastXIndex)
+        {
+            AutoScaleEvaluate(rawIntArrayYData, firstNewXIndex, lastXIndex, _chartArea3Name);
+        }
+
+        // TODO1: OS24EVK-57 OS24EVK-54 AutoScaleEvaluate(int[] rawIntArrayYData,...) Calculate autoscale min/max/SampleVariance from the raw integer data. This should be much faster as it doesn't involve arbitrarily converting into floating-point numbers or excessive indexing.
+        public void AutoScaleEvaluate(int[] rawIntArrayYData,
+                int firstNewXIndex,
+                int lastXIndex,
+                /*Chart chart,*/ string chartAreaName
+                // TODO1: OS24EVK-75 replace AutoScaleEvaluate dataFormatIs16bit2sComplement with if (DataFormat == DataFormats.Format16bit2sComplement) 
+                //bool dataFormatIs16bit2sComplement = false
+            //string seriesName, 
+            //int sampleNumber, 
+            //ref int sampleNumberPreviousAutoscale
+            )
+        {
+#if PROFILER
+            // TODO1: OS24EVK-54 profiling: capture max interval, number of intervals, cumulative interval
+            _profilingStopwatchAutoScaleEvaluate.Start();
+            _profilingStopwatchAutoScaleEvaluate_NumIntervals = _profilingStopwatchAutoScaleEvaluate_NumIntervals + 1;
+#endif // PROFILER
+
+            // TODO1: OS24EVK-57 OS24EVK-54 Calculate autoscale min/max/SampleVariance from the raw integer data. This should be much faster as it doesn't involve arbitrarily converting into floating-point numbers or excessive indexing.
+
+            // https://jira.maxim-ic.com/browse/OS24EVK-34 AutoScaleEvaluate() use _AutoScaleMarginXLeft; // ignore old data at left of graph
+            // https://jira.maxim-ic.com/browse/OS24EVK-34 AutoScaleEvaluate() use _AutoScaleMarginXRight; // ignore new data at right of graph? probably 0 by default
+            //const int firstPointIndex = 0;
+            // advance the left and right X limits
+            // https://jira.maxim-ic.com/browse/OS24EVK-48 Graph X axis - Replace hidden chkPlotTime with a menu option plotXAxisTimeToolStripMenuItem.Checked
+            // https://jira.maxim-ic.com/browse/OS24EVK-47 Graph scrolling needs to be smooth progression like a paper tape chart even when (plotXAxisTimeToolStripMenuItem.Checked is true) 
+            // per Larry Skrenes 2014-11-24: graph scrolling needs to be smooth progression like a paper tape chart.
+            // When (plotXAxisTimeToolStripMenuItem.Checked is false) graph scrolling is already smooth.
+            // When (plotXAxisTimeToolStripMenuItem.Checked is true) graph scrolling moves in staccato 1-second steps. Larry hates this.
+            int xWidth = _plotPoints * (_plotPointsToSkip + 1) * SampleAverage_n / (plotXAxisTime ? SampleRate_Hz : 1);
+            // VERIFY: OS24EVK-73 Sample Avg 2 breaks chart scrolling -- xLastXIndex = lastXIndex * myMAX30101.SampleAverage_n
+            int xLastXIndex = lastXIndex * SampleAverage_n / (plotXAxisTime ? SampleRate_Hz : 1);
+            //int xWidth = _plotPoints * (_plotPointsToSkip + 1) * _cboSampleAvg / (false ? int.Parse(cboSampleRate.Text) : 1);
+            //int xWidth = _plotPoints * (_plotPointsToSkip + 1) * _cboSampleAvg / (1);
+            //int xWidth = _plotPoints * (_plotPointsToSkip + 1) * _cboSampleAvg;
+            // https://jira.maxim-ic.com/browse/OS24EVK-15 Fix plot X axis jumping around (_plotWindowTime)
+            // 0.0 --> 0  1  2  3  4  5
+            // 0.0 --> 0_ 1  2  3  4  5
+            // 0.0 --> 0__1  2  3  4  5
+            // 0.0 --> 0__1_ 2  3  4  5
+            // 0.0 --> 0__1__2  3  4  5
+            // 0.0 --> 0__1__2_ 3  4  5
+            // 0.0 --> 0__1__2__3  4  5
+            // 0.0 --> 0__1__2__3_ 4  5
+            // 0.0 --> 0__1__2__3__4  5
+            // 0.0 --> 0__1__2__3__4_ 5
+            // 0.0 --> 0__1__2__3__4__5
+            // 0.5 -->    1__2__3__4__5_ 6
+            // 1.0 -->    1__2__3__4__5__6
+            // 1.5 -->       2__3__4__5__6_ 7
+            // 2.0 -->       2__3__4__5__6__7
+            // https://jira.maxim-ic.com/browse/OS24EVK-47 Graph scrolling needs to be smooth progression like a paper tape chart even when (plotXAxisTimeToolStripMenuItem.Checked is true) 
+            // per Larry Skrenes 2014-11-24: graph scrolling needs to be smooth progression like a paper tape chart.
+            // When (plotXAxisTimeToolStripMenuItem.Checked is false) graph scrolling is already smooth.
+            // When (plotXAxisTimeToolStripMenuItem.Checked is true) graph scrolling moves in staccato 1-second steps. Larry hates this.
+            // VERIFY: OS24EVK-76 Autoscale delay time is affected by Sample Average - firstVisiblePointIndex
+            //int firstVisiblePointIndex = lastXIndex - (_plotPoints * (_plotPointsToSkip + 1) * SampleAverage_n);
+            int firstVisiblePointIndex = lastXIndex - (_plotPoints * (_plotPointsToSkip + 1));
+            if (firstVisiblePointIndex < 0) { firstVisiblePointIndex = 0; }
+            //
+            // VERIFY: OS24EVK-73 Sample Avg 2 breaks chart scrolling -- xLastXIndex instead of lastXIndex
+            int firstVisiblePointX = xLastXIndex - xWidth; // (int)chart.Series[0].Points[firstPointIndex].XValue;
+            if (firstVisiblePointX < 0) { firstVisiblePointX = 0; }
+            //int firstPointX = (int)System.Math.Ceiling(chart.Series[seriesName].Points[firstPointIndex].XValue);
+            //if ((chart.Series[seriesName].Points[firstPointIndex].XValue) < 0.1)
+            //{
+            //    firstPointX = (int)System.Math.Floor(chart.Series[seriesName].Points[firstPointIndex].XValue);
+            //}
+            _chart.ChartAreas[chartAreaName].AxisX.Minimum = firstVisiblePointX;
+            // https://jira.maxim-ic.com/browse/OS24EVK-47 Graph scrolling needs to be smooth progression like a paper tape chart even when (plotXAxisTimeToolStripMenuItem.Checked is true) 
+            //chart.ChartAreas[0].AxisX.Maximum = (int)System.Math.Ceiling((double)firstPointX + xWidth);
+            _chart.ChartAreas[chartAreaName].AxisX.Maximum = firstVisiblePointX + xWidth;
+
+            if (lastXIndex /* chart.Series[seriesName].Points.Count */ < 1)
+            {
+                //int iMaxY_chart_default = (_AutoScaleMinSpanY * (1.0 + _AutoScaleMarginYTop + _AutoScaleMarginYBottom)) / _AutoScaleYmultiples;
+                //int _AutoscaleInitialChartMaxY = iMaxY_chart_default * _AutoScaleYmultiples;
+                //int _AutoscaleInitialChartMaxY =
+                //    (
+                //        (int)
+                //            ((_AutoScaleMinSpanY * (1.0 + _AutoScaleMarginYTop + _AutoScaleMarginYBottom)) / _AutoScaleYmultiples)
+                //    )
+                //    * (int)(_AutoScaleYmultiples);
+                //int _AutoscaleInitialChartMinY = 0;
+                _chart.ChartAreas[chartAreaName].AxisY.Maximum = _AutoscaleInitialChartMaxY;
+                _chart.ChartAreas[chartAreaName].AxisY.Minimum = _AutoscaleInitialChartMinY;
+#if PROFILER
+                // TODO1: OS24EVK-54 profiling: capture max interval, number of intervals, cumulative interval
+                _profilingStopwatchAutoScaleEvaluate.Stop();
+#endif // PROFILER
+                return;
+            }
+
+            //            // TODO1: OS24EVK-57 OS24EVK-54 scan new data rawIntArrayYData[firstNewIndex .. lastIndex]. As is this code only triggers if the last point is extreme.
+            //            int newestPointIndex = lastXIndex; // chart.Series[seriesName].Points.Count - 1;
+            //            int newestPointY = rawIntArrayYData[lastXIndex]; // (int)chart.Series[seriesName].Points[newestPointIndex].YValues[0];
+            //            if ((newestPointY < chart.ChartAreas[chartAreaName].AxisY.Maximum)
+            //                && (newestPointY > chart.ChartAreas[chartAreaName].AxisY.Minimum)
+            //                )
+            //            {
+            //                // https://jira.maxim-ic.com/browse/OS24EVK-34 always re-evaluate chart when new data exceeds Minimum or Maximum
+            //                // But if we just return at this point, then autoscale will never contract to fit smaller data series.
+            //                //
+            //                // https://jira.maxim-ic.com/browse/OS24EVK-34 Change _AutoScaleTimeInterval to _AutoScaleEveryNSamples and use sampleNumber to measure time
+            //                // https://jira.maxim-ic.com/browse/OS24EVK-34 AutoScaleEvaluate() after every _AutoScaleEveryNSamples, re-scan data and fit chart to data
+            //                // if ( interval has been less than _AutoScaleEveryNSamples ) { return; }
+            //                if ((sampleNumber - sampleNumberPreviousAutoscale) < _AutoScaleEveryNSamples)
+            //                {
+            //#if PROFILER
+            //                    // TODO1: OS24EVK-54 profiling: capture max interval, number of intervals, cumulative interval
+            //                    _profilingStopwatchAutoScaleEvaluate.Stop();
+            //#endif // PROFILER
+            //                    return;
+            //                }
+            //            }
+
+            int chartMinYValue = (int)_chart.ChartAreas[chartAreaName].AxisY.Minimum; // rawIntArrayYData[firstVisiblePointX] - 1;
+            int chartMaxYValue = (int)_chart.ChartAreas[chartAreaName].AxisY.Maximum; // rawIntArrayYData[firstVisiblePointX] + 1;
+            // VERIFY: OS24EVK-73 Sample Avg 2 breaks chart scrolling - firstVisiblePointIndex instead of firstVisiblePointX
+            int dataMinYValue = rawIntArrayYData[firstVisiblePointIndex] - 1;
+            int dataMaxYValue = rawIntArrayYData[firstVisiblePointIndex] + 1;
+            for (int index = firstVisiblePointIndex; index <= lastXIndex; index++)
+            {
+                int Y = rawIntArrayYData[index];
+                // VERIFY: OS24EVK-57 OS24EVK-54 improve chart throughput: AutoScaleEvaluate() dataFormatIs16bit2sComplement=true for Accelerometer X Y Z data
+                // VERIFY: OS24EVK-75 replace AutoScaleEvaluate dataFormatIs16bit2sComplement with if (DataFormat == DataFormats.Format16bit2sComplement) 
+                if (DataFormat == DataFormats.Format16bit2sComplement)
+                {
+                    // VERIFY: OS24EVK-57 interpret rawX rawY rawZ as 16-bit 2's complement
+                    if (Y > 0x8000)
+                    {
+                        Y = Y - 0x10000;
+                    }
+                }
+                //else
+                //{
+                //    Y = Y + 0; // debug breakpoint for code path verification
+                //}
+                if (dataMinYValue > Y)
+                {
+                    dataMinYValue = Y;
+                }
+                if (dataMaxYValue < Y)
+                {
+                    dataMaxYValue = Y;
+                }
+            }
+            // rawIntArrayYData[firstIndex..lastIndex] spans the range from dataMinYValue .. dataMaxYValue
+            double dataSpanY = (dataMaxYValue - dataMinYValue);
+            double dataCenterY = (dataMaxYValue + dataMinYValue) / 2;
+
+            bool isAllDataVisible = (
+                (chartMinYValue < dataMaxYValue) && (dataMaxYValue < chartMaxYValue)
+                &&
+                (chartMinYValue < dataMinYValue) && (dataMinYValue < chartMaxYValue)
+                );
+            if (isAllDataVisible)
+            {
+                // all data is within the chart limits, but is the chart sufficiently zoomed in?
+                double relativeDataSpan = (double)dataSpanY / (chartMaxYValue - chartMinYValue);
+                if (relativeDataSpan > 0.65)
+                {
+                    // the current chart scale is good enough, do not update
+#if PROFILER
+                    // TODO1: OS24EVK-54 profiling: capture max interval, number of intervals, cumulative interval
+                    _profilingStopwatchAutoScaleEvaluate.Stop();
+#endif // PROFILER
+                    return;
+                }
+            }
+            // https://jira.maxim-ic.com/browse/OS24EVK-34 AutoScaleEvaluate() use _AutoScaleMinSpanY; // minimum allowed span of chartMax-chartMin, to avoid focusing on LSB noise
+            if (dataSpanY < _AutoScaleMinSpanY)
+            {
+                // https://jira.maxim-ic.com/browse/OS24EVK-34 Autoscale - Minimum span (in case dataMax-dataMin is too small) to avoid focusing on LSB noise
+                dataSpanY = _AutoScaleMinSpanY;
+            }
+            else
+            {
+                // https://jira.maxim-ic.com/browse/OS24EVK-34 Autoscale - Apply a Top margin - Bottom margin = 12% .. 88% when mapping Chart max-min to Data max-min
+                // https://jira.maxim-ic.com/browse/OS24EVK-34 AutoScaleEvaluate() use _AutoScaleMarginYTop; // chartMax empty area above dataMax
+                // https://jira.maxim-ic.com/browse/OS24EVK-34 AutoScaleEvaluate() use _AutoScaleMarginYBottom; // chartMin empty area below dataMin
+                // dataSpanY = dataSpanY * 1.25;
+                // dataSpanY = dataSpanY * (1.0 + 0.125 + 0.125);
+                dataSpanY = dataSpanY * (1.0 + _AutoScaleMarginYTop + _AutoScaleMarginYBottom);
+
+                // https://jira.maxim-ic.com/browse/OS24EVK-42 Autoscale tuning (Larry 2014-11-24) Round to nearest multiple of 100.
+                // - Y axis: No decimals. Round to nearest multiple of 100.
+                // private double _AutoScaleYmultiples = 100;
+                //int tempdataSpanY = (int)(dataSpanY / _AutoScaleYmultiples);
+                //dataSpanY = tempdataSpanY * _AutoScaleYmultiples;
+                //dataSpanY = (double)((int)dataSpanY / _AutoScaleYmultiples) * _AutoScaleYmultiples;
+                //dataCenterY = (double)((int)dataCenterY / _AutoScaleYmultiples) * _AutoScaleYmultiples;
+            }
+            // https://jira.maxim-ic.com/browse/OS24EVK-34 Autoscale - There are 5 vertical divisions; keep the minor axis tick values integer
+            //int YaxisDivisions = (int)System.Math.Ceiling(dataSpanY / 6.0);
+            //dataSpanY = YaxisDivisions * 6;
+            // https://jira.maxim-ic.com/browse/OS24EVK-42 Autoscale tuning (Larry 2014-11-24) Round to nearest multiple of 100.
+            // - Y axis: No decimals. Round to nearest multiple of 100.
+            // private double _AutoScaleYmultiples = 100;
+            //int tempdataCenterY = (int)(dataCenterY / (_AutoScaleYmultiples*2));
+            //dataCenterY = tempdataCenterY * (_AutoScaleYmultiples*2);
+
+            // chart.ChartAreas[0].AxisY.Maximum = dataMaxYValue;
+            // chart.ChartAreas[0].AxisY.Minimum = dataMinYValue;
+            //chart.ChartAreas[0].AxisY.Maximum = System.Math.Ceiling(dataCenterY + (dataSpanY / 2)); // dataMaxYValue;
+            //chart.ChartAreas[0].AxisY.Minimum = System.Math.Floor(dataCenterY - (dataSpanY / 2)); // dataMinYValue;
+            // https://jira.maxim-ic.com/browse/OS24EVK-42 Autoscale tuning (Larry 2014-11-24) Round to nearest multiple of 100.
+            // - Y axis: No decimals. Round to nearest multiple of 100.
+            // private double _AutoScaleYmultiples = 100;
+            int iMaxY_target = (int)((dataCenterY + (dataSpanY / 2)) / _AutoScaleYmultiples);
+            int iMinY_target = (int)((dataCenterY - (dataSpanY / 2)) / _AutoScaleYmultiples);
+
+            double dampingConstantK = 0.2;
+            int iMaxY_damped = iMaxY_target;
+            int iMinY_damped = iMinY_target;
+            if (double.IsNaN(_chart.ChartAreas[chartAreaName].AxisY.Maximum) == false)
+            {
+                int iMaxY_chart = (int)(_chart.ChartAreas[chartAreaName].AxisY.Maximum / _AutoScaleYmultiples);
+                int iMinY_chart = (int)(_chart.ChartAreas[chartAreaName].AxisY.Minimum / _AutoScaleYmultiples);
+                iMaxY_damped = (int)((dampingConstantK * (double)iMaxY_target) + ((1 - dampingConstantK) * (double)iMaxY_chart) + 0.5);
+                iMinY_damped = (int)((dampingConstantK * (double)iMinY_target) + ((1 - dampingConstantK) * (double)iMinY_chart));
+            }
+            double maxY = iMaxY_target * _AutoScaleYmultiples;
+            double minY = iMinY_target * _AutoScaleYmultiples;
+            _chart.ChartAreas[chartAreaName].AxisY.Maximum = maxY;
+            _chart.ChartAreas[chartAreaName].AxisY.Minimum = minY;
+            // if chart.ChartAreas[chartAreaName].AxisY.Maximum  is NaN then just assign maxY
+            //if (double.IsNaN(chart.ChartAreas[chartAreaName].AxisY.Maximum))
+            //{
+            //    chart.ChartAreas[chartAreaName].AxisY.Maximum = maxY;
+            //    chart.ChartAreas[chartAreaName].AxisY.Minimum = minY;
+            //}
+            //else
+            //{
+            //    chart.ChartAreas[chartAreaName].AxisY.Maximum = (dampingConstantK * maxY) + ((1 - dampingConstantK) * chart.ChartAreas[chartAreaName].AxisY.Maximum);
+            //    chart.ChartAreas[chartAreaName].AxisY.Minimum = (dampingConstantK * minY) + ((1 - dampingConstantK) * chart.ChartAreas[chartAreaName].AxisY.Minimum);
+            //}
+
+#if PROFILER
+            // TODO1: OS24EVK-54 profiling: capture max interval, number of intervals, cumulative interval
+            _profilingStopwatchAutoScaleEvaluate.Stop();
+#endif // PROFILER
+        }
+
+        /// <summary>
+        /// Raw data format
+        /// </summary>
+        public DataFormats DataFormat = DataFormats.FormatUnsigned;
+
+        public enum DataFormats
+        {
+            /// <summary>
+            /// Interpret raw data as unsigned values
+            /// </summary>
+            FormatUnsigned,
+
+            /// <summary>
+            /// Interpret raw data as 16-bit, signed 2's complement values
+            /// </summary>
+            Format16bit2sComplement,
+        }
+
+    } // public class MedicalChartHelper
+    
+} // namespace Maxim.MAX30101
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HspGuiSourceV301/HSPGui/Model/ACLeadOff.cs	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,48 @@
+/*******************************************************************************
+* Copyright (C) 2016 Maxim Integrated Products, Inc., All rights Reserved.
+* 
+* This software is protected by copyright laws of the United States and
+* of foreign countries. This material may also be protected by patent laws
+* and technology transfer regulations of the United States and of foreign
+* countries. This software is furnished under a license agreement and/or a
+* nondisclosure agreement and may only be used or reproduced in accordance
+* with the terms of those agreements. Dissemination of this information to
+* any party or parties not specified in the license agreement and/or
+* nondisclosure agreement is expressly prohibited.
+*
+* The above copyright notice and this permission notice shall be included
+* in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+* OTHER DEALINGS IN THE SOFTWARE.
+*
+* Except as contained in this notice, the name of Maxim Integrated
+* Products, Inc. shall not be used except as stated in the Maxim Integrated
+* Products, Inc. Branding Policy.
+*
+* The mere transfer of this software does not imply any licenses
+* of trade secrets, proprietary technology, copyrights, patents,
+* trademarks, maskwork rights, or any other form of intellectual
+* property whatsoever. Maxim Integrated Products, Inc. retains all
+* ownership rights.
+*******************************************************************************
+*/
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace HealthSensorPlatform.Model
+{
+    public class ACLeadOff
+    {
+        public bool BioZOverRange;
+        public bool BioZUnderRange;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HspGuiSourceV301/HSPGui/Model/BioZEventArgs.cs	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,47 @@
+/*******************************************************************************
+* Copyright (C) 2016 Maxim Integrated Products, Inc., All rights Reserved.
+* 
+* This software is protected by copyright laws of the United States and
+* of foreign countries. This material may also be protected by patent laws
+* and technology transfer regulations of the United States and of foreign
+* countries. This software is furnished under a license agreement and/or a
+* nondisclosure agreement and may only be used or reproduced in accordance
+* with the terms of those agreements. Dissemination of this information to
+* any party or parties not specified in the license agreement and/or
+* nondisclosure agreement is expressly prohibited.
+*
+* The above copyright notice and this permission notice shall be included
+* in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+* OTHER DEALINGS IN THE SOFTWARE.
+*
+* Except as contained in this notice, the name of Maxim Integrated
+* Products, Inc. shall not be used except as stated in the Maxim Integrated
+* Products, Inc. Branding Policy.
+*
+* The mere transfer of this software does not imply any licenses
+* of trade secrets, proprietary technology, copyrights, patents,
+* trademarks, maskwork rights, or any other form of intellectual
+* property whatsoever. Maxim Integrated Products, Inc. retains all
+* ownership rights.
+*******************************************************************************
+*/
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace HealthSensorPlatform.Presenter
+{
+    public class BioZEventArgs : EventArgs
+    {
+        public double[] BioZValue;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HspGuiSourceV301/HSPGui/Model/DCLeadOff.cs	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,50 @@
+/*******************************************************************************
+* Copyright (C) 2016 Maxim Integrated Products, Inc., All rights Reserved.
+* 
+* This software is protected by copyright laws of the United States and
+* of foreign countries. This material may also be protected by patent laws
+* and technology transfer regulations of the United States and of foreign
+* countries. This software is furnished under a license agreement and/or a
+* nondisclosure agreement and may only be used or reproduced in accordance
+* with the terms of those agreements. Dissemination of this information to
+* any party or parties not specified in the license agreement and/or
+* nondisclosure agreement is expressly prohibited.
+*
+* The above copyright notice and this permission notice shall be included
+* in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+* OTHER DEALINGS IN THE SOFTWARE.
+*
+* Except as contained in this notice, the name of Maxim Integrated
+* Products, Inc. shall not be used except as stated in the Maxim Integrated
+* Products, Inc. Branding Policy.
+*
+* The mere transfer of this software does not imply any licenses
+* of trade secrets, proprietary technology, copyrights, patents,
+* trademarks, maskwork rights, or any other form of intellectual
+* property whatsoever. Maxim Integrated Products, Inc. retains all
+* ownership rights.
+*******************************************************************************
+*/
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace HealthSensorPlatform.Model
+{
+    public class DCLeadOff
+    {
+        public bool PostiveHigh;
+        public bool PostiveLow;
+        public bool NegativeHigh;
+        public bool NegativeLow;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HspGuiSourceV301/HSPGui/Model/DataLogModel.cs	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,250 @@
+/*******************************************************************************
+* Copyright (C) 2016 Maxim Integrated Products, Inc., All rights Reserved.
+* 
+* This software is protected by copyright laws of the United States and
+* of foreign countries. This material may also be protected by patent laws
+* and technology transfer regulations of the United States and of foreign
+* countries. This software is furnished under a license agreement and/or a
+* nondisclosure agreement and may only be used or reproduced in accordance
+* with the terms of those agreements. Dissemination of this information to
+* any party or parties not specified in the license agreement and/or
+* nondisclosure agreement is expressly prohibited.
+*
+* The above copyright notice and this permission notice shall be included
+* in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+* OTHER DEALINGS IN THE SOFTWARE.
+*
+* Except as contained in this notice, the name of Maxim Integrated
+* Products, Inc. shall not be used except as stated in the Maxim Integrated
+* Products, Inc. Branding Policy.
+*
+* The mere transfer of this software does not imply any licenses
+* of trade secrets, proprietary technology, copyrights, patents,
+* trademarks, maskwork rights, or any other form of intellectual
+* property whatsoever. Maxim Integrated Products, Inc. retains all
+* ownership rights.
+*******************************************************************************
+*/
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+using RPCSupport;
+using RPCSupport.Streaming;
+using RPCSupport.DataLogging;
+
+namespace HealthSensorPlatform.Model
+{
+    class DataLogModel : IDataLogModel
+    {
+        RPCClient rpcClient;
+        StreamDataLog streamDataLog;
+        EventHandler<PartialArrayIntAvailableEventArgs> onStreamDataHandler; 
+
+        Mission missionSettings;
+
+        public DataLogModel(RPCClient rpcClient)
+        {
+            this.rpcClient = rpcClient;
+        }
+
+        public Mission MissionSettings 
+        { 
+            get
+            {
+                return missionSettings;
+            }
+        }
+
+        public event EventHandler<EventArgs> LogStreamDone;
+        public event EventHandler<PartialArrayIntAvailableEventArgs> LogData;
+
+        public void Start()
+        {
+            onStreamDataHandler = new EventHandler<PartialArrayIntAvailableEventArgs>(OnStreamData);
+            rpcClient.streaming.PartialArrayIntAvailable += onStreamDataHandler;
+            streamDataLog = new StreamDataLog(rpcClient);
+
+            streamDataLog.Start();
+        }
+
+        public void EraseWrittenSectors()
+        {
+            ((SerialWrapPipeline)rpcClient.Pipeline).ReadTimeout = 180000;
+            rpcClient.DataLogging.EraseWrittenSectors();
+            ((SerialWrapPipeline)rpcClient.Pipeline).ReadTimeout = 1000;
+        }
+
+        public void MissionStartDefinition()
+        {
+            rpcClient.DataLogging.MissionStartDefinition();
+        }
+
+        public void MissionWrite()
+        {
+            rpcClient.DataLogging.MissionWrite();
+        }
+
+        public void MissionErase()
+        {
+            rpcClient.DataLogging.EraseMission();
+        }
+
+        public void MissionRead()
+        {
+            rpcClient.DataLogging.MissionRead();
+
+            missionSettings = new Mission();
+            // pre cmd
+            missionSettings.PreCommand = rpcClient.DataLogging.PreCommand.cmdString;
+            // ecg
+            missionSettings.EnableEcg = rpcClient.DataLogging.MAX30001_Ecg.IsExistsInDeviceMission();
+            if (missionSettings.EnableEcg)
+                missionSettings.EcgArgs = rpcClient.DataLogging.MAX30001_Ecg.ToIntArray();
+            // pace
+            missionSettings.EnablePace = rpcClient.DataLogging.MAX30001_Pace.IsExistsInDeviceMission();
+            if (missionSettings.EnablePace)
+                missionSettings.PaceArgs = rpcClient.DataLogging.MAX30001_Pace.ToIntArray();
+            // bioz
+            missionSettings.EnableBioZ = rpcClient.DataLogging.MAX30001_Bioz.IsExistsInDeviceMission();
+            if (missionSettings.EnableBioZ)
+                missionSettings.BioZArgs = rpcClient.DataLogging.MAX30001_Bioz.ToIntArray();
+            // RtoR
+            missionSettings.EnableRToR = rpcClient.DataLogging.MAX30001_RtoR.IsExistsInDeviceMission();
+            if (missionSettings.EnableRToR)
+                missionSettings.RToRArgs = rpcClient.DataLogging.MAX30001_RtoR.ToIntArray();
+            // Rbias, FMSTR
+            //missionSettings.EnableRBias = rpcClient.DataLogging.MAX30001_Rbias.IsExistsInDeviceMission();
+            missionSettings.EnableRBias = missionSettings.EnableRBias | missionSettings.EnableEcg | missionSettings.EnableBioZ | missionSettings.EnableRToR | missionSettings.EnablePace;
+            if (missionSettings.EnableRBias)
+                missionSettings.RBiasArgs = rpcClient.DataLogging.MAX30001_Rbias_Fmstr.ToIntArray();
+            // SpO2
+            missionSettings.EnableOpticalSpO2 = rpcClient.DataLogging.MAX30101_SpO2.IsExistsInDeviceMission();
+            if (missionSettings.EnableOpticalSpO2)
+                missionSettings.SpO2HRModeArgs = rpcClient.DataLogging.MAX30101_SpO2.ToIntArray();
+            // HR
+            missionSettings.EnableOpticalHR = rpcClient.DataLogging.MAX30101_HR.IsExistsInDeviceMission();
+            if (missionSettings.EnableOpticalHR)
+                missionSettings.HRModeArgs = rpcClient.DataLogging.MAX30101_HR.ToIntArray();
+            // Multi
+            missionSettings.EnableOpticalMulti = rpcClient.DataLogging.MAX30101_Multi.IsExistsInDeviceMission();
+            if (missionSettings.EnableOpticalMulti)
+                missionSettings.MultiModeArgs = rpcClient.DataLogging.MAX30101_Multi.ToIntArray();
+
+            // Temp1
+            missionSettings.EnableTemperature1 = rpcClient.DataLogging.MAX31725_1.IsExistsInDeviceMission();
+            if (missionSettings.EnableTemperature1)
+                missionSettings.Temperature1Parameters = rpcClient.DataLogging.MAX31725_1.ToIntArray();
+            // Temp2
+            missionSettings.EnableTemperature2 = rpcClient.DataLogging.MAX31725_2.IsExistsInDeviceMission();
+            if (missionSettings.EnableTemperature2)
+                missionSettings.Temperature2Parameters = rpcClient.DataLogging.MAX31725_2.ToIntArray();
+            // Accel
+            missionSettings.EnableAccelerometer = rpcClient.DataLogging.LIS2DH.IsExistsInDeviceMission();
+            if (missionSettings.EnableAccelerometer)
+                missionSettings.AccelerometerParameters = rpcClient.DataLogging.LIS2DH.ToIntArray();
+            // Pressure
+            missionSettings.EnablePressure = rpcClient.DataLogging.BMP280.IsExistsInDeviceMission();
+            if (missionSettings.EnablePressure)
+                missionSettings.PressureParameters = rpcClient.DataLogging.BMP280.ToIntArray();
+
+
+            // post cmd
+            missionSettings.PostCommand = rpcClient.DataLogging.PostCommand.cmdString;
+
+        }
+
+        public string[] MissionString()
+        {
+            string[] missionStrings = rpcClient.DataLogging.MissionStrings();
+
+            List<string> stringList = new List<string>(missionStrings);
+
+            if (stringList[0] == "null")
+                stringList.RemoveAt(0);
+
+            if (stringList.Count > 0 && stringList[stringList.Count - 1] == "null")
+            {
+                stringList.RemoveAt(stringList.Count - 1);
+            }
+
+            return stringList.ToArray();
+        }
+
+        public void OnStreamData(object sender, PartialArrayIntAvailableEventArgs e)
+        {
+            if (e.reportID == PartialArrayIntAvailableEventArgs.PACKET_END_OF_STREAM)
+            {
+                if (LogStreamDone != null)
+                    LogStreamDone(this, e);
+
+                rpcClient.streaming.PartialArrayIntAvailable -= onStreamDataHandler;
+
+            }
+
+            if (LogData != null)
+                LogData(this, e);
+        }
+    }
+
+    public class Mission
+    {
+        public string PreCommand;
+        public bool EnableEcg;
+        public int[] EcgArgs;
+
+        public bool EnablePace;
+        public int[] PaceArgs;
+
+        public bool EnableBioZ;
+        public int[] BioZArgs;
+
+        public bool EnableRToR;
+        public int[] RToRArgs;
+
+        public bool EnableRBias;
+        public int[] RBiasArgs;
+
+        public bool EnableOpticalSpO2;
+        public int[] SpO2HRModeArgs;
+
+        public bool EnableOpticalHR;
+        public int[] HRModeArgs;
+
+        public bool EnableOpticalMulti;
+        public int[] MultiModeArgs;
+
+        public bool EnableTemperature1;
+        public int[] Temperature1Parameters;
+
+        public bool EnableTemperature2;
+        public int[] Temperature2Parameters;
+
+        public bool EnablePressure;
+        public int[] PressureParameters;
+
+        public bool EnableAccelerometer;
+        public int[] AccelerometerParameters;
+
+        public string PostCommand;
+
+        public bool Enable
+        {
+            get
+            {
+                return EnableEcg | EnablePace | EnableBioZ | EnableRToR | EnableRBias
+                    | EnableOpticalSpO2 | EnableOpticalHR | EnableOpticalMulti
+                    | EnableTemperature1 | EnableTemperature2 | EnablePressure | EnableAccelerometer; 
+            }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HspGuiSourceV301/HSPGui/Model/EcgEventArgs.cs	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,47 @@
+/*******************************************************************************
+* Copyright (C) 2016 Maxim Integrated Products, Inc., All rights Reserved.
+* 
+* This software is protected by copyright laws of the United States and
+* of foreign countries. This material may also be protected by patent laws
+* and technology transfer regulations of the United States and of foreign
+* countries. This software is furnished under a license agreement and/or a
+* nondisclosure agreement and may only be used or reproduced in accordance
+* with the terms of those agreements. Dissemination of this information to
+* any party or parties not specified in the license agreement and/or
+* nondisclosure agreement is expressly prohibited.
+*
+* The above copyright notice and this permission notice shall be included
+* in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+* OTHER DEALINGS IN THE SOFTWARE.
+*
+* Except as contained in this notice, the name of Maxim Integrated
+* Products, Inc. shall not be used except as stated in the Maxim Integrated
+* Products, Inc. Branding Policy.
+*
+* The mere transfer of this software does not imply any licenses
+* of trade secrets, proprietary technology, copyrights, patents,
+* trademarks, maskwork rights, or any other form of intellectual
+* property whatsoever. Maxim Integrated Products, Inc. retains all
+* ownership rights.
+*******************************************************************************
+*/
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace HealthSensorPlatform.Presenter
+{
+    public class EcgEventArgs : EventArgs
+    {
+        public double[] EcgValue;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HspGuiSourceV301/HSPGui/Model/FifoStruct.cs	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,86 @@
+/*******************************************************************************
+* Copyright (C) 2016 Maxim Integrated Products, Inc., All rights Reserved.
+* 
+* This software is protected by copyright laws of the United States and
+* of foreign countries. This material may also be protected by patent laws
+* and technology transfer regulations of the United States and of foreign
+* countries. This software is furnished under a license agreement and/or a
+* nondisclosure agreement and may only be used or reproduced in accordance
+* with the terms of those agreements. Dissemination of this information to
+* any party or parties not specified in the license agreement and/or
+* nondisclosure agreement is expressly prohibited.
+*
+* The above copyright notice and this permission notice shall be included
+* in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+* OTHER DEALINGS IN THE SOFTWARE.
+*
+* Except as contained in this notice, the name of Maxim Integrated
+* Products, Inc. shall not be used except as stated in the Maxim Integrated
+* Products, Inc. Branding Policy.
+*
+* The mere transfer of this software does not imply any licenses
+* of trade secrets, proprietary technology, copyrights, patents,
+* trademarks, maskwork rights, or any other form of intellectual
+* property whatsoever. Maxim Integrated Products, Inc. retains all
+* ownership rights.
+*******************************************************************************
+*/
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace HealthSensorPlatform.Model
+{
+    public struct EcgFifo
+    {
+        /// <summary>
+        /// ECG in millivolts
+        /// </summary>
+        public double Data;
+        /// <summary>
+        /// ECG FIFO raw code
+        /// </summary>
+        public int Code;
+        /// <summary>
+        /// ECG_DATA bit field
+        /// </summary>
+        public int EcgData;
+        /// <summary>
+        /// PTAG bit field
+        /// </summary>
+        public int PTag;
+        /// <summary>
+        /// ETAG bit field
+        /// </summary>
+        public int ETag;
+    }
+
+    public struct BioZFifo
+    {
+        /// <summary>
+        /// BioZ in Ohms
+        /// </summary>
+        public double Data;
+        /// <summary>
+        /// BIOZ FIFO raw code
+        /// </summary>
+        public int Code;
+        /// <summary>
+        /// BIOZ_DATA bit field
+        /// </summary>
+        public int BioZData;
+        /// <summary>
+        /// BTAG bit field
+        /// </summary>
+        public int BTag;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HspGuiSourceV301/HSPGui/Model/IDataLogModel.cs	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,57 @@
+/*******************************************************************************
+* Copyright (C) 2016 Maxim Integrated Products, Inc., All rights Reserved.
+* 
+* This software is protected by copyright laws of the United States and
+* of foreign countries. This material may also be protected by patent laws
+* and technology transfer regulations of the United States and of foreign
+* countries. This software is furnished under a license agreement and/or a
+* nondisclosure agreement and may only be used or reproduced in accordance
+* with the terms of those agreements. Dissemination of this information to
+* any party or parties not specified in the license agreement and/or
+* nondisclosure agreement is expressly prohibited.
+*
+* The above copyright notice and this permission notice shall be included
+* in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+* OTHER DEALINGS IN THE SOFTWARE.
+*
+* Except as contained in this notice, the name of Maxim Integrated
+* Products, Inc. shall not be used except as stated in the Maxim Integrated
+* Products, Inc. Branding Policy.
+*
+* The mere transfer of this software does not imply any licenses
+* of trade secrets, proprietary technology, copyrights, patents,
+* trademarks, maskwork rights, or any other form of intellectual
+* property whatsoever. Maxim Integrated Products, Inc. retains all
+* ownership rights.
+*******************************************************************************
+*/
+
+using System;
+namespace HealthSensorPlatform.Model
+{
+    interface IDataLogModel
+    {
+
+        Mission MissionSettings { get; }
+
+        event EventHandler<RPCSupport.Streaming.PartialArrayIntAvailableEventArgs> LogData;
+        event EventHandler<EventArgs> LogStreamDone;
+        void OnStreamData(object sender, RPCSupport.Streaming.PartialArrayIntAvailableEventArgs e);
+        void Start();
+
+        void EraseWrittenSectors();
+        void MissionStartDefinition();
+        void MissionWrite();
+        void MissionRead();
+        void MissionErase();
+
+        string[] MissionString();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HspGuiSourceV301/HSPGui/Model/ITemperatureModel.cs	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,53 @@
+/*******************************************************************************
+* Copyright (C) 2016 Maxim Integrated Products, Inc., All rights Reserved.
+* 
+* This software is protected by copyright laws of the United States and
+* of foreign countries. This material may also be protected by patent laws
+* and technology transfer regulations of the United States and of foreign
+* countries. This software is furnished under a license agreement and/or a
+* nondisclosure agreement and may only be used or reproduced in accordance
+* with the terms of those agreements. Dissemination of this information to
+* any party or parties not specified in the license agreement and/or
+* nondisclosure agreement is expressly prohibited.
+*
+* The above copyright notice and this permission notice shall be included
+* in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+* OTHER DEALINGS IN THE SOFTWARE.
+*
+* Except as contained in this notice, the name of Maxim Integrated
+* Products, Inc. shall not be used except as stated in the Maxim Integrated
+* Products, Inc. Branding Policy.
+*
+* The mere transfer of this software does not imply any licenses
+* of trade secrets, proprietary technology, copyrights, patents,
+* trademarks, maskwork rights, or any other form of intellectual
+* property whatsoever. Maxim Integrated Products, Inc. retains all
+* ownership rights.
+*******************************************************************************
+*/
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace MAX30205EVKit.Model
+{
+    interface ITemperatureModel
+    {
+        bool DataFormat { get; }
+
+        int[] Registers { get; }
+
+        void RegWrite(int regAddress, int regValue);
+        int RegRead(int regAddress);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HspGuiSourceV301/HSPGui/Model/MAX30001.cs	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,88 @@
+/*******************************************************************************
+* Copyright (C) 2016 Maxim Integrated Products, Inc., All rights Reserved.
+* 
+* This software is protected by copyright laws of the United States and
+* of foreign countries. This material may also be protected by patent laws
+* and technology transfer regulations of the United States and of foreign
+* countries. This software is furnished under a license agreement and/or a
+* nondisclosure agreement and may only be used or reproduced in accordance
+* with the terms of those agreements. Dissemination of this information to
+* any party or parties not specified in the license agreement and/or
+* nondisclosure agreement is expressly prohibited.
+*
+* The above copyright notice and this permission notice shall be included
+* in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+* OTHER DEALINGS IN THE SOFTWARE.
+*
+* Except as contained in this notice, the name of Maxim Integrated
+* Products, Inc. shall not be used except as stated in the Maxim Integrated
+* Products, Inc. Branding Policy.
+*
+* The mere transfer of this software does not imply any licenses
+* of trade secrets, proprietary technology, copyrights, patents,
+* trademarks, maskwork rights, or any other form of intellectual
+* property whatsoever. Maxim Integrated Products, Inc. retains all
+* ownership rights.
+*******************************************************************************
+*/
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+using RPCSupport;
+
+namespace HealthSensorPlatform.Model
+{
+    public class MAX30001Model
+    {
+        RPCSupport.Devices.MAX30001 max30001; 
+
+        public Part PartID;
+
+        public MAX30001Model(RPCSupport.Devices.MAX30001 max30001)
+        {
+            this.max30001 = max30001;
+
+            PartID = partID();
+        }
+
+        private Part partID()
+        {
+            int data;
+            Part part;
+            
+            data = max30001.ReadReg(0x0F);
+
+            part = (Part)((data >> 12) & 0x3);
+
+            return part; 
+        }
+
+        public enum Part
+        {
+            MAX30004 = 0,
+            MAX30001 = 1,
+            MAX30002 = 2,
+            MAX30003 = 3,
+        }
+
+        public void Write(int register, int data)
+        {
+            max30001.WriteReg((byte)register, data);
+        }
+
+        public int Read(int register)
+        {
+            return max30001.ReadReg((byte)register);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HspGuiSourceV301/HSPGui/Model/MAX30205Model.cs	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,118 @@
+/*******************************************************************************
+* Copyright (C) 2016 Maxim Integrated Products, Inc., All rights Reserved.
+* 
+* This software is protected by copyright laws of the United States and
+* of foreign countries. This material may also be protected by patent laws
+* and technology transfer regulations of the United States and of foreign
+* countries. This software is furnished under a license agreement and/or a
+* nondisclosure agreement and may only be used or reproduced in accordance
+* with the terms of those agreements. Dissemination of this information to
+* any party or parties not specified in the license agreement and/or
+* nondisclosure agreement is expressly prohibited.
+*
+* The above copyright notice and this permission notice shall be included
+* in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+* OTHER DEALINGS IN THE SOFTWARE.
+*
+* Except as contained in this notice, the name of Maxim Integrated
+* Products, Inc. shall not be used except as stated in the Maxim Integrated
+* Products, Inc. Branding Policy.
+*
+* The mere transfer of this software does not imply any licenses
+* of trade secrets, proprietary technology, copyrights, patents,
+* trademarks, maskwork rights, or any other form of intellectual
+* property whatsoever. Maxim Integrated Products, Inc. retains all
+* ownership rights.
+*******************************************************************************
+*/
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using MAX30205EVKit.Model;
+using RPCSupport.Devices;
+
+namespace HealthSensorPlatform.Model
+{
+    class MAX30205Model : ITemperatureModel
+    {
+        private I2cDevice i2cDevice; 
+        private 
+        byte i2cAddress;
+        int[] registers = new int[4];
+
+        public MAX30205Model(I2cDevice i2cDevice, byte i2cAddress)
+        {
+            this.i2cDevice = i2cDevice;
+            this.i2cAddress = i2cAddress;
+        }
+
+                /* Properties */
+        public bool DataFormat
+        {
+            get
+            {
+                return ((registers[1] >> 5) & 0x01) == 0x01 ? true : false;
+            }
+        }
+
+        public int[] Registers
+        {
+            get
+            {
+                return registers;
+            }
+        }
+
+        public void RegWrite(int regAddress, int regValue)
+        {
+
+            if ((regAddress == 0x02 || regAddress == 0x03))
+            {
+                //base.RegWrite(regAddress, new byte[] { (byte)((regValue >> 8) & 0xFF), (byte)(regValue & 0xFF) });
+                i2cDevice.WriteRead(1, i2cAddress, new byte[] { (byte)regAddress, (byte)((regValue >> 8) & 0xFF), (byte)(regValue & 0xFF) }, 0);
+            }
+            else
+            {
+                //base.RegWrite(regAddress, regValue);
+                i2cDevice.WriteReg(1, i2cAddress, (byte)regAddress, (byte)regValue);
+            }
+
+
+            System.Diagnostics.Debug.Print("RegWrite: " + regAddress.ToString("X2") + " " + regValue.ToString("X4"));
+        }
+
+        public int RegRead(int regAddress)
+        {
+            int result;
+            byte[] readResult;
+
+            switch (regAddress)
+            {
+                case 0x00:
+                case 0x02:
+                case 0x03:
+                    readResult = i2cDevice.ReadMultiReg(1, (byte)i2cAddress, (byte)regAddress, 2);//base.RegRead(regAddress, 2);
+                    result = readResult[0] << 8 | readResult[1];
+                    break;
+                default:
+                    result = i2cDevice.ReadReg(1, (byte)i2cAddress, (byte)regAddress); //base.RegRead(regAddress, 1);
+                    break;
+            }
+
+            registers[regAddress] = result;
+
+            System.Diagnostics.Debug.Print("RegRead: " + regAddress.ToString("X2") + " " + result.ToString("X4"));
+
+            return result;
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HspGuiSourceV301/HSPGui/Model/PaceData.cs	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,166 @@
+/*******************************************************************************
+* Copyright (C) 2016 Maxim Integrated Products, Inc., All rights Reserved.
+* 
+* This software is protected by copyright laws of the United States and
+* of foreign countries. This material may also be protected by patent laws
+* and technology transfer regulations of the United States and of foreign
+* countries. This software is furnished under a license agreement and/or a
+* nondisclosure agreement and may only be used or reproduced in accordance
+* with the terms of those agreements. Dissemination of this information to
+* any party or parties not specified in the license agreement and/or
+* nondisclosure agreement is expressly prohibited.
+*
+* The above copyright notice and this permission notice shall be included
+* in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+* OTHER DEALINGS IN THE SOFTWARE.
+*
+* Except as contained in this notice, the name of Maxim Integrated
+* Products, Inc. shall not be used except as stated in the Maxim Integrated
+* Products, Inc. Branding Policy.
+*
+* The mere transfer of this software does not imply any licenses
+* of trade secrets, proprietary technology, copyrights, patents,
+* trademarks, maskwork rights, or any other form of intellectual
+* property whatsoever. Maxim Integrated Products, Inc. retains all
+* ownership rights.
+*******************************************************************************
+*/
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace HealthSensorPlatform.Model
+{
+    /// <summary>
+    /// Store and parse all the Pace burst read data
+    /// </summary>
+    public class PaceData 
+    {
+        private PaceRegister[] Group = new PaceRegister[6];
+
+        /// <summary>
+        /// Raw pace data from HSP firmware
+        /// </summary>
+        /// <param name="rawData"></param>
+        public PaceData(int[] rawData)
+        {
+            if (rawData.Length == 18)
+            {
+                for (int i = 0; i < 6; i++)
+                {
+                    Group[i] = new PaceRegister(new int[] { rawData[3 * i + 0], rawData[3 * i + 1], rawData[3 * i + 2] });
+                }
+            }
+            else
+            {
+                throw new InvalidOperationException("Pace register group expects array length of 18.");
+            }
+        }
+
+        /// <summary>
+        /// Calculate the time between first pace event and last event
+        /// </summary>
+        /// <param name="group"></param>
+        /// <returns>Time count unit difference. To obtain the time value multiply the count by PACE_RES = 1/FPACE</returns>
+        public int PaceLength(int group)
+        {
+            int start = 0, stop = 0;
+            int sign = 1;
+
+            start = Group[group].Edge[0].Data;
+            sign = Group[group].Edge[0].Polarity == true ? 1 : -1;
+
+            foreach (PaceEdge time in Group[group].Edge)
+            {
+                if (time.Last == true)
+                {
+                    stop = time.Data;
+                    break;
+                }
+            }
+
+            return sign * (stop - start);
+        }
+
+        public PaceRegister PaceGroup(int group)
+        {
+            return Group[group];
+        }
+
+        public string GroupToString(int group)
+        {
+            StringBuilder sb = new StringBuilder();
+
+            foreach (PaceEdge pe in Group[group].Edge)
+            {
+                sb.Append(pe.Data);
+                sb.Append(", ");
+                sb.Append(pe.Polarity ? 'R' : 'F');
+                sb.Append(", ");
+                sb.Append(pe.Last ? 'Y' : 'N');
+                sb.Append(", ");
+            }
+
+            return sb.ToString();
+        }
+
+        public static string GroupEmptyString()
+        {
+            return "0, R, Y, 0, R, Y, 0, R, Y, 0, R, Y, 0, R, Y, 0, R, Y";
+        }
+
+
+        ///// Inner classes of PaceData ////
+
+        /// <summary>
+        /// Pace edge information
+        /// </summary>
+        public class PaceEdge
+        {
+            public int Data;
+            public bool Polarity;
+            public bool Last;
+
+            public PaceEdge(int data)
+            {
+                Data = data >> 2;
+                Polarity = ((data & 0x02) >> 1) == 1 ? true : false;
+                Last = ((data & 0x01) >> 0) == 1 ? true : false;
+            }
+        }
+
+        /// <summary>
+        /// Pace register information, each pace register contains up to 6 pace edge events
+        /// </summary>
+        public class PaceRegister
+        {
+            private PaceEdge[] Bytes = new PaceEdge[6];
+
+            public PaceEdge[] Edge
+            {
+                get { return Bytes; }
+            }
+
+            public PaceRegister(int[] groupData)
+            {
+                if (groupData.Length == 3)
+                {
+                    for (int i = 0; i < 3; i++)
+                    {
+                        Bytes[2 * i] = new PaceEdge(groupData[i] >> 12);
+                        Bytes[2 * i + 1] = new PaceEdge(groupData[i] & 0xFFF);
+                    }
+                }
+            }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HspGuiSourceV301/HSPGui/Model/PaceEventArgs.cs	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,49 @@
+/*******************************************************************************
+* Copyright (C) 2016 Maxim Integrated Products, Inc., All rights Reserved.
+* 
+* This software is protected by copyright laws of the United States and
+* of foreign countries. This material may also be protected by patent laws
+* and technology transfer regulations of the United States and of foreign
+* countries. This software is furnished under a license agreement and/or a
+* nondisclosure agreement and may only be used or reproduced in accordance
+* with the terms of those agreements. Dissemination of this information to
+* any party or parties not specified in the license agreement and/or
+* nondisclosure agreement is expressly prohibited.
+*
+* The above copyright notice and this permission notice shall be included
+* in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+* OTHER DEALINGS IN THE SOFTWARE.
+*
+* Except as contained in this notice, the name of Maxim Integrated
+* Products, Inc. shall not be used except as stated in the Maxim Integrated
+* Products, Inc. Branding Policy.
+*
+* The mere transfer of this software does not imply any licenses
+* of trade secrets, proprietary technology, copyrights, patents,
+* trademarks, maskwork rights, or any other form of intellectual
+* property whatsoever. Maxim Integrated Products, Inc. retains all
+* ownership rights.
+*******************************************************************************
+*/
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+using HealthSensorPlatform.CustomControls;
+
+namespace HealthSensorPlatform.Model
+{
+    public class PaceEventArgs : EventArgs
+    {
+        public PaceData PaceGroups;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HspGuiSourceV301/HSPGui/Model/RToREventArgs.cs	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,47 @@
+/*******************************************************************************
+* Copyright (C) 2016 Maxim Integrated Products, Inc., All rights Reserved.
+* 
+* This software is protected by copyright laws of the United States and
+* of foreign countries. This material may also be protected by patent laws
+* and technology transfer regulations of the United States and of foreign
+* countries. This software is furnished under a license agreement and/or a
+* nondisclosure agreement and may only be used or reproduced in accordance
+* with the terms of those agreements. Dissemination of this information to
+* any party or parties not specified in the license agreement and/or
+* nondisclosure agreement is expressly prohibited.
+*
+* The above copyright notice and this permission notice shall be included
+* in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+* OTHER DEALINGS IN THE SOFTWARE.
+*
+* Except as contained in this notice, the name of Maxim Integrated
+* Products, Inc. shall not be used except as stated in the Maxim Integrated
+* Products, Inc. Branding Policy.
+*
+* The mere transfer of this software does not imply any licenses
+* of trade secrets, proprietary technology, copyrights, patents,
+* trademarks, maskwork rights, or any other form of intellectual
+* property whatsoever. Maxim Integrated Products, Inc. retains all
+* ownership rights.
+*******************************************************************************
+*/
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace HealthSensorPlatform.Presenter
+{
+    public class RToREventArgs : EventArgs
+    {
+        public double Interval;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HspGuiSourceV301/HSPGui/NimitzHID.cs	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,500 @@
+using Microsoft.VisualBasic;
+using System;
+using System.Collections;
+using System.Data;
+using System.Diagnostics;
+using System.Drawing;
+using System.Windows.Forms;
+using Microsoft.Win32.SafeHandles;
+using System.Runtime.InteropServices;
+
+
+namespace SimpleHID
+{
+    class NimitzHID
+    {
+        internal const byte COMMAND_SUCCEED = 0xEE;
+        internal const byte COMMAND_FAILED = 0xFA;
+
+        // private IntPtr deviceNotificationHandle;
+        // private Boolean exclusiveAccess;
+        private SafeFileHandle hidHandle;
+        private String hidUsage;
+        private Boolean myDeviceDetected;
+        private String myDevicePathName;
+        private SafeFileHandle readHandle;
+        private SafeFileHandle writeHandle;
+
+        // private Debugging MyDebugging = new Debugging(); //  For viewing results of API calls via Debug.Write.
+        private Guid hidGuid;
+        private IntPtr deviceNotificationHandle = System.IntPtr.Zero;
+        private HID myHID;
+
+        //internal FrmMain FrmMy;
+
+        ///  <summary>
+        ///  Define a class of delegates that point to the Hid.ReportIn.Read function.
+        ///  The delegate has the same parameters as Hid.ReportIn.Read.
+        ///  Used for asynchronous reads from the device.       
+        ///  </summary>
+
+        private delegate void ReadInputReportDelegate(SafeFileHandle hidHandle, SafeFileHandle readHandle, SafeFileHandle writeHandle, ref Boolean myDeviceDetected, ref Byte[] readBuffer, ref Boolean success);
+
+        //  This delegate has the same parameters as AccessForm.
+        //  Used in accessing the application's form from a different thread.
+
+        private delegate void MarshalToForm(String action, String textToAdd);
+        ///  <summary>
+        ///  Uses a series of API calls to locate a HID-class device
+        ///  by its Vendor ID and Product ID.
+        ///  </summary>
+        ///          
+        ///  <returns>
+        ///   True if the device is detected, False if not detected.
+        ///  </returns>
+
+        internal Boolean OpenNimitzH()
+        {
+            Boolean deviceFound = false;
+            String[] devicePathName = new String[128];
+            Guid hidGuid = Guid.Empty;
+            Int32 memberIndex = 0;
+            Int32 myProductID = 0x1365;
+            Int32 myVendorID = 0x0B6A;
+            Boolean success = false;
+
+            myDeviceDetected = false;
+
+            myHID.findHIDs();
+
+            //  ***
+            //  API function: 'HidD_GetHidGuid
+            //  Purpose: Retrieves the interface class GUID for the HID class.
+            //  Accepts: 'A System.Guid object for storing the GUID.
+            //  ***
+
+            Hid.HidD_GetHidGuid(ref hidGuid);
+
+            //  Fill an array with the device path names of all attached HIDs.
+
+            deviceFound = MyDeviceManagement.FindDeviceFromGuid(hidGuid, ref devicePathName);
+
+            //  If there is at least one HID, attempt to read the Vendor ID and Product ID
+            //  of each device until there is a match or all devices have been examined.
+
+            if (deviceFound)
+            {
+                memberIndex = 0;
+
+                do
+                {
+                    //  ***
+                    //  API function:
+                    //  CreateFile
+                    //  Purpose:
+                    //  Retrieves a handle to a device.
+                    //  Accepts:
+                    //  A device path name returned by SetupDiGetDeviceInterfaceDetail
+                    //  The type of access requested (read/write).
+                    //  FILE_SHARE attributes to allow other processes to access the device while this handle is open.
+                    //  A Security structure or IntPtr.Zero. 
+                    //  A creation disposition value. Use OPEN_EXISTING for devices.
+                    //  Flags and attributes for files. Not used for devices.
+                    //  Handle to a template file. Not used.
+                    //  Returns: a handle without read or write access.
+                    //  This enables obtaining information about all HIDs, even system
+                    //  keyboards and mice. 
+                    //  Separate handles are used for reading and writing.
+                    //  ***
+                    hidHandle = FileIO.CreateFile(devicePathName[memberIndex], 0, FileIO.FILE_SHARE_READ | FileIO.FILE_SHARE_WRITE, IntPtr.Zero, FileIO.OPEN_EXISTING, 0, 0);
+
+                    if (!hidHandle.IsInvalid)
+                    {
+                        //  The returned handle is valid, 
+                        //  so find out if this is the device we're looking for.
+
+                        //  Set the Size property of DeviceAttributes to the number of bytes in the structure.
+                        MyHid.DeviceAttributes.Size = Marshal.SizeOf(MyHid.DeviceAttributes);
+
+                        //  ***
+                        //  API function:
+                        //  HidD_GetAttributes
+
+                        //  Purpose:
+                        //  Retrieves a HIDD_ATTRIBUTES structure containing the Vendor ID, 
+                        //  Product ID, and Product Version Number for a device.
+
+                        //  Accepts:
+                        //  A handle returned by CreateFile.
+                        //  A pointer to receive a HIDD_ATTRIBUTES structure.
+
+                        //  Returns:
+                        //  True on success, False on failure.
+                        //  ***                            
+
+                        success = Hid.HidD_GetAttributes(hidHandle, ref MyHid.DeviceAttributes);
+
+                        if (success)
+                        {
+                            //  Find out if the device matches the one we're looking for.
+                            if ((MyHid.DeviceAttributes.VendorID == myVendorID) && (MyHid.DeviceAttributes.ProductID == myProductID))
+                            {
+                                myDeviceDetected = true;
+                                //  Save the DevicePathName for OnDeviceChange().
+                                myDevicePathName = devicePathName[memberIndex];
+                            }
+                            else
+                            {
+                                //  It's not a match, so close the handle.
+                                myDeviceDetected = false;
+                                hidHandle.Close();
+                            }
+                        }
+                        else
+                        {
+                            //  There was a problem in retrieving the information.
+                            myDeviceDetected = false;
+                            hidHandle.Close();
+                        }
+                    }
+
+                    //  Keep looking until we find the device or there are no devices left to examine.
+                    memberIndex = memberIndex + 1;
+                }
+                while (!((myDeviceDetected || (memberIndex == devicePathName.Length))));
+            }
+
+            if (myDeviceDetected)
+            {
+                //  The device was detected.
+                //  Learn the capabilities of the device.
+                MyHid.Capabilities = MyHid.GetDeviceCapabilities(hidHandle);
+
+                //  Find out if the device is a system mouse or keyboard.
+                hidUsage = MyHid.GetHidUsage(MyHid.Capabilities);
+
+                //  Get handles to use in requesting Input and Output reports.
+                readHandle = FileIO.CreateFile(myDevicePathName, FileIO.GENERIC_READ, FileIO.FILE_SHARE_READ | FileIO.FILE_SHARE_WRITE, IntPtr.Zero, FileIO.OPEN_EXISTING, FileIO.FILE_FLAG_OVERLAPPED, 0);
+                writeHandle = FileIO.CreateFile(myDevicePathName, FileIO.GENERIC_WRITE, FileIO.FILE_SHARE_READ | FileIO.FILE_SHARE_WRITE, IntPtr.Zero, FileIO.OPEN_EXISTING, 0, 0);
+
+                //  Flush any waiting reports in the input buffer. (optional)
+                MyHid.FlushQueue(readHandle);
+            }
+            return myDeviceDetected;
+        }
+
+        internal void CloseNimitzH()
+        {
+            if (!(hidHandle == null))
+            {
+                if (!(hidHandle.IsInvalid))
+                {
+                    hidHandle.Close();
+                }
+            }
+
+            if (!(readHandle == null))
+            {
+                if (!(readHandle.IsInvalid))
+                {
+                    readHandle.Close();
+                }
+            }
+
+            if (!(writeHandle == null))
+            {
+                if (!(writeHandle.IsInvalid))
+                {
+                    writeHandle.Close();
+                }
+            }
+        }
+
+        // This function only checks the status variable and does not actively check
+        // if the NimitzH is still present.  This function
+        // only checks the variable to avoid any timeout delays.
+        internal Boolean NimitzHPresent()
+        {
+            if (myDeviceDetected)
+                return true;
+            else
+                return false;
+        }
+
+        //////////////////////////////////////////////////////////////////////
+        // Functions that can be called once NimitzH is opened
+        //////////////////////////////////////////////////////////////////////
+
+        // This function calls the NimitzH Read Revision command.
+        // This is done by sending 0xC2, and then receiving 1 byte major rev, then 1byte minor Rev, and then 0xD2
+        // This function returns firmware MAJORVERSION in upper word and MINORVERSION in lower word
+        // This function returns -1 if an error occurs
+
+        internal int GetFirmwareVersion()
+        {
+            Boolean success = false;
+            Byte[] inputBuffer = null;
+            Byte[] dataOut = new Byte[2];
+
+            dataOut[0] = 0x01;//number of bytes to send
+            dataOut[1] = 0x02;//firmware command
+
+            success = InputOutputReports(dataOut, ref inputBuffer);
+
+            if (!success)
+                return -1;
+
+            if (inputBuffer[2] == COMMAND_SUCCEED)
+                return (inputBuffer[3] << 16) + inputBuffer[4];
+            else
+                return -1;
+
+        }
+        internal Boolean TestSendPacket(byte[] sendData, ref byte[] readData)
+        {
+            Boolean success = false;
+            Byte[] inputBuffer = null;
+            byte numData = (byte)sendData.Length;
+            Byte[] dataOut = new Byte[3 + numData];
+
+            if ((numData > 62) || (numData < 0))
+                return false;			// Max packet size is 62 bytes
+
+            dataOut[0] = (byte)(0x02 + numData);//number of bytes to send (include command and data bytes)
+            dataOut[1] = 0x01;//command byte
+            dataOut[2] = (byte)(numData);//number of data bytes
+
+            for (int i = 0; i < numData; i++)
+                dataOut[i + 3] = sendData[i];
+
+            success = InputOutputReports(dataOut, ref inputBuffer);
+
+            if (!success)
+                return false;
+
+            for (int i = 0; i < numData; i++)
+                readData[i] = inputBuffer[i + 3];
+
+            if (inputBuffer[2] == COMMAND_SUCCEED)
+                return true;
+            else
+                return false;
+        }
+        /****************I2CPacketWrite****************/
+        /* Description: Generates the correct sequence of events on the I2C bus for a packet write (up to 60 data bytes) 
+        /* Information: New Implementation for packet writes ( SHOULD BE USED in most ALLL Writes/Read of and I2C Device )!!
+        /* Paramters: slaveAddress = slave address of DUT (R/W# is set in firmware), numBytes = Number of data bytes to write (1 to 60), 
+        /*	memoryaddress = Desired memory location, databuffer = pointer to the data to write on the buss*/
+        internal Boolean I2CWritePacket(Byte slaveAddress, Byte memoryaddress, Byte numBytes, Byte[] databuffer)
+        {
+            Boolean success = false;
+            Byte[] inputBuffer = null;
+            Byte[] dataOut = new Byte[64];
+
+            if ((numBytes > 59) || (numBytes < 0))
+                return false;			// Max packet size is 60 bytes
+
+            dataOut[0] = (byte)(numBytes + 4);
+            dataOut[1] = 0x20;
+            dataOut[2] = slaveAddress;
+            dataOut[3] = memoryaddress;
+            dataOut[4] = numBytes;
+
+            for (int i = 0; i < numBytes; i++)
+                dataOut[i + 5] = databuffer[i];
+
+            success = InputOutputReports(dataOut, ref inputBuffer);
+
+            if (!success)
+                return false;
+
+            if (inputBuffer[2] == COMMAND_SUCCEED)
+                return true;
+            else
+                return false;
+        }
+
+        /****************I2CPacketRead****************/
+        /* Description: Generates the correct sequence of events on the I2C bus for a packet read (up to 60 data bytes) 
+        /* Information: New Implementation for packet reads ( SHOULD BE USED in most ALLL Writes/Read of and I2C Device )!!
+        /* Paramters: slaveAddress = slave address of DUT (R/W# is set in firmware), numBytes = Number of data bytes to write (1 to 60), 
+        /*	memoryaddress = Desired memory location, databuffer = pointer to the data read should be saved*/
+        internal Boolean I2CReadPacket(Byte slaveAddress, Byte memoryaddress, Byte numBytes, ref Byte[] databuffer)
+        {
+            Boolean success = false;
+            Byte[] inputBuffer = null;
+            Byte[] dataOut = new Byte[5];
+
+            if ((numBytes > 62) || (numBytes < 1))
+                return false;			// Max packet size is 62 bytes
+
+            dataOut[0] = 0x04;
+            dataOut[1] = 0x21;
+            dataOut[2] = (byte)(slaveAddress | 0x01);
+            dataOut[3] = memoryaddress;
+            dataOut[4] = numBytes;
+
+            success = InputOutputReports(dataOut, ref inputBuffer);
+
+            if (!success)
+                return false;
+
+            for (int i = 0; i < numBytes; i++)
+                databuffer[i] = inputBuffer[i + 3];
+
+            if (inputBuffer[2] == COMMAND_SUCCEED)
+                return true;
+            else
+                return false;
+        }
+
+        internal Boolean SPIReadPacket(Byte address, Byte numBytes, ref Byte[] data)
+        {
+            Boolean success = false;
+            Byte[] inputBuffer = null;
+            Byte[] dataOut = new Byte[4];
+
+            if ((numBytes > 62) || (numBytes < 1))
+                return false;				// Max packet size is 62 bytes
+
+            dataOut[0] = 3;
+            dataOut[1] = 0x41;
+            dataOut[2] = address;
+            dataOut[3] = numBytes;
+
+            success = InputOutputReports(dataOut, ref inputBuffer);
+
+            if (!success)
+                return false;
+
+            for (int i = 0; i < numBytes; i++)
+                data[i] = inputBuffer[i + 3];
+
+            if (inputBuffer[2] == COMMAND_SUCCEED)
+                return true;
+            else
+                return false;
+        }
+
+        internal Boolean SPIStartSampling(Byte address, Byte numBytes, uint numSamples, ref Byte[] data)
+        {
+            Boolean success = false;
+            Byte[] inputBuffer = null;
+            Byte[] dataOut = new Byte[6];
+
+            if ((numBytes > 62) || (numBytes < 1))
+                return false;				// Max packet size is 62 bytes
+
+            dataOut[0] = 5;
+            dataOut[1] = 0x45;
+            dataOut[2] = address;
+            dataOut[3] = numBytes;
+            dataOut[4] = (byte)(numSamples >> 8);
+            dataOut[5] = (byte)numSamples;
+
+            success = InputOutputReports(dataOut, ref inputBuffer);
+
+            if (!success)
+                return false;
+
+            for (int i = 0; i < numBytes; i++)
+                data[i] = inputBuffer[i + 3];
+
+            if (inputBuffer[2] == COMMAND_SUCCEED)
+                return true;
+            else
+                return false;
+        }
+
+        internal bool SPIWritePacket(Byte address, Byte numBytes, Byte[] data)
+        {
+            Boolean success = false;
+            Byte[] inputBuffer = null;
+            Byte[] dataOut = new Byte[64];
+
+            if ((numBytes > 60) || (numBytes < 1))
+                return false;				// Max packet size is 60 bytes
+
+            dataOut[0] = (byte)(numBytes + 3);
+            dataOut[1] = 0x40;
+            dataOut[2] = address;
+            dataOut[3] = numBytes;
+
+            for (int i = 0; i < numBytes; i++)
+                dataOut[4 + i] = data[i];
+
+            success = InputOutputReports(dataOut, ref inputBuffer);
+
+            if (!success)
+                return false;
+
+            if (inputBuffer[2] == COMMAND_SUCCEED)
+                return true;
+            else
+                return false;
+        }
+        ///  <summary>
+        ///  Sends an Output report, then retrieves an Input report.
+        ///  Assumes report ID = 0 for both reports.
+        ///  </summary>
+
+        private Boolean InputOutputReports(Byte[] data, ref Byte[] inputReportBuffer)
+        {
+            // Byte[] inputReportBuffer = null;
+            Byte[] outputReportBuffer = null;
+            Boolean success = false;
+
+            success = false;
+
+            //  Don't attempt to exchange reports if valid handles aren't available
+            //  (as for a mouse or keyboard under Windows 2000/XP.)
+
+            if (!readHandle.IsInvalid && !writeHandle.IsInvalid)
+            {
+                //  Don't attempt to send an Output report if the HID has no Output report.
+                if (MyHid.Capabilities.OutputReportByteLength > 0)
+                {
+                    //  Set the size of the Output report buffer.   
+
+                    outputReportBuffer = new Byte[MyHid.Capabilities.OutputReportByteLength];
+
+                    outputReportBuffer[0] = 0;      // Ensure Report ID = 0
+
+
+                    for (int i = 0; i < data.Length; i++)
+                        outputReportBuffer[i + 1] = data[i];
+
+                    //  Use WriteFile to send the report.
+                    //  If the HID has an interrupt OUT endpoint, WriteFile uses an 
+                    //  interrupt transfer to send the report. 
+                    //  If not, WriteFile uses a control transfer.
+
+                    Hid.OutputReportViaInterruptTransfer myOutputReport = new Hid.OutputReportViaInterruptTransfer();
+                    success = myOutputReport.Write(outputReportBuffer, writeHandle);
+                }
+
+                if (!success)
+                    return false;
+
+                //  Read an Input report
+                success = false;
+
+                //  Don't attempt to send an Input report if the HID has no Input report.
+                //  (The HID spec requires all HIDs to have an interrupt IN endpoint,
+                //  which suggests that all HIDs must support Input reports.)
+
+                if (MyHid.Capabilities.InputReportByteLength > 0)
+                {
+                    //  Set the size of the Input report buffer. 
+                    inputReportBuffer = new Byte[MyHid.Capabilities.InputReportByteLength];
+
+                    Hid.InputReportViaInterruptTransfer myInputReport = new Hid.InputReportViaInterruptTransfer();
+                    myInputReport.Read(hidHandle, readHandle, writeHandle, ref myDeviceDetected, ref inputReportBuffer, ref success);
+
+                }
+
+            }
+            return success;
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HspGuiSourceV301/HSPGui/PaceChannel.cs	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,136 @@
+/*******************************************************************************
+* Copyright (C) 2016 Maxim Integrated Products, Inc., All rights Reserved.
+* 
+* This software is protected by copyright laws of the United States and
+* of foreign countries. This material may also be protected by patent laws
+* and technology transfer regulations of the United States and of foreign
+* countries. This software is furnished under a license agreement and/or a
+* nondisclosure agreement and may only be used or reproduced in accordance
+* with the terms of those agreements. Dissemination of this information to
+* any party or parties not specified in the license agreement and/or
+* nondisclosure agreement is expressly prohibited.
+*
+* The above copyright notice and this permission notice shall be included
+* in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+* OTHER DEALINGS IN THE SOFTWARE.
+*
+* Except as contained in this notice, the name of Maxim Integrated
+* Products, Inc. shall not be used except as stated in the Maxim Integrated
+* Products, Inc. Branding Policy.
+*
+* The mere transfer of this software does not imply any licenses
+* of trade secrets, proprietary technology, copyrights, patents,
+* trademarks, maskwork rights, or any other form of intellectual
+* property whatsoever. Maxim Integrated Products, Inc. retains all
+* ownership rights.
+*******************************************************************************
+*/
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace HealthSensorPlatform
+{
+
+    public partial class HspForm
+    {
+        List<RegisterField> paceChannelField = new List<RegisterField>();
+
+        void initalizePaceChannelFields()
+        {
+            // Pace Channel
+            string[] aoutLbwOptions = { "Max (~100 kHz)*", "Limited (16 kHz)" };
+            string[] aoutOptions = { "Disabled*", "INA Output", "PGA Output", "Pace Input" };
+            string[] polOptions = { "Non-Inverted*", "Inverted" };
+            string[] gainOptions = { "540   / 50.625 / 202.50*", 
+                                     "270   / 50.625 / 101.25", 
+                                     "240   / 22.5     /  90", 
+                                     "120   / 22.5     /  45", 
+                                     " 60    /  5.625  /  22.5", 
+                                     " 30    /  5.625  /  11.25", 
+                                     " 26.4 /  5.625 /  22.5", 
+                                     " 13.2 /  5.625 /  11.25" 
+                                   };
+            string[] gnDiffOffOptions = { "Differentiator*", "Sample and Hold" };
+            string[] dacpOptions = new string[16];
+            for (int i = 0; i < dacpOptions.Length; i++)
+            {
+                dacpOptions[i] = (22.5 * i).ToString() + " mV";
+            }
+            dacpOptions[5] += "*";
+            string[] dacnOptions = new string[16];
+            for (int i = 0; i < dacnOptions.Length; i++)
+            {
+                dacnOptions[i] = (-22.5 * i).ToString() + " mV";
+            }
+            dacnOptions[5] += "*";
+
+            //RegisterField rateField = new RegisterField { Name = "BIOZ_RATE", Register = 0x18, Index = 23, Width = 1, Descriptions = rateOptions, Label = lblBioZSampleRate, Control = cboBioZSampleRate };
+            RegisterField polField = new RegisterField { Name = "PACE_POL", Register = 0x1A, Index = 23, Width = 1, Descriptions = polOptions, Label = lblPaceInputPolarity, Control = cboPaceInputPolarity, Device = max30001 };
+            RegisterField gnDiffOffField = new RegisterField { Name = "PACE_GN_DIFF_OFF", Register = 0x1A, Index = 19, Width = 1, Descriptions = gnDiffOffOptions, Label = lblPaceDifferentiatorMode, Control = cboPaceDifferentiatorMode, Device = max30001 };
+            RegisterField gainField = new RegisterField { Name = "PACE_GAIN", Register = 0x1A, Index = 16, Width = 3, Descriptions = gainOptions, Label = lblPaceChannelGain, Control = cboPaceChannelGain, Device = max30001 };
+            RegisterField aoutLbwField = new RegisterField { Name = "PACE_AOUT_LBW", Register = 0x1A, Index = 14, Width = 1, Descriptions = aoutLbwOptions, Label = lblPaceBufferBandwidth, Control = cboPaceBufferBandwidth, Device = max30001 };
+            RegisterField aoutField = new RegisterField { Name = "PACE_AOUT", Register = 0x1A, Index = 12, Width = 2, Descriptions = aoutOptions, Label = lblPaceSignalSelection, Control = cboPaceSignalSelection, Device = max30001 };
+            RegisterField dacpField = new RegisterField { Name = "PACE_DACP", Register = 0x1A, Index = 4, Width = 4, Descriptions = dacpOptions, Label = lblPaceDetectorPostiveThreshold, Control = cboPaceDetectorPostiveThreshold, Device = max30001 };
+            RegisterField dacnField = new RegisterField { Name = "PACE_DACN", Register = 0x1A, Index = 0, Width = 4, Descriptions = dacnOptions, Label = lblPaceDetectorNegativeThreshold, Control = cboPaceDetectorNegativeThreshold, Device = max30001 };
+            paceChannelField.Add(polField);
+            paceChannelField.Add(gnDiffOffField);
+            paceChannelField.Add(gainField);
+            paceChannelField.Add(aoutLbwField);
+            paceChannelField.Add(aoutField);
+            paceChannelField.Add(dacpField);
+            paceChannelField.Add(dacnField);
+
+            // BioZ Channel
+            string[] aHpfOptions = { "250 Hz", "500 Hz", "1000 Hz*", "2000 Hz", "4000 Hz", "8000 Hz", "Bypass" };
+            RegisterField aHpfField = new RegisterField { Name = "BIOZ_AHPF", Register = 0x18, Index = 20, Width = 3, Descriptions = aHpfOptions, Label = lblPaceAnalogHpf, Control = cboPaceAnalogHpf, Device = max30001 };
+            paceChannelField.Add(aHpfField);
+        }
+
+        void PaceChannelUpdateRegisters()
+        {
+            internalUpdate = true;
+            ReadComboBoxesRegisters(paceChannelField);
+            internalUpdate = false;
+        }
+
+        private CustomControls.InitArgs.PACEInitStart getPaceArgs()
+        {
+            CustomControls.InitArgs.PACEInitStart paceArgs = new CustomControls.InitArgs.PACEInitStart();
+
+            paceArgs.En_pace = chkEnPace.Checked == true ? 1 : 0;
+            paceArgs.Clr_pedge = 0; // TODO default from jerry
+            paceArgs.Pol = cboPaceInputPolarity.SelectedIndex;
+            paceArgs.Gn_diff_off = cboPaceDifferentiatorMode.SelectedIndex;
+            paceArgs.Gain = cboPaceChannelGain.SelectedIndex;
+            paceArgs.Aout_lbw = cboPaceBufferBandwidth.SelectedIndex;
+            paceArgs.Aout = cboPaceSignalSelection.SelectedIndex;
+            paceArgs.Dacp = cboPaceDetectorPostiveThreshold.SelectedIndex;
+            paceArgs.Dacn = cboPaceDetectorNegativeThreshold.SelectedIndex;
+
+            return paceArgs;
+        }
+
+        private void setPaceArgs(CustomControls.InitArgs.PACEInitStart paceArgs)
+        {
+            //paceArgs.En_pace = chkEnPace.Checked == true ? 1 : 0;
+            //paceArgs.Clr_pedge = 0; // TODO default from jerry
+            cboPaceInputPolarity.SelectedIndex = paceArgs.Pol;
+            cboPaceDifferentiatorMode.SelectedIndex = paceArgs.Gn_diff_off;
+            cboPaceChannelGain.SelectedIndex = paceArgs.Gain;
+            cboPaceBufferBandwidth.SelectedIndex = paceArgs.Aout_lbw;
+            cboPaceSignalSelection.SelectedIndex = paceArgs.Aout;
+            cboPaceDetectorPostiveThreshold.SelectedIndex = paceArgs.Dacp;
+            cboPaceDetectorNegativeThreshold.SelectedIndex = paceArgs.Dacn;
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HspGuiSourceV301/HSPGui/PartialArrayIntAvailableEventArgs.cs	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,31 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace HealthSensorPlatform
+{
+    public class PartialArrayIntAvailableEventArgs : EventArgs
+    {
+        /// <summary>
+        /// Sequential index of the first sample.
+        /// </summary>
+        public int sampleNumberOffset { get; set; }
+
+        /// <summary>
+        /// Red channel (660nm) integer values in time sequence.
+        /// </summary>
+        public int[] rawRedData { get; set; }
+
+        /// <summary>
+        /// Infrared channel (880nm) integer values in time sequence.
+        /// </summary>
+        public int[] rawIRData { get; set; }
+
+        /// <summary>
+        /// Green channel (527nm) integer values in time sequence.
+        /// </summary>
+        public int[] rawGreenData { get; set; }
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HspGuiSourceV301/HSPGui/Presenter/DataLogPresenter.cs	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,711 @@
+/*******************************************************************************
+* Copyright (C) 2016 Maxim Integrated Products, Inc., All rights Reserved.
+* 
+* This software is protected by copyright laws of the United States and
+* of foreign countries. This material may also be protected by patent laws
+* and technology transfer regulations of the United States and of foreign
+* countries. This software is furnished under a license agreement and/or a
+* nondisclosure agreement and may only be used or reproduced in accordance
+* with the terms of those agreements. Dissemination of this information to
+* any party or parties not specified in the license agreement and/or
+* nondisclosure agreement is expressly prohibited.
+*
+* The above copyright notice and this permission notice shall be included
+* in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+* OTHER DEALINGS IN THE SOFTWARE.
+*
+* Except as contained in this notice, the name of Maxim Integrated
+* Products, Inc. shall not be used except as stated in the Maxim Integrated
+* Products, Inc. Branding Policy.
+*
+* The mere transfer of this software does not imply any licenses
+* of trade secrets, proprietary technology, copyrights, patents,
+* trademarks, maskwork rights, or any other form of intellectual
+* property whatsoever. Maxim Integrated Products, Inc. retains all
+* ownership rights.
+*******************************************************************************
+*/
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+using RPCSupport.Streaming;
+using HealthSensorPlatform.Model;
+using HealthSensorPlatform.View;
+using HealthSensorPlatform.CustomControls;
+
+namespace HealthSensorPlatform.Presenter
+{
+    class DataLogPresenter
+    {
+        IDataLogModel model;
+        DataLoggingView view;
+        IRawFileLogView temperatureLog1;
+        IRawFileLogView temperatureLog2;
+        IRawFileLogView pressureLog;
+
+        IRawFileLogView accelerometerLog;
+        IRawFileLogView opticalLog;
+
+        IRawFileLogView ecgLog;
+        IRawFileLogView bioZLog;
+        IRawFileLogView paceLog;
+        IRawFileLogView rToRLog;
+
+        IFormView formView;
+
+        StatusForm statusForm;
+
+        EcgView ecgView; // Needed to obtain some state information, should be decoupled later and use from data log model
+        OpticalView opticalView;
+
+        int count = 0;
+        int bioZCount = 0;
+        int ppgCount = 0;
+        int accelCount = 0;
+        PaceData paceData;
+        RToRCalculator rToRCalculator;
+        bool rToRFirst = true;
+
+        string logFileDirectory = null;
+
+        View.FileLogView.FileLogHeader fileLogHeader = new View.FileLogView.FileLogHeader();
+
+        public DataLogPresenter(IFormView formView, EcgView ecgView, OpticalView opticalView, IDataLogModel model, DataLoggingView view, 
+            IRawFileLogView temperatureLog1, IRawFileLogView temperatureLog2, IRawFileLogView pressureLog, 
+            IRawFileLogView accelerometerLog, IRawFileLogView opticalLog, 
+            IRawFileLogView ecgLog, IRawFileLogView bioZLog, IRawFileLogView paceLog, IRawFileLogView rToRLog)
+        {
+            this.model = model;
+            this.view = view;
+
+            this.formView = formView;
+            this.ecgView = ecgView;
+            this.opticalView = opticalView;
+
+            this.temperatureLog1 = temperatureLog1;
+            this.temperatureLog2 = temperatureLog2;
+            this.pressureLog = pressureLog;
+
+            this.accelerometerLog = accelerometerLog;
+            this.opticalLog = opticalLog;
+
+            this.ecgLog = ecgLog;
+            this.bioZLog = bioZLog;
+            this.paceLog = paceLog;
+            this.rToRLog = rToRLog;
+
+            view.LogDownloadStart += new EventHandler<EventArgs>(OnLogDownloadStart);
+            view.MissionWrite += new EventHandler<EventArgs>(OnMissionWrite);
+            view.MissionRead += new EventHandler<EventArgs>(OnMissionRead);
+            view.MissionErase += new EventHandler<EventArgs>(OnMissionErase);
+            model.LogData += new EventHandler<PartialArrayIntAvailableEventArgs>(OnLogData);
+        }
+        
+        public void ProcessTemperature1(int[] data)
+        {
+            double[] calcTemp;
+
+            calcTemp = CalculateTemperature(data);
+            temperatureLog1.DisplayTemperature(data, calcTemp);
+        }
+
+        public void ProcessTemperature2(int[] data)
+        {
+            double[] calcTemp;
+
+            calcTemp = CalculateTemperature(data);
+            temperatureLog2.DisplayTemperature(data, calcTemp);
+        }
+
+        public double[] CalculateTemperature(int[] data)
+        {
+            double[] calcTemp = new double[data.Length];
+            int rawCode;
+
+            for (int i = 0; i < data.Length; i++ )
+            {
+                rawCode = data[i];
+
+                if (rawCode > 0x7fff)
+                    rawCode -= 0x10000;
+
+                calcTemp[i] = rawCode / Math.Pow(2, 8);
+            }
+
+            return calcTemp;
+        }
+
+        public void ProcessPressure(int[] data)
+        {
+            int[] rawTemp = new int[data.Length/2];
+			int[] rawPress = new int[data.Length/2];
+            double[] calcTemp, calcPress;
+			
+			for (int i = 0, j = 0; i < data.Length; i = i + 2, j++)
+			{
+				rawTemp[j] = data[i];
+				rawPress[j] = data[i + 1];
+			}
+
+            var result = CalculatePressure(rawTemp, rawPress);
+			calcTemp = result.Item1;
+            calcPress = result.Item2;
+			
+            pressureLog.DisplayPressure(rawTemp, calcTemp, rawPress, calcPress);
+        }
+
+        public Tuple<double[], double[]> CalculatePressure(int[] temperature, int[] pressure)
+        {
+            double[] calcTemp = new double[temperature.Length];
+            double[] calcPress = new double[pressure.Length];
+
+            for (int i = 0; i < temperature.Length; i++ )
+            {
+                calcTemp[i] = temperature[i] / 10.0;
+            }
+
+            for (int i = 0; i < pressure.Length; i++ )
+            {
+                calcPress[i] = pressure[i] / 10;
+            }
+
+            return new Tuple<double[],double[]>(calcTemp, calcPress);
+        }
+
+        private void OnLogDownloadStart(object sender, EventArgs e)
+        {
+
+            if (view.Connected)
+            {
+                count = 0;
+                bioZCount = 0;
+                ppgCount = 0;
+                accelCount = 0;
+
+                missionRead();
+
+                if (model.MissionSettings.Enable)
+                {
+
+                    if (selectFile())
+                    {
+                        string missionString;
+                        StringBuilder sb = new StringBuilder();
+                        foreach (string str in model.MissionString())
+                        {
+                            sb.Append("% ");
+                            sb.Append(str);
+                            sb.Append(Environment.NewLine);
+                        }
+                        missionString = sb.ToString().Trim(Environment.NewLine.ToCharArray());
+
+
+                        if (temperatureLog1 != null && temperatureLog1.Enable)
+                        {
+                            temperatureLog1.WriteLine(missionString);
+                            temperatureLog1.WriteLine(fileLogHeader.Temperature1);
+                        }
+
+                        if (temperatureLog2 != null && temperatureLog2.Enable)
+                        {
+                            temperatureLog2.WriteLine(missionString);
+                            temperatureLog2.WriteLine(fileLogHeader.Temperature2);
+                        }
+
+                        if (pressureLog != null && pressureLog.Enable)
+                        {
+                            pressureLog.WriteLine(missionString);
+                            pressureLog.WriteLine(fileLogHeader.Pressure);
+                        }
+
+                        if (accelerometerLog != null && accelerometerLog.Enable)
+                        {
+                            accelerometerLog.WriteLine(missionString);
+                            accelerometerLog.WriteLine(fileLogHeader.Accelerometer);
+                        }
+
+                        if (opticalLog != null && opticalLog.Enable)
+                        {
+                            opticalLog.WriteLine(missionString);
+                            opticalLog.WriteLine(fileLogHeader.Optical);
+                        }
+
+                        if (ecgLog != null && ecgLog.Enable)
+                        {
+                            ecgLog.WriteLine(missionString);
+                            ecgLog.WriteLine(fileLogHeader.Ecg);
+                        }
+
+                        if (bioZLog != null && bioZLog.Enable)
+                        {
+                            bioZLog.WriteLine(missionString);
+                            bioZLog.WriteLine(fileLogHeader.BioZ);
+                        }
+
+                        if (rToRLog != null && rToRLog.Enable && ecgLog.Enable)
+                        {
+                            rToRLog.WriteLine(missionString);
+                            rToRCalculator = new RToRCalculator(ecgView.MasterClockField, view.EcgArgs.Rate, view.EcgArgs.Dlpf, view.RToRArgs.Wndw);
+                            rToRLog.WriteLine(fileLogHeader.RToR);
+                        }
+                        else if (rToRLog != null && rToRLog.Enable)
+                        {
+                            rToRLog.WriteLine(missionString);
+                            rToRCalculator = null;
+                            rToRLog.WriteLine(fileLogHeader.RToR);
+                        }
+
+                        if (paceLog != null && paceLog.Enable)
+                        {
+                            paceLog.WriteLine(missionString);
+                            paceLog.WriteLine(fileLogHeader.Pace);
+                        }
+
+                        statusForm = new StatusForm();
+                        statusForm.Text = "Flash Download";
+                        statusForm.Message = "Please wait while your data is saved to your file.";
+                        statusForm.Show();
+
+                        model.Start();
+                    }
+                }
+            }
+        }
+
+        private void LogDownloadStop()
+        {
+            if (temperatureLog1 != null && temperatureLog1.Enable)
+                temperatureLog1.Enable = false;
+
+            if (temperatureLog2 != null && temperatureLog2.Enable)
+                temperatureLog2.Enable = false;
+
+            if (pressureLog != null && pressureLog.Enable)
+                pressureLog.Enable = false;
+
+            if (accelerometerLog != null && accelerometerLog.Enable)
+                accelerometerLog.Enable = false;
+
+            if (opticalLog != null && opticalLog.Enable)
+                opticalLog.Enable = false;
+
+            if (ecgLog != null && ecgLog.Enable)
+                ecgLog.Enable = false;
+
+            if (bioZLog != null && bioZLog.Enable)
+                bioZLog.Enable = false;
+
+            if (rToRLog != null && rToRLog.Enable)
+                rToRLog.Enable = false;
+
+            if (paceLog != null && paceLog.Enable)
+                paceLog.Enable = false;
+
+            formView.MessageInfo("File save complete");
+            statusForm.Hide();
+        }
+
+        private void OnLogData(object sender, PartialArrayIntAvailableEventArgs e)
+        {
+            switch(e.reportID)
+            {
+                case PartialArrayIntAvailableEventArgs.PACKET_BMP280_PRESSURE:
+                    if (pressureLog != null && pressureLog.Enable)
+                        ProcessPressure(e.array1);
+                    break;
+                case PartialArrayIntAvailableEventArgs.PACKET_MAX31725_TEMP1:
+                    if (temperatureLog1 != null && temperatureLog1.Enable)
+                        ProcessTemperature1(e.array1);
+                    break;
+                case PartialArrayIntAvailableEventArgs.PACKET_MAX31725_TEMP2:
+                    if (temperatureLog2 != null && temperatureLog2.Enable)
+                        ProcessTemperature2(e.array1);
+                    break;
+
+                case PartialArrayIntAvailableEventArgs.PACKET_MAX30001_ECG:
+                    if (ecgLog != null && ecgLog.Enable)
+                        ProcessEcg(e.array1);
+                    break;
+                case PartialArrayIntAvailableEventArgs.PACKET_MAX30001_BIOZ:
+                    if (bioZLog != null && bioZLog.Enable)
+                        ProcessBioZ(e.array1);
+                    break;
+                case PartialArrayIntAvailableEventArgs.PACKET_MAX30001_PACE:
+                    if (paceLog != null && paceLog.Enable)
+                        paceData = new PaceData(e.array1);
+                    break;
+                case PartialArrayIntAvailableEventArgs.PACKET_MAX30001_RTOR:
+                    if (rToRLog != null && rToRLog.Enable)
+                        ProcessRToR(e.array1[0]);
+                    break;
+
+                case PartialArrayIntAvailableEventArgs.PACKET_LIS2DH:
+                case PartialArrayIntAvailableEventArgs.PACKET_LSM6DS3_ACCEL:
+                    if (accelerometerLog != null && accelerometerLog.Enable)
+                        ProcessAccelerometer(e.array1, e.array2, e.array3);
+                    break;
+                case PartialArrayIntAvailableEventArgs.PACKET_END_OF_STREAM:
+                    LogDownloadStop();
+                    break;
+            }
+
+            if ((e.reportID & 0xF0) == PartialArrayIntAvailableEventArgs.PACKET_MAX30101)
+            {
+                if (opticalLog != null && opticalLog.Enable)
+                    ProcessOptical(e.array1, e.array2, e.array3);
+
+            }
+        }
+
+        private void OnMissionWrite(object sender, EventArgs e)
+        {
+            if (view.Connected)
+            {
+                if (view.EnableAccelerometer || view.EnableBioz || view.EnableEcg || view.EnableOpticalHR 
+                    || view.EnableOpticalMulti || view.EnableOpticalSpO2 || view.EnablePace 
+                    || view.EnablePressure || view.EnableRToR || view.EnableTemperature1 || view.EnableTemperature2)
+                {
+                    if (view.ValidateGuiElements())
+                    {
+                        statusForm = new StatusForm();
+                        statusForm.Message = "Please wait while your flash log is cleared and new parameters are written. Do not unplug the USB connection or press start button on the board until write is complete.";
+                        statusForm.Show();
+                        formView.MessageInfo("Writing in progress...");
+                        model.MissionErase();
+                        model.EraseWrittenSectors();
+                        model.MissionStartDefinition();
+                        view.ProcessGuiElements();
+                        //rpcClient.DataLogging.Test();
+                        model.MissionWrite();
+                        statusForm.Hide();
+                        formView.MessageInfo("Write parameters complete");
+                    }
+                    else
+                        formView.MessageInfo("Incorrect logging parameters");
+                }
+                else
+                {
+                    formView.MessageInfo("No devices selected");
+                }
+            }
+        }
+
+        private void OnMissionRead(object sender, EventArgs e)
+        {
+            if (view.Connected)
+            {
+                missionRead();
+            }
+        }
+
+        private void OnMissionErase(object sender, EventArgs e)
+        {
+            if (view.Connected)
+            {
+                model.MissionErase();
+
+                formView.MessageInfo("Erase parameters complete");
+            }
+        }
+
+        private void OnLogFileEnable(object sender, EnableEventArgs e)
+        {
+            // Not used
+        }
+
+        private bool selectFile()
+        {
+            bool result = false;
+
+            Mission settings = model.MissionSettings;
+
+            if (settings.EnableEcg)
+                result |= selectLogFileName(ecgLog, "hsp-log-ecg");
+
+            if (settings.EnablePace)
+                result |= selectLogFileName(paceLog, "hsp-log-pace");
+
+            if (settings.EnableBioZ)
+                result |= selectLogFileName(bioZLog, "hsp-log-bioz");
+
+            if (settings.EnableRToR)
+                result |= selectLogFileName(rToRLog, "hsp-log-rtor");
+
+            if (settings.EnableOpticalHR || settings.EnableOpticalMulti || settings.EnableOpticalSpO2)
+                result |= selectLogFileName(opticalLog, "hsp-log-optical");
+
+            if (settings.EnableTemperature1)
+                result |= selectLogFileName(temperatureLog1, "hsp-log-temperature1");
+
+            if (settings.EnableTemperature2)
+                result |= selectLogFileName(temperatureLog2, "hsp-log-temperature2");
+
+            if (settings.EnablePressure)
+                result |= selectLogFileName(pressureLog, "hsp-log-barometer");
+
+            if (settings.EnableAccelerometer)
+                result |= selectLogFileName(accelerometerLog, "hsp-log-accelerometer");
+
+            return result;
+        }
+
+        bool selectLogFileName(IRawFileLogView log, string name)
+        {
+            bool result;
+
+            if (logFileDirectory != null)
+                log.FileDirectory = logFileDirectory;
+
+            result = log.SelectCSVFile(name);
+            log.Enable = result;
+
+            if (result)
+                logFileDirectory = log.FileDirectory;
+
+            return result;
+        }
+
+        private void missionRead()
+        {
+            model.MissionRead();
+            view.UpdateGuiElements(model.MissionSettings);
+            if (model.MissionSettings.Enable)
+                formView.MessageInfo("Read complete");
+            else
+                formView.MessageInfo("No parameters defined");
+        }
+
+        void ProcessBioZ(int[] rawData)
+        {
+            BioZFifo[] bioZFifo;
+            double[] time = new double[rawData.Length];
+            double sampleRate = ecgView.SampleRateBioZ;
+
+            bioZFifo = ConvertBioZ(rawData);
+
+            for (int i = 0; i < time.Length; i++ )
+            {
+                time[i] = bioZCount / (double)sampleRate;
+                bioZCount++;
+            }
+
+            bioZLog.DisplayBioZ(time, bioZFifo);
+        }
+
+        public BioZFifo[] ConvertBioZ(int[] data)
+        {
+            BioZFifo[] impedance = new BioZFifo[data.Length];
+            //EcgView.ChartInfo chartInfo = BioZInfo();
+            EcgView.ChartInfo chartInfo = ecgView.BioZInfo;
+
+            int dataShift;
+
+            for (int i = 0; i < data.Length; i++)
+            {
+                dataShift = data[i] >> chartInfo.Shift;
+
+                // Two's Complement Conversions
+                if (dataShift > chartInfo.Threshold)
+                {
+                    dataShift -= chartInfo.Offset;
+                }
+
+                // 1.9734 = 1/2^19 * 1e-6
+                impedance[i].Data = dataShift * 1.9073486328125 /
+                    (chartInfo.Gain * ((chartInfo.CurrentGenerator == 0) ? 1 : chartInfo.CurrentGenerator));
+                impedance[i].Code = data[i];
+                impedance[i].BioZData = dataShift;
+                impedance[i].BTag = data[i] & 0x07;
+            }
+
+            return impedance;
+        }
+
+        public EcgView.ChartInfo BioZInfo()
+        {
+            EcgView.ChartInfo info = new EcgView.ChartInfo();
+            int[] currentGen = new int[] {1, 8, 16, 32, 48, 64, 80, 96};
+            int[] gain = new int[] {20, 40, 80, 160};
+
+            info.Shift = 4;
+            info.Offset = 0x100000;
+            info.Threshold = 0x100000;
+            info.Gain = gain[model.MissionSettings.BioZArgs[10]];
+            info.CurrentGenerator = currentGen[model.MissionSettings.BioZArgs[15]];
+
+            return info;
+        }
+
+        void ProcessEcg(int[] rawData)
+        {
+            EcgFifo[] ecgFifo;
+            double[] ecgVoltage = new double[rawData.Length];
+            double[] timeSecond = new double[rawData.Length];
+            double ecgRate = ecgView.SampleRateEcg;
+
+            ecgFifo = ConvertEcg(rawData);
+
+            for (int i = 0; i < ecgFifo.Length; i++)
+            {
+                timeSecond[i] = count / ecgRate;
+
+                // Look for Pace Events
+                if (paceLog.Enable)
+                {
+                    //for (int j = 0; j < ecgFifo.Length; j++)
+                    //{
+                    if (ecgFifo[i].PTag != 7)
+                    {
+                        PaceData.PaceRegister paceRegister = paceData.PaceGroup(ecgFifo[i].PTag);
+                        List<double> timeMillsecondPace = new List<double>();
+                        List<PaceData.PaceEdge> paceEdges = new List<PaceData.PaceEdge>();
+
+                        for (int k = 0; k < 6; k++)
+                        {
+                            PaceData.PaceEdge edge = paceRegister.Edge[k];
+
+                            timeMillsecondPace.Add(count / ecgRate + ConvertPace(edge.Data));
+                            paceEdges.Add(edge);
+
+                            if (edge.Last == true)
+                                break;
+                        }
+
+                        paceLog.DisplayPace(timeMillsecondPace.ToArray(), paceEdges.ToArray());
+                        System.Diagnostics.Debug.Print("ECG PTag = " + ecgFifo[i].PTag);
+                    }
+                    //}
+                }
+
+                count++;
+            }
+
+            ecgLog.DisplayEcg(timeSecond, ecgFifo);
+
+        }
+
+        public EcgFifo[] ConvertEcg(int[] data)
+        {
+            EcgFifo[] voltage = new EcgFifo[data.Length];
+            //EcgView.ChartInfo chartInfo = EcgInfo();
+            EcgView.ChartInfo chartInfo = ecgView.EcgInfo;
+
+            int dataShift;
+
+            for (int i = 0; i < data.Length; i++)
+            {
+                dataShift = data[i] >> chartInfo.Shift;
+
+                // Two's Complement Conversions
+                if (dataShift > chartInfo.Threshold)
+                {
+                    dataShift -= chartInfo.Offset;
+                }
+
+                voltage[i].Data = 1000 * 7.62939453125e-6 * dataShift / chartInfo.Gain;
+                voltage[i].EcgData = dataShift;
+                voltage[i].Code = data[i];
+                voltage[i].PTag = data[i] & 0x07;
+                voltage[i].ETag = (data[i] >> 3) & 0x07;
+            }
+
+            return voltage;
+        }
+
+        public EcgView.ChartInfo EcgInfo()
+        {
+            EcgView.ChartInfo info = new EcgView.ChartInfo();
+            int[] gain = new int[] {20, 40, 80, 160};
+
+            info.Shift = 6;
+            info.Threshold = 0x1ffff;
+            info.Offset = 0x40000;
+
+            info.Gain = gain[model.MissionSettings.EcgArgs[10]];
+
+            return info;
+        }
+
+        public double ConvertRToR(int data)
+        {
+            return ecgView.TimeResolution * 1000 * data * 512;
+        }
+
+        public double ConvertPace(int data)
+        {
+            return data * ecgView.TimeResolution;
+        }
+
+        public string PaceRegisterGroupToString(PaceData.PaceRegister paceRegister)
+        {
+            StringBuilder paceRegisterLogBuilder = new StringBuilder();
+            for (int j = 0; j < 6; j++)
+            {
+                paceRegisterLogBuilder.Append(paceRegister.Edge[j].Data / (2 * ecgView.MasterClockFrequency));
+                paceRegisterLogBuilder.Append(", ");
+                paceRegisterLogBuilder.Append(paceRegister.Edge[j].Polarity ? 'R' : 'F');
+                paceRegisterLogBuilder.Append(", ");
+                paceRegisterLogBuilder.Append(paceRegister.Edge[j].Last ? 'Y' : 'N');
+                paceRegisterLogBuilder.Append(", ");
+            }
+
+            return paceRegisterLogBuilder.ToString();
+        }
+
+        void ProcessRToR(int data)
+        {
+            if (rToRCalculator != null)
+            {
+                if (rToRFirst)
+                {
+                    rToRLog.DisplayRToR(data, rToRCalculator.Corrected(data, true) / 1000);
+                    rToRFirst = false;
+                }
+                else
+                    rToRLog.DisplayRToR(data, rToRCalculator.Corrected(data, false) / 1000);
+            }
+            else
+            {
+                rToRLog.DisplayRToR(data, 0);
+            }
+        }
+
+        public void ProcessOptical(int[] red, int[] ir, int[] green)
+        {
+            int sampleRate = opticalView.OpticalSampleRate;
+            double[] time = new double[red.Length];
+
+            for (int i = 0; i < time.Length; i++ )
+            {
+                time[i] = ppgCount / (double)sampleRate;
+                ppgCount++;
+            }
+
+            opticalLog.DisplayPpg(time, new int[][] { red, ir, green });
+        }
+
+        public void ProcessAccelerometer(int[] x, int[] y, int[] z)
+        {
+            int sampleRate = view.AccelSampleRate;
+            double[] time = new double[x.Length];
+
+            for (int i = 0; i < time.Length; i++)
+            {
+                time[i] = accelCount / (double)sampleRate;
+                accelCount++;
+            }
+
+            accelerometerLog.DisplayXYZ(time, new int[][] { x, y, z });
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HspGuiSourceV301/HSPGui/Presenter/EcgDelay.cs	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,168 @@
+/*******************************************************************************
+* Copyright (C) 2016 Maxim Integrated Products, Inc., All rights Reserved.
+* 
+* This software is protected by copyright laws of the United States and
+* of foreign countries. This material may also be protected by patent laws
+* and technology transfer regulations of the United States and of foreign
+* countries. This software is furnished under a license agreement and/or a
+* nondisclosure agreement and may only be used or reproduced in accordance
+* with the terms of those agreements. Dissemination of this information to
+* any party or parties not specified in the license agreement and/or
+* nondisclosure agreement is expressly prohibited.
+*
+* The above copyright notice and this permission notice shall be included
+* in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+* OTHER DEALINGS IN THE SOFTWARE.
+*
+* Except as contained in this notice, the name of Maxim Integrated
+* Products, Inc. shall not be used except as stated in the Maxim Integrated
+* Products, Inc. Branding Policy.
+*
+* The mere transfer of this software does not imply any licenses
+* of trade secrets, proprietary technology, copyrights, patents,
+* trademarks, maskwork rights, or any other form of intellectual
+* property whatsoever. Maxim Integrated Products, Inc. retains all
+* ownership rights.
+*******************************************************************************
+*/
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+using HealthSensorPlatform.CustomControls;
+
+namespace HealthSensorPlatform.Presenter
+{
+    class EcgDelay
+    {
+        public const int RToRMaxValue = 0x3FFF;
+
+        List<double> ecg;
+        List<string> pace;
+        List<double> rToR;
+
+        //bool enableEcg;
+        //bool enablePace;
+        bool enableRToR;
+
+        int offset;
+
+        RToRCalculator rToRCalculator;
+
+        bool firstRToR = true;
+
+        public EcgDelay(bool enableRToR, int fmstr, int ecgSampleRate, int dlpf, int rWndw)
+        {
+            ecg = new List<double>();
+            pace = new List<string>();
+            rToR = new List<double>();
+
+            this.enableRToR = enableRToR;
+
+            rToRCalculator = new RToRCalculator(fmstr, ecgSampleRate, dlpf, rWndw);
+
+            offset = rToRCalculator.EcgPoints(0, true) * -1;
+        }
+
+        public void AddEcg(double[] ecgVoltage)
+        {
+            ecg.AddRange(ecgVoltage);
+        }
+
+        public void AddPace(string[] paceLog)
+        {
+            pace.AddRange(paceLog);
+        }
+
+        public void AddRToR(int rToRRaw)
+        {
+            int rToREcg;
+
+            if (firstRToR)
+            {
+                rToREcg = rToRCalculator.EcgPoints(rToRRaw, true);
+                firstRToR = false;
+            }
+            else
+            {
+                rToREcg = rToRCalculator.EcgPoints(rToRRaw, false);
+            }
+
+            for (int i = 1; i < rToREcg; i++)
+            {
+                rToR.Add(0);
+            }
+
+            if (rToRRaw != RToRMaxValue)
+                rToR.Add(rToRCalculator.Millisecond(rToRRaw));
+            else
+                rToR.Add(0);
+        }
+
+        public bool HasData()
+        {
+            if (enableRToR)
+                return offset + 10 < rToR.Count;
+            else
+                return offset + 10 < ecg.Count;
+        }
+
+        public bool HasFinalData()
+        {
+            return ecg.Count > 0;
+        }
+
+        public Tuple<double[], string[], double[]> GetEcg()
+        {
+            double[] ecgVoltage;
+            string[] paceGroup;
+            double[] rToRInterval;
+
+            int size;
+
+            if (enableRToR)
+                size = rToR.Count - offset - 10;
+            else
+                size = ecg.Count; // No delay needed if R To R is disabled, dump all points
+
+
+            ecgVoltage = new double[size];
+            paceGroup = new string[size];
+            rToRInterval = new double[size];
+
+            for (int i = 0; i < size; i++ )
+            {
+                ecgVoltage[i] = ecg[i];
+                paceGroup[i] = pace[i];
+                if (enableRToR)
+                    rToRInterval[i] = rToR[i];
+            }
+
+            ecg.RemoveRange(0, size);
+            pace.RemoveRange(0, size);
+            if (enableRToR)
+                rToR.RemoveRange(0, size);
+
+            return new Tuple<double[],string[],double[]>(ecgVoltage, paceGroup, rToRInterval);
+        }
+
+        public Tuple<double[], string[], double[]> GetAllEcg()
+        {
+			double[] rToRZeroData = new double[ecg.Count];
+
+            for (int i = 0; i < rToR.Count; i++)
+                rToRZeroData[i] = rToR[i];
+
+            return new Tuple<double[], string[], double[]>(ecg.ToArray(), pace.ToArray(), rToRZeroData);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HspGuiSourceV301/HSPGui/Presenter/OpticalAlgorithmPresenter.cs	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,142 @@
+/*******************************************************************************
+* Copyright (C) 2016 Maxim Integrated Products, Inc., All rights Reserved.
+* 
+* This software is protected by copyright laws of the United States and
+* of foreign countries. This material may also be protected by patent laws
+* and technology transfer regulations of the United States and of foreign
+* countries. This software is furnished under a license agreement and/or a
+* nondisclosure agreement and may only be used or reproduced in accordance
+* with the terms of those agreements. Dissemination of this information to
+* any party or parties not specified in the license agreement and/or
+* nondisclosure agreement is expressly prohibited.
+*
+* The above copyright notice and this permission notice shall be included
+* in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+* OTHER DEALINGS IN THE SOFTWARE.
+*
+* Except as contained in this notice, the name of Maxim Integrated
+* Products, Inc. shall not be used except as stated in the Maxim Integrated
+* Products, Inc. Branding Policy.
+*
+* The mere transfer of this software does not imply any licenses
+* of trade secrets, proprietary technology, copyrights, patents,
+* trademarks, maskwork rights, or any other form of intellectual
+* property whatsoever. Maxim Integrated Products, Inc. retains all
+* ownership rights.
+*******************************************************************************
+*/
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+using Maxim.MAX30101GUI;
+using HealthSensorPlatform.View;
+using HealthSensorPlatform.CustomControls;
+using RPCSupport;
+using RPCSupport.Streaming;
+
+namespace HealthSensorPlatform.Presenter
+{
+    class OpticalAlgorithmPresenter
+    {
+        private MaximAlgorithmClass algorithm;
+        private IOpticalAlgorithmView view;
+
+        private bool streaming;
+        private int count;
+
+        private bool validRed = false;
+        private bool validGreen = false;
+        private bool validIR = false;
+
+        public OpticalAlgorithmPresenter(RPCClient rpcClient, MaximAlgorithmClass algorithm, IOpticalAlgorithmView view)
+        {
+            this.algorithm = algorithm;
+            this.view = view;
+
+            //((OpticalView)view).StreamingStartStop += new OpticalView.StreamingStartStopEventHandler(OnStreamingStartStop);
+            ((OpticalView)view).StreamingStartStop += new EventHandler<StreamingStartStopEventArgs>(OnStreamingStartStop);
+            rpcClient.streaming.PartialArrayIntAvailable += new EventHandler<PartialArrayIntAvailableEventArgs>(OnPartialArrayIntAvaible);
+            algorithm.OnHeartRateSpO2dataAvailable += OnHeartRateSpO2DataAvailable; // view.DisplayAlgorithmResult;
+        }
+
+        public void OnHeartRateSpO2DataAvailable(double heartRateBPM, bool heartRateBPMValid, double heartRateBPMSignalStrength,
+                double spO2Percent, bool spO2PercentValid, double spO2PercentSignalStrength)
+        {
+            view.DisplayAlgorithmResult(heartRateBPM, heartRateBPMValid, heartRateBPMSignalStrength,
+                spO2Percent, spO2PercentValid, spO2PercentSignalStrength);
+        }
+
+        public void OnStreamingStartStop(object sender, StreamingStartStopEventArgs e)
+        {
+            streaming = e.state;
+            count = 0;
+            if (streaming)
+            {
+                algorithm.Clear();
+                view.DisplayAlgorithmReset();
+                switch (((OpticalView)view).ModeConfiguration)
+                {
+                    case OpticalView.eStreamMode.eHR:
+                        validRed = true;
+                        validIR = false;
+                        validGreen = false;
+                        break;
+                    case OpticalView.eStreamMode.eSPO2:
+                        validRed = true;
+                        validIR = true;
+                        validGreen = false;
+                        break;
+                    case OpticalView.eStreamMode.eMulti:
+                        validRed = true;
+                        validIR = true;
+                        validGreen = true;
+                        break;
+                }
+            }
+        }
+
+        public void OnPartialArrayIntAvaible(object sender, PartialArrayIntAvailableEventArgs e)
+        {
+            int numSamples;
+
+            if (streaming)
+            {
+                if ((e.reportID & 0xF0) == PartialArrayIntAvailableEventArgs.PACKET_MAX30101)
+                {
+                    numSamples = e.array1.Length;
+
+                    for (int i = 0; i < numSamples; i++)
+                    {
+                        int red = 0, ir = 0, green = 0;
+
+                        if (e.array1.Length != 0)
+                        {
+                            red = e.array1[i];
+                        }
+                        if (e.array2.Length != 0)
+                        {
+                            ir = e.array2[i];
+                        }
+                        if (e.array3.Length != 0)
+                        {
+                            green = e.array3[i];
+                        }
+
+                        algorithm.ConsumeRedIRGreenLEDdata(count, ir, red, green, validIR, validRed, validGreen);
+                        count++;
+                    }
+                }
+            }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HspGuiSourceV301/HSPGui/Presenter/OpticalFileLogPresenter.cs	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,198 @@
+/*******************************************************************************
+* Copyright (C) 2016 Maxim Integrated Products, Inc., All rights Reserved.
+* 
+* This software is protected by copyright laws of the United States and
+* of foreign countries. This material may also be protected by patent laws
+* and technology transfer regulations of the United States and of foreign
+* countries. This software is furnished under a license agreement and/or a
+* nondisclosure agreement and may only be used or reproduced in accordance
+* with the terms of those agreements. Dissemination of this information to
+* any party or parties not specified in the license agreement and/or
+* nondisclosure agreement is expressly prohibited.
+*
+* The above copyright notice and this permission notice shall be included
+* in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+* OTHER DEALINGS IN THE SOFTWARE.
+*
+* Except as contained in this notice, the name of Maxim Integrated
+* Products, Inc. shall not be used except as stated in the Maxim Integrated
+* Products, Inc. Branding Policy.
+*
+* The mere transfer of this software does not imply any licenses
+* of trade secrets, proprietary technology, copyrights, patents,
+* trademarks, maskwork rights, or any other form of intellectual
+* property whatsoever. Maxim Integrated Products, Inc. retains all
+* ownership rights.
+*******************************************************************************
+*/
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+using HealthSensorPlatform.View;
+using HealthSensorPlatform.CustomControls;
+
+using RPCSupport.Streaming;
+
+namespace HealthSensorPlatform.Presenter
+{
+    public class OpticalFileLogPresenter
+    {
+        IRawFileLogView optical;
+        IRawFileLogView accel;
+        HspForm mainForm;
+        OpticalView opticalView;
+
+        string logFileDirectory = null;
+
+        int ppgCount = 0;
+        int accelCount = 0;
+
+        public OpticalFileLogPresenter(RPCSupport.RPCClient rpcClient, HspForm mainForm, OpticalView opticalView, IRawFileLogView optical, IRawFileLogView accel)
+        {
+            this.optical = optical;
+            this.accel = accel;
+            this.mainForm = mainForm;
+            this.opticalView = opticalView;
+
+            rpcClient.streaming.PartialArrayIntAvailable += new EventHandler<PartialArrayIntAvailableEventArgs>(OnStreamData);
+            mainForm.OpticalFileLogEnable += new EventHandler<EnableEventArgs>(OnFileLogEnable);
+            //opticalView.StreamingStartStop += new OpticalView.StreamingStartStopEventHandler(OnStreamingStartStop);
+            opticalView.StreamingStartStop += new EventHandler<StreamingStartStopEventArgs>(OnStreamingStartStop);
+        }
+
+        public void ProcessOptical(int[] red, int[] ir, int[] green)
+        {
+            double[] time = new double[red.Length];
+
+            for (int i = 0; i < time.Length; i++ )
+            {
+                time[i] = ppgCount / (double)opticalView.OpticalSampleRate;
+                ppgCount++;
+            }
+
+            optical.DisplayPpg(time, new int[][] { red, ir, green });
+        }
+
+        public void ProcessXYZ(int[] x, int[] y, int[] z)
+        {
+            int[] decimalFormatX;
+            int[] decimalFormatY;
+            int[] decimalFormatZ;
+            double[] time = new double[x.Length];
+
+            decimalFormatX = ConvertXYZBinary(x);
+            decimalFormatY = ConvertXYZBinary(y);
+            decimalFormatZ = ConvertXYZBinary(z);
+
+            for (int i = 0; i < time.Length; i++ )
+            {
+                time[i] = accelCount / (double)opticalView.AccelSampleRate;
+                accelCount++;
+            }
+
+            accel.DisplayXYZ(time, new int[][] { decimalFormatX, decimalFormatY, decimalFormatZ });
+        }
+
+        public static int[] ConvertXYZBinary(int[] data)
+        {
+            int[] decimalFormat = new int[data.Length];
+
+            for (int i = 0; i < data.Length; i++)
+            {
+                if (data[i] > 0x8000)
+                    decimalFormat[i] = data[i] - 0x10000;
+                else
+                    decimalFormat[i] = data[i];
+            }
+
+            return decimalFormat;
+        }
+
+        public void OnStreamData(object sender, PartialArrayIntAvailableEventArgs e)
+        {
+            if ((e.reportID & 0xF0) == PartialArrayIntAvailableEventArgs.PACKET_MAX30101)
+            {
+                if (optical.Enable)
+                    ProcessOptical(e.array1, e.array2, e.array3);
+            }
+            if (e.reportID == PartialArrayIntAvailableEventArgs.PACKET_LIS2DH)
+            {
+                if (accel.Enable)
+                    ProcessXYZ(e.array1, e.array2, e.array3);
+            }
+        }
+
+        void OnFileLogEnable(object sender, EnableEventArgs e)
+        {
+            optical = new RawFileLogView();
+            accel = new RawFileLogView();
+
+            if (logFileDirectory != null)
+            {
+                optical.FileDirectory = logFileDirectory;
+                //accel.FileDirectory = logFileDirectory;
+            }
+
+            if (e.Enable && e.Stream == StreamType.Optical && optical.SelectCSVFile("hsp-optical"))
+            {
+                accel.FileDirectory = optical.FileDirectory;
+                if (accel.SelectCSVFile("hsp-accel"))
+                {
+                    mainForm.OpticalLogFileItem(true);
+                    optical.Enable = true;
+                    accel.Enable = true;
+                    logFileDirectory = optical.FileDirectory;
+                }
+            }
+            else
+            {
+                mainForm.OpticalLogFileItem(false);
+                optical.Enable = false;
+                accel.Enable = false;
+            }
+        }
+
+        void OnStreamingStartStop(object sender, StreamingStartStopEventArgs e)
+        {
+            if (e.state == true)
+            {
+                View.FileLogView.FileLogHeader fileLogHeader = new View.FileLogView.FileLogHeader();
+                ppgCount = 0;
+                accelCount = 0;
+
+                if (optical.Enable == true)
+                {
+                    optical.WriteLine(opticalView.SettingsString());
+                    optical.WriteLine(fileLogHeader.Optical);
+                }
+                if (accel.Enable == true)
+                {
+                    accel.WriteLine(opticalView.AccelSettingString());
+                    accel.WriteLine(fileLogHeader.Accelerometer);
+
+                    // Try to have "0" be the same on both files
+                    optical.StreamStartStop();
+                    accel.StreamStartStop(); 
+                }
+                
+            }
+            else
+            {
+                optical.Enable = false;
+                accel.Enable = false;
+
+                mainForm.LogFileItem(StreamType.Optical, false);
+            }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HspGuiSourceV301/HSPGui/Presenter/RToRCalculator.cs	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,197 @@
+/*******************************************************************************
+* Copyright (C) 2016 Maxim Integrated Products, Inc., All rights Reserved.
+* 
+* This software is protected by copyright laws of the United States and
+* of foreign countries. This material may also be protected by patent laws
+* and technology transfer regulations of the United States and of foreign
+* countries. This software is furnished under a license agreement and/or a
+* nondisclosure agreement and may only be used or reproduced in accordance
+* with the terms of those agreements. Dissemination of this information to
+* any party or parties not specified in the license agreement and/or
+* nondisclosure agreement is expressly prohibited.
+*
+* The above copyright notice and this permission notice shall be included
+* in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+* OTHER DEALINGS IN THE SOFTWARE.
+*
+* Except as contained in this notice, the name of Maxim Integrated
+* Products, Inc. shall not be used except as stated in the Maxim Integrated
+* Products, Inc. Branding Policy.
+*
+* The mere transfer of this software does not imply any licenses
+* of trade secrets, proprietary technology, copyrights, patents,
+* trademarks, maskwork rights, or any other form of intellectual
+* property whatsoever. Maxim Integrated Products, Inc. retains all
+* ownership rights.
+*******************************************************************************
+*/
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace HealthSensorPlatform.Presenter
+{
+    /// <summary>
+    /// R To R Calculator for referring R to R code values to ECG samples
+    /// </summary>
+    public class RToRCalculator
+    {
+        const int RToROffset = 3;
+
+        double masterClockFrequency;
+        int rToRDifferentialDelay;
+
+        int ecgDelay;
+        int rToRDelay;
+
+        double sampleRateRToR;
+        double sampleRateEcg;
+
+        double rToRTimeMilliSecond;
+
+        /// <summary>
+        /// Error difference between rounded R To R in ECG samples and actual calculated value. Error used
+        /// in calculation of next R To R in ECG samples point.
+        /// </summary>
+        double ecgSampleError;
+
+        /// <summary>
+        /// FMSTR clock frequency. Array index by FMSTR[1:0]
+        /// </summary>
+        double[] clockFreq = { 32768, 32000, 32000, 32768 * 640 / 656 }; // 31968.7804878 = 32768 * 640 / 65
+        /// <summary>
+        /// ECG decimation delay. Array indexed by FMSTR, ECG_RATE, ECG_DLFF (0 for disabled, 1 for enabled) 
+        /// </summary>
+        int[, ,] ecgDecimationDelay = new int[,,] { {{650, 1034}, {2922, 3690}, {3370, 4906}, {3370, 4906}}, 
+													{{650, 1034}, {2922, 3690}, {3370, 4906}, {3370, 4906}},
+													{{1242, 2202}, {1242, 2202}, {1242, 2202}, {1242, 2202}},
+													{{1242, 2202}, {1242, 2202}, {1242, 2202}, {1242, 2202}}
+                                                  };
+
+        /// <summary>
+        /// ECG sample rate look up based on FMSTR and ECG_RATE
+        /// </summary>
+        double[][] ecgSampleRates = new double[][]
+        {
+                new double[] {512, 256, 128, 128},
+                new double[] {500, 250, 125, 125},
+                new double[] {200, 200, 200, 200},
+                new double[] {199.8, 199.8, 199.8, 199.8} 
+        };
+
+        /// <summary>
+        /// ECG processing delay in FMSTR clocks
+        /// </summary>
+        public int EcgDecimationDelay
+        {
+            get
+            {
+                return ecgDelay;
+            }
+        }
+
+        /// <summary>
+        /// R To R path processing delay in FMSTR clocks
+        /// </summary>
+        public int RToRDelay
+        {
+            get
+            {
+                return rToRDelay;
+            }
+        }
+
+        /// <summary>
+        /// Last R To R detected time in millisecond from first ECG point
+        /// </summary>
+        public double RToRMilliSecond
+        {
+            get
+            {
+                return rToRTimeMilliSecond;
+            }
+        }
+        
+        /// <summary>
+        /// Constructor for R to R calculator
+        /// </summary>
+        /// <param name="masterClockFrequencyField">Value of FMSTR[1:0]</param>
+        /// <param name="sampleRateEcgField">Value of ECG_RATE[1:0]</param>
+        /// <param name="ecgDigitalLowPass">Value of ECG_DLF[1:0]</param>
+        /// <param name="rTorWindowField">Value of RTOR_WNDW[3:0]</param>
+        public RToRCalculator(int masterClockFrequencyField, int sampleRateEcgField, int ecgDigitalLowPass, int rTorWindowField)
+        {
+            masterClockFrequency = clockFreq[masterClockFrequencyField];
+            sampleRateRToR = masterClockFrequency / 256;
+            sampleRateEcg = ecgSampleRates[masterClockFrequencyField][sampleRateEcgField];
+
+            ecgDelay = ecgDecimationDelay[masterClockFrequencyField, sampleRateEcgField, ecgDigitalLowPass > 0 ? 1 : 0];
+            rToRDelay = 5376 + 3370 + 256 * rTorWindowField;
+
+            rToRDifferentialDelay = rToRDelay - ecgDelay;
+
+            rToRTimeMilliSecond = 0;
+        }
+
+        /// <summary>
+        /// R To R code to beats per minute
+        /// </summary>
+        /// <param name="rToRCode">R To R Code</param>
+        /// <returns></returns>
+        public double BeatsPerMinute(int rToRCode)
+        {
+            return 60 * 1000 / Millisecond(rToRCode);
+        }
+
+        /// <summary>
+        /// R To R code to millisecond interval
+        /// </summary>
+        /// <param name="rToRCode">R To R Code</param>
+        /// <returns></returns>
+        public double Millisecond(double rToRCode)
+        {
+            return rToRCode * 512.0 * 1000 / (2 * masterClockFrequency);
+        }
+
+        public double Corrected(int rToR, bool first)
+        {
+            if (first)
+                rToRTimeMilliSecond = Millisecond(rToR - rToRDifferentialDelay / 256.0);
+            else
+                rToRTimeMilliSecond += Millisecond(rToR);
+
+            return rToRTimeMilliSecond;
+        }
+
+        /// <summary>
+        /// R To R code converted to ECG points
+        /// </summary>
+        /// <param name="rToR">R To R code</param>
+        /// <param name="first">first R To R sample include the processing delay between the ECG and R To R processing path</param>
+        /// <returns></returns>
+        public int EcgPoints(int rToR, bool first)
+        {
+            double rToRInEcgSamples;
+            int rToRInEcgSamplesInt;
+
+            if (first)
+                rToRInEcgSamples = (rToR - rToRDifferentialDelay / 256.0) * (sampleRateEcg / sampleRateRToR) + RToROffset;
+            else
+                rToRInEcgSamples = rToR * (sampleRateEcg / sampleRateRToR) - ecgSampleError;
+
+            rToRInEcgSamplesInt = (int)(rToRInEcgSamples + 0.5);
+            ecgSampleError = rToRInEcgSamplesInt - rToRInEcgSamples;
+
+            return rToRInEcgSamplesInt;
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HspGuiSourceV301/HSPGui/Presenter/RawFileLogPresenter.cs	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,477 @@
+/*******************************************************************************
+* Copyright (C) 2016 Maxim Integrated Products, Inc., All rights Reserved.
+* 
+* This software is protected by copyright laws of the United States and
+* of foreign countries. This material may also be protected by patent laws
+* and technology transfer regulations of the United States and of foreign
+* countries. This software is furnished under a license agreement and/or a
+* nondisclosure agreement and may only be used or reproduced in accordance
+* with the terms of those agreements. Dissemination of this information to
+* any party or parties not specified in the license agreement and/or
+* nondisclosure agreement is expressly prohibited.
+*
+* The above copyright notice and this permission notice shall be included
+* in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+* OTHER DEALINGS IN THE SOFTWARE.
+*
+* Except as contained in this notice, the name of Maxim Integrated
+* Products, Inc. shall not be used except as stated in the Maxim Integrated
+* Products, Inc. Branding Policy.
+*
+* The mere transfer of this software does not imply any licenses
+* of trade secrets, proprietary technology, copyrights, patents,
+* trademarks, maskwork rights, or any other form of intellectual
+* property whatsoever. Maxim Integrated Products, Inc. retains all
+* ownership rights.
+*******************************************************************************
+*/
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+using HealthSensorPlatform.View;
+using HealthSensorPlatform.Model;
+using HealthSensorPlatform.CustomControls;
+
+using RPCSupport;
+using RPCSupport.Streaming;
+
+namespace HealthSensorPlatform.Presenter
+{
+    public class RawFileLogPresenter
+    {
+        IRawFileLogView ecgLog;
+        IRawFileLogView bioZLog;
+        IRawFileLogView rToRLog;
+        IRawFileLogView paceLog;
+        IFormView formView;
+        IEcgView ecgView;
+
+        bool fileLog = false; // user enabled file logging
+        bool streaming = false; // streaming data or flash log data, only save data from streaming
+        //bool flashLog = false;
+
+        IDataLoggingView dataLogView;
+
+        PaceData paceData;
+
+        RToRCalculator rToRCalculator;
+        bool rToRFirst = true; // received first RR value for offset correction
+
+        //bool ecgLeadOff; // DC Lead off data for ECG or BioZ Channel
+        DCLeadOff leadOff; // lead off status bits
+        ACLeadOff acLeadOff; // bioz lead off status bits
+
+        int count = 0;
+        int bioZCount = 0;
+        //int ppgCount = 0;
+        //int accelCount = 0;
+
+        string logFileDirectory = null;
+
+        View.FileLogView.FileLogHeader fileLogHeader = new View.FileLogView.FileLogHeader();
+
+        public RawFileLogPresenter(IRawFileLogView ecg, IRawFileLogView bioZ, IRawFileLogView rToR, IRawFileLogView pace, IFormView formView, RPCClient rpcClient, IEcgView ecgView, IDataLoggingView dataLogView)
+        {
+            this.ecgLog = ecg;
+            this.bioZLog = bioZ;
+            this.rToRLog = rToR;
+            this.paceLog = pace;
+            this.formView = formView;
+            this.ecgView = ecgView;
+
+            this.dataLogView = dataLogView;
+
+            formView.FileLogEnable += new EventHandler<EnableEventArgs>(OnLogFileEnable);
+            ecgView.StreamingStartStop += new EventHandler<StreamingStartStopEventArgs>(OnStreamStart);
+            //dataLogView.LogDownloadStart += new EventHandler<EventArgs>(OnLogDownloadStart);
+            rpcClient.streaming.PartialArrayIntAvailable += new EventHandler<PartialArrayIntAvailableEventArgs>(OnStreamData);
+        }
+
+        public void OnLogFileEnable(object sender, EnableEventArgs e)
+        {
+            fileLog = e.Enable;
+
+            if (e.Enable)
+            {
+                bool result = false;
+                IRawFileLogView log = ecgLog;
+                string filePrefixName = String.Empty;
+
+                switch(e.Stream)
+                {
+                    case StreamType.Ecg:
+                        log = ecgLog;
+                        filePrefixName = "hsp-ecg";
+                        break;
+                    case StreamType.RToR:
+                        log = rToRLog;
+                        filePrefixName = "hsp-rtor";
+                        break;
+                    case StreamType.Pace:
+                        log = paceLog;
+                        filePrefixName = "hsp-pace";
+                        break;
+                    case StreamType.BioZ:
+                        log = bioZLog;
+                        filePrefixName = "hsp-bioz";
+                        break;
+                }
+
+                if (logFileDirectory != null) // Set starting directory to be the same as the last
+                    log.FileDirectory = logFileDirectory;
+
+                result = log.SelectCSVFile(filePrefixName);
+                log.Enable = result;
+
+                if (result) // Save directory if success
+                    logFileDirectory = log.FileDirectory;
+
+                formView.LogFileItem(e.Stream, result);
+            }
+            else
+            {
+                switch (e.Stream)
+                {
+                    case StreamType.Ecg:
+                        ecgLog.Enable = false;
+                        break;
+                    case StreamType.RToR:
+                        rToRLog.Enable = false;
+                        break;
+                    case StreamType.Pace:
+                        paceLog.Enable = false;
+                        break;
+                    case StreamType.BioZ:
+                        bioZLog.Enable = false;
+                        break;
+                }
+
+                formView.LogFileItem(e.Stream, false);
+            }
+        }
+
+        public void OnStreamStart(object sender, StreamingStartStopEventArgs e)
+        {
+            streaming = e.state;
+            count = 0;
+            bioZCount = 0;
+
+            if (e.state)
+            {
+                leadOff = new DCLeadOff { NegativeHigh = false, NegativeLow = false, PostiveHigh = false, PostiveLow = false };
+                acLeadOff = new ACLeadOff { BioZOverRange = false, BioZUnderRange = false };
+
+                if (ecgLog != null && ecgLog.Enable && ecgView.EnableECG)
+                {
+                    //ecgLog.WriteLine("% " + ecgView.HspSetting.EcgSettingString()); // TODO: What is the requirement for headers
+                    ecgLog.WriteLine(fileLogHeader.Ecg);
+                }
+
+                if (bioZLog != null && bioZLog.Enable && ecgView.EnableBioZ)
+                {
+                    //ecgLog.WriteLine("% " + ecgView.HspSetting.BioZSettingString());
+                    bioZLog.WriteLine(fileLogHeader.BioZ);
+                }
+
+                if (rToRLog != null && rToRLog.Enable && ecgView.EnableRToR)
+                {
+                    rToRLog.WriteLine(fileLogHeader.RToR);
+                    rToRCalculator = new RToRCalculator(ecgView.MasterClockField, ecgView.EcgArgs.Rate, ecgView.EcgArgs.Dlpf, ecgView.RToRArgs.Wndw);
+                }
+
+                if (paceLog != null && paceLog.Enable && ecgView.EnablePace)
+                {
+                    paceLog.WriteLine(fileLogHeader.Pace);
+                }
+            }
+            else
+            {
+                if (ecgLog != null)
+                    ecgLog.Enable = false;
+
+                if (bioZLog != null)
+                    bioZLog.Enable = false;
+
+                if (rToRLog != null)
+                    rToRLog.Enable = false;
+
+                if (paceLog != null)
+                    paceLog.Enable = false;
+            }
+        }
+
+        void fileLogStop()
+        {
+            fileLog = false;
+            stop();
+
+        }
+
+        void stop()
+        {
+            if (ecgLog != null && ecgLog.Enable)
+                ecgLog.Enable = false;
+
+            if (rToRLog != null && rToRLog.Enable)
+                rToRLog.Enable = false;
+
+            if (paceLog != null && paceLog.Enable)
+                paceLog.Enable = false;
+
+            if (bioZLog != null && bioZLog.Enable)
+                bioZLog.Enable = false;
+
+            formView.LogFileItem(StreamType.Ecg, false);
+            formView.LogFileItem(StreamType.RToR, false);
+            formView.LogFileItem(StreamType.Pace, false);
+            formView.LogFileItem(StreamType.BioZ, false);
+        }
+
+        private void OnStreamData(object sender, PartialArrayIntAvailableEventArgs e)
+        {
+            if (streaming)
+            {
+                switch (e.reportID)
+                {
+                    case PartialArrayIntAvailableEventArgs.PACKET_MAX30001_ECG:
+                        if (ecgLog.Enable)
+                            ProcessEcg(e.array1);
+                        break;
+                    case PartialArrayIntAvailableEventArgs.PACKET_MAX30001_BIOZ:
+                        if (bioZLog.Enable)
+                            ProcessBioZ(e.array1);
+                        break;
+                    case PartialArrayIntAvailableEventArgs.PACKET_MAX30001_PACE:
+                        if (paceLog.Enable)
+                            paceData = new PaceData(e.array1);
+                        break;
+                    case PartialArrayIntAvailableEventArgs.PACKET_MAX30001_RTOR:
+                        if (rToRLog.Enable)
+                            ProcessRToR(e.array1[0]);
+                        break;
+                    case PartialArrayIntAvailableEventArgs.PACKET_END_OF_STREAM:
+                        fileLogStop();
+                        break;
+                    case PartialArrayIntAvailableEventArgs.PACKET_MAX30001_LEADOFF_DC:
+                        ProcessLeadOff(e.array1[0]);
+                        break;
+                    case PartialArrayIntAvailableEventArgs.PACKET_MAX30001_LEADOFF_AC:
+                        ProcessACLeadOff(e.array1[0]);
+                        break;
+                }
+            }
+        }
+
+        void ProcessBioZ(int[] rawData)
+        {
+            BioZFifo[] bioZFifo;
+            double sampleRate = ecgView.SampleRateBioZ;
+            double[] time = new double[rawData.Length];
+
+            bioZFifo = ConvertBioZ(rawData);
+
+            for (int i = 0; i < time.Length; i++)
+            {
+                time[i] = bioZCount / sampleRate;
+                bioZCount++;
+            }
+
+            if (ecgView.EnableDCLeadOff == false && ecgView.EnableBioZOverUnderRange == true)
+                bioZLog.DisplayBioZ(time, bioZFifo, acLeadOff);
+            else if (ecgView.EnableDCLeadOff == true && ecgView.EnableEcgDCLeadOff == false && ecgView.EnableBioZOverUnderRange == false) // && ecgLeadOff == false)
+                bioZLog.DisplayBioZ(time, bioZFifo, leadOff);
+            else if (ecgView.EnableDCLeadOff == true && ecgView.EnableEcgDCLeadOff == false && ecgView.EnableBioZOverUnderRange == true)
+                bioZLog.DisplayBioZ(time, bioZFifo, leadOff, acLeadOff);
+            else if ((ecgView.EnableDCLeadOff == false && ecgView.EnableBioZOverUnderRange == false) ||
+                ecgView.EnableEcgDCLeadOff == true && ecgView.EnableEcgDCLeadOff == true && ecgView.EnableBioZOverUnderRange == false)
+                bioZLog.DisplayBioZ(time, bioZFifo);
+        }
+
+        public BioZFifo[] ConvertBioZ(int[] data)
+        {
+            BioZFifo[] impedance = new BioZFifo[data.Length];
+            EcgView.ChartInfo chartInfo = ecgView.BioZInfo;
+            int dataShift;
+
+            for (int i = 0; i < data.Length; i++)
+            {
+                dataShift = data[i] >> chartInfo.Shift;
+
+                // Two's Complement Conversions
+                if (dataShift > chartInfo.Threshold)
+                {
+                    dataShift -= chartInfo.Offset;
+                }
+
+                // 1.9734 = 1/2^19 * 1e-6
+                impedance[i].Data = dataShift * 1.9073486328125 /
+                    (chartInfo.Gain * ((chartInfo.CurrentGenerator == 0) ? 1 : chartInfo.CurrentGenerator));
+                impedance[i].Code = data[i];
+                impedance[i].BioZData = dataShift;
+                impedance[i].BTag = data[i] & 0x07;
+            }
+
+            return impedance;
+        }
+
+        void ProcessEcg(int[] rawData)
+        {
+            EcgFifo[] ecgFifo;
+            double ecgRate = ecgView.SampleRateEcg;
+            double[] ecgVoltage = new double[rawData.Length];
+            double[] timeSecond = new double[rawData.Length];
+
+            ecgFifo = ConvertEcg(rawData);
+
+            for (int i = 0; i < ecgFifo.Length; i++ )
+            {
+                timeSecond[i] = count / ecgRate;
+
+                // Look for Pace Events
+                if (paceLog.Enable)
+                {
+                    //for (int j = 0; j < ecgFifo.Length; j++)
+                    //{
+                        if (ecgFifo[i].PTag != 7)
+                        {
+                            PaceData.PaceRegister paceRegister = paceData.PaceGroup(ecgFifo[i].PTag);
+                            List<double> timeMillsecondPace = new List<double>();
+                            List<PaceData.PaceEdge> paceEdges = new List<PaceData.PaceEdge>();
+
+                            for (int k = 0; k < 6; k++)
+                            {
+                                PaceData.PaceEdge edge = paceRegister.Edge[k];
+
+                                timeMillsecondPace.Add(count / ecgRate + ConvertPace(edge.Data));
+                                paceEdges.Add(edge);
+
+                                if (edge.Last == true)
+                                    break;
+                            }
+
+                            paceLog.DisplayPace(timeMillsecondPace.ToArray(), paceEdges.ToArray());
+                            System.Diagnostics.Debug.Print("ECG PTag = " + ecgFifo[i].PTag);
+                        }
+                    //}
+                }
+
+                count++;
+            }
+
+            if (ecgView.EnableDCLeadOff && ecgView.EnableEcgDCLeadOff)
+                ecgLog.DisplayEcg(timeSecond, ecgFifo, leadOff);
+            else
+                ecgLog.DisplayEcg(timeSecond, ecgFifo);
+            
+        }
+
+        public EcgFifo[] ConvertEcg(int[] data)
+        {
+            EcgFifo[] voltage = new EcgFifo[data.Length];
+            EcgView.ChartInfo chartInfo = ecgView.EcgInfo;
+            int dataShift;
+
+            for (int i = 0; i < data.Length; i++)
+            {
+                dataShift = data[i] >> chartInfo.Shift;
+
+                // Two's Complement Conversions
+                if (dataShift > chartInfo.Threshold)
+                {
+                    dataShift -= chartInfo.Offset;
+                }
+
+                voltage[i].Data = 1000 * 7.62939453125e-6 * dataShift / chartInfo.Gain;
+                voltage[i].EcgData = dataShift;
+                voltage[i].Code = data[i];
+                voltage[i].PTag = data[i] & 0x07;
+                voltage[i].ETag = (data[i] >> 3) & 0x07;
+            }
+
+            return voltage;
+        }
+
+        public double ConvertRToR(int data)
+        {
+            return ecgView.TimeResolution * 1000 * data * 512;
+        }
+
+        public double ConvertPace(int data)
+        {
+            return data * ecgView.TimeResolution;
+        }
+
+        public string PaceRegisterGroupToString(PaceData.PaceRegister paceRegister)
+        {
+            StringBuilder paceRegisterLogBuilder = new StringBuilder();
+            for (int j = 0; j < 6; j++)
+            {
+                paceRegisterLogBuilder.Append(paceRegister.Edge[j].Data / (2 * ecgView.MasterClockFrequency));
+                paceRegisterLogBuilder.Append(", ");
+                paceRegisterLogBuilder.Append(paceRegister.Edge[j].Polarity ? 'R' : 'F');
+                paceRegisterLogBuilder.Append(", ");
+                paceRegisterLogBuilder.Append(paceRegister.Edge[j].Last ? 'Y' : 'N');
+                paceRegisterLogBuilder.Append(", ");
+            }
+
+            return paceRegisterLogBuilder.ToString();
+        }
+
+        void ProcessLeadOff(int data)
+        {
+            /*
+            if (bitShiftMask(data, 8)) // ECG lead off
+                ecgLeadOff = true;
+            else if (bitShiftMask(data, 9)) // BioZ lead off
+                ecgLeadOff = false;
+            */
+
+            leadOff = new DCLeadOff()
+            {
+                PostiveHigh = bitShiftMask(data, 3),
+                PostiveLow = bitShiftMask(data, 2),
+                NegativeHigh = bitShiftMask(data, 1),
+                NegativeLow = bitShiftMask(data, 0)
+            };
+
+        }
+
+        void ProcessACLeadOff(int data)
+        {
+            acLeadOff = new ACLeadOff()
+            {
+                BioZUnderRange = bitShiftMask(data, 1),
+                BioZOverRange = bitShiftMask(data, 0),
+            };
+        }
+
+        private static bool bitShiftMask(int data, int index)
+        {
+            int state;
+            int mask = 1 << index;
+            state = ((data & mask) == mask) ? 1 : 0;
+            return state == 1;
+        }
+
+        void ProcessRToR(int data)
+        {
+            if (rToRFirst)
+            {
+                rToRLog.DisplayRToR(data, rToRCalculator.Corrected(data, true) / 1000);
+                rToRFirst = false;
+            }
+            else
+                rToRLog.DisplayRToR(data, rToRCalculator.Corrected(data, false) / 1000);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HspGuiSourceV301/HSPGui/Presenter/RegisterExportPresenter.cs	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,183 @@
+/*******************************************************************************
+* Copyright (C) 2016 Maxim Integrated Products, Inc., All rights Reserved.
+* 
+* This software is protected by copyright laws of the United States and
+* of foreign countries. This material may also be protected by patent laws
+* and technology transfer regulations of the United States and of foreign
+* countries. This software is furnished under a license agreement and/or a
+* nondisclosure agreement and may only be used or reproduced in accordance
+* with the terms of those agreements. Dissemination of this information to
+* any party or parties not specified in the license agreement and/or
+* nondisclosure agreement is expressly prohibited.
+*
+* The above copyright notice and this permission notice shall be included
+* in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+* OTHER DEALINGS IN THE SOFTWARE.
+*
+* Except as contained in this notice, the name of Maxim Integrated
+* Products, Inc. shall not be used except as stated in the Maxim Integrated
+* Products, Inc. Branding Policy.
+*
+* The mere transfer of this software does not imply any licenses
+* of trade secrets, proprietary technology, copyrights, patents,
+* trademarks, maskwork rights, or any other form of intellectual
+* property whatsoever. Maxim Integrated Products, Inc. retains all
+* ownership rights.
+*******************************************************************************
+*/
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+using System.Globalization;
+
+using HealthSensorPlatform.View;
+using Maxim.CustomControls;
+using Maxim.Utility;
+
+namespace HealthSensorPlatform.Presenter
+{
+    class RegisterExportPresenter
+    {
+        IRegisterExportView exportView;
+        IFormView hspMainForm;
+        List<RegisterView> registerModels;
+
+        Dictionary<string, RegisterView> registerModelDict;
+
+        FileLog registerDataFile;
+        FileCsvReader fileReader;
+
+        public RegisterExportPresenter(IFormView hspMainForm, IRegisterExportView exportView, List<RegisterView> registerModels)
+        {
+            this.exportView = exportView;
+            this.registerModels = registerModels;
+            this.hspMainForm = hspMainForm;
+
+            exportView.SelectionComplete += new EventHandler<CompleteEventArgs>(OnSelectionComplete);
+
+            hspMainForm.RegisterExport += new EventHandler<EventArgs>(OnRegisterExport);
+            hspMainForm.RegisterImport += new EventHandler<EventArgs>(OnRegisterImport);
+            hspMainForm.Connected += new EventHandler<EventArgs>(OnConnected);
+
+            registerDataFile = new FileLog();
+            fileReader = new FileCsvReader();
+
+            registerModelDict = new Dictionary<string, RegisterView>();
+
+            foreach (RegisterView rV in registerModels)
+            {
+                registerModelDict.Add(rV.DeviceName, rV);
+                if (rV.DeviceName == "MAX30001")
+                    registerModelDict.Add("MAX30003", rV); // add a second reference for MAX30003
+            }
+
+        }
+
+        public List<string> GetDeviceNames()
+        {
+            List<string> devices = new List<string>();
+
+            foreach(RegisterView device in registerModels)
+            {
+                devices.Add(device.DeviceName);
+            }
+
+            return devices;
+        }
+
+        private void OnConnected(object sender, EventArgs e)
+        {
+            exportView.Devices = GetDeviceNames();
+            exportView.SelectedDevices = new List<string>();
+        }
+
+        private void OnRegisterExport(object sender, EventArgs e)
+        {
+            exportView.Show();            
+        }
+
+        private void OnRegisterImport(object sender, EventArgs e)
+        {
+            char[] hexSymbol = new char[] { 'h', 'H' };
+            bool ok = true;
+
+            if (fileReader.OpenCSVFile())
+            {
+                    while (fileReader.Peek() > 0)
+                    {
+                        string[] elements = fileReader.ReadLineElements();
+                        string registerAddress;
+                        string registerValue;
+
+                        // End of data
+                        if (elements[0].Contains('%') || elements[0] == String.Empty)
+                            continue;
+
+                        if (ok = registerModelDict.ContainsKey(elements[0]))
+                        {
+                            RegisterView view = registerModelDict[elements[0]]; // Look up in dictionary
+
+                            registerAddress = elements[1].TrimEnd(hexSymbol);
+                            registerValue = elements[3].TrimEnd(hexSymbol);
+
+                            RPCSupport.DeviceSupport.RegisterInfo reg = view.RegisterAddress(Int32.Parse(registerAddress, NumberStyles.HexNumber));
+
+                            if (reg.type == RPCSupport.DeviceSupport.RegisterInfo.RegisterType.None)
+                                view.WriteRegister(reg, Int32.Parse(registerValue, NumberStyles.HexNumber));
+                        }
+                        else
+                            break;
+                }
+
+                fileReader.Close();
+
+                if (ok)
+                {
+                    hspMainForm.UpdateRegisters();
+                    hspMainForm.MessageBoxShow("Register load complete", "Register Import/Export");
+                }
+                else
+                {
+                    hspMainForm.MessageBoxShow("Register load failed, file format incorrect", "Register Import/Export");
+                }
+            }
+        }
+
+        private void OnSelectionComplete(object sender, CompleteEventArgs e)
+        {
+            List<string> devices = exportView.SelectedDevices;
+
+            if (e.Complete == true) // Successful device selection
+            {
+                if (registerDataFile.SelectCSVFile("hsp-register_data")) // Successful file selection
+                {
+                    foreach (string device in devices) // Match string with RegisterView
+                    {
+                        RegisterView regView = registerModelDict[device]; // Find register view corresponding with device name
+
+                        regView.ReadAll(); // Update register values
+                        registerDataFile.WriteLine("% Device, Address (hex), Name, Value (hex)");
+                        registerDataFile.WriteLine(regView.RegistersToString()); // Do the Export
+                        registerDataFile.WriteLine("%"); // End of register data
+                    }
+
+                    registerDataFile.Close();
+
+                    hspMainForm.MessageBoxShow("Register save complete", "Register Import/Export");
+                }
+            }
+
+        }
+
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HspGuiSourceV301/HSPGui/Presenter/StreamPresenter.cs	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,265 @@
+/*******************************************************************************
+* Copyright (C) 2016 Maxim Integrated Products, Inc., All rights Reserved.
+* 
+* This software is protected by copyright laws of the United States and
+* of foreign countries. This material may also be protected by patent laws
+* and technology transfer regulations of the United States and of foreign
+* countries. This software is furnished under a license agreement and/or a
+* nondisclosure agreement and may only be used or reproduced in accordance
+* with the terms of those agreements. Dissemination of this information to
+* any party or parties not specified in the license agreement and/or
+* nondisclosure agreement is expressly prohibited.
+*
+* The above copyright notice and this permission notice shall be included
+* in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+* OTHER DEALINGS IN THE SOFTWARE.
+*
+* Except as contained in this notice, the name of Maxim Integrated
+* Products, Inc. shall not be used except as stated in the Maxim Integrated
+* Products, Inc. Branding Policy.
+*
+* The mere transfer of this software does not imply any licenses
+* of trade secrets, proprietary technology, copyrights, patents,
+* trademarks, maskwork rights, or any other form of intellectual
+* property whatsoever. Maxim Integrated Products, Inc. retains all
+* ownership rights.
+*******************************************************************************
+*/
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+using RPCSupport;
+using RPCSupport.Streaming;
+using HealthSensorPlatform.CustomControls;
+using HealthSensorPlatform.Model;
+using HealthSensorPlatform.View;
+
+namespace HealthSensorPlatform.Presenter
+{
+    public class StreamPresenter
+    {
+        const double NoData = -5000;
+        const int NoRToR = -1;
+
+        private RPCClient rpcClient;
+        private EcgView ecgView;
+        private IFormView formView;
+        private int rToRRaw = NoRToR;
+        private PaceData paceData;
+        private bool start = false;
+
+        public StreamPresenter()
+        {
+
+        }
+
+        public StreamPresenter(EcgView ecgView)
+        {
+            this.ecgView = ecgView;
+        }
+
+        public StreamPresenter(RPCClient rpcClient, EcgView ecgView, IFormView formView)
+        {
+            this.rpcClient = rpcClient;
+            this.ecgView = ecgView;
+            this.formView = formView;
+
+            ecgView.StreamingStartStop += new EventHandler<StreamingStartStopEventArgs>(OnStreamingStartStop);
+            rpcClient.streaming.PartialArrayIntAvailable += new EventHandler<PartialArrayIntAvailableEventArgs>(OnStreamData);
+        }
+
+        private void OnStreamingStartStop(object sender, StreamingStartStopEventArgs e)
+        {
+            start = e.state;
+
+            if (ecgView.Connected && !start) // Clear Interrupts on stream start and stop, start to prevent RPC Int Assignment freeze
+            {
+                rpcClient.MAX30001.WriteReg(0x02, 0x03); // Stop Interrupts
+                rpcClient.MAX30001.WriteReg(0x03, 0x03); // Stop Interrupts
+            }
+
+            formView.EcgLogFileItem(false);
+            formView.BioZLogFileItem(false);
+            formView.RtoRLogFileItem(false);
+            formView.PaceLogFileItem(false);
+        }
+
+        private void OnStreamData(object sender, PartialArrayIntAvailableEventArgs e)
+        {
+            int leadOffState;
+            if (start && e.array1.Length > 0) // Ignore events unless started (from flash logging)
+            {
+                leadOffState = e.array1[0];
+
+                switch(e.reportID)
+                {
+                    case PartialArrayIntAvailableEventArgs.PACKET_MAX30001_LEADOFF_DC:
+                        ecgView.SetDCLeadOff(leadOffState);
+                        break;
+                    case PartialArrayIntAvailableEventArgs.PACKET_MAX30001_LEADOFF_AC:
+                        ecgView.SetACLeadOff(leadOffState);
+                        break;
+                }
+
+                switch (e.reportID)
+                {
+                    case PartialArrayIntAvailableEventArgs.PACKET_MAX30001_ECG:
+                        ProcessEcg(e.array1);
+                        break;
+                    case PartialArrayIntAvailableEventArgs.PACKET_MAX30001_BIOZ:
+                        ProcessBioZ(e.array1);
+                        break;
+                    case PartialArrayIntAvailableEventArgs.PACKET_MAX30001_PACE:
+                        ProcessPace(e.array1);
+                        break;
+                    case PartialArrayIntAvailableEventArgs.PACKET_MAX30001_RTOR:
+                        rToRRaw = e.array1[0];
+                        ecgView.DisplayRToR(e.array1[0]);
+                        break;
+                }
+            }
+        }
+
+        void ProcessBioZ(int[] rawData)
+        {
+            BioZFifo[] bioZFifo;
+            double[] bioZImpedance;
+
+            bioZFifo = ConvertBioZ(rawData);
+
+            bioZImpedance = new double[bioZFifo.Length];
+            for (int i = 0; i < bioZFifo.Length; i++)
+            {
+                bioZImpedance[i] = bioZFifo[i].Data;
+            }
+            ecgView.DisplayBioZ(bioZImpedance);
+        }
+
+        public BioZFifo[] ConvertBioZ(int[] data)
+        {
+            BioZFifo[] impedence = new BioZFifo[data.Length];
+            EcgView.ChartInfo chartInfo = ecgView.BioZInfo;
+            int dataShift;
+
+            for (int i = 0; i < data.Length; i++)
+            {
+                dataShift = data[i] >> chartInfo.Shift;
+
+                // Two's Complement Conversions
+                if (dataShift > chartInfo.Threshold)
+                {
+                    dataShift -= chartInfo.Offset;
+                }
+
+                // 1.9734 = 1/2^19 * 1e-6
+                impedence[i].Data = dataShift * 1.9073486328125 /
+                    (chartInfo.Gain * ((chartInfo.CurrentGenerator == 0) ? 1 : chartInfo.CurrentGenerator));
+                impedence[i].BTag = data[i] & 0x07;
+            }
+
+            return impedence;
+        }
+
+        public double[] ProcessEcg(int[] rawData)
+        {
+            EcgFifo[] ecgFifo;
+            double[] ecgVoltage = new double[rawData.Length];
+            double[] rToRInterval = null;
+
+            // Pace File Log
+            string[] paceRegisterLog = new string[rawData.Length];
+
+            List<EcgView.PacePoint> pacePoints = new List<EcgView.PacePoint>();
+
+            ecgFifo = ConvertEcg(rawData); 
+
+            // ECG
+            for (int i = 0; i < ecgFifo.Length; i++)
+            {
+                ecgVoltage[i] = ecgFifo[i].Data;
+
+                if (ecgFifo[i].PTag != 0x07 && paceData != null) // Pace Event
+                {
+                    PaceData.PaceRegister paceRegister = paceData.PaceGroup(ecgFifo[i].PTag); // Register Group
+                    PaceData.PaceEdge[] paceEdges = paceRegister.Edge; // Pace Edge
+                    
+                    // Pace Charting Data
+                    int k = 0;
+                    PaceData.PaceEdge edge;
+                    do
+                    {
+                        edge = paceEdges[k];
+                        // Convert Pace into ECG samples
+                        // (Pace Raw / (2 * FMSTR )) / (1 / ECG Sample Rate) = Pace Raw * ECG Sample Rate / (2 * FMSTR)
+                        pacePoints.Add(new EcgView.PacePoint(i + (edge.Data * ecgView.SampleRateEcg / (2 * ecgView.MasterClockFrequency)), edge.Polarity));
+
+                        k++;
+                    }
+                    while (!(edge.Last == true || k >= 6));
+                }
+            }
+
+            // R to R
+            if (ecgView.EnableRToR)
+            {
+                rToRInterval = new double[rawData.Length];
+                for (int i = 0; i < rToRInterval.Length; i++)
+                {
+                    rToRInterval[i] = NoData;
+                }
+
+                if (rToRRaw > 0)
+                {
+                    rToRInterval[0] = ecgVoltage[0]; // Plot at height of ECG signal
+                    rToRRaw = NoRToR;
+                }
+            }
+
+            ecgView.DisplayEcg(ecgVoltage, pacePoints.ToArray(), rToRInterval);
+
+            return ecgVoltage;
+        }
+
+        public EcgFifo[] ConvertEcg(int[] data)
+        {
+            EcgFifo[] voltage = new EcgFifo[data.Length];
+            EcgView.ChartInfo chartInfo = ecgView.EcgInfo;
+            int dataShift;
+
+            for (int i = 0; i < data.Length; i++)
+            {
+                dataShift = data[i] >> chartInfo.Shift;
+
+                // Two's Complement Conversions
+                if (dataShift > chartInfo.Threshold)
+                {
+                    dataShift -= chartInfo.Offset;
+                }
+
+                voltage[i].Data = 1000 * 7.62939453125e-6 * dataShift / chartInfo.Gain;
+                voltage[i].PTag = data[i] & 0x07;
+                voltage[i].ETag = (data[i] >> 3) & 0x07;
+            }
+
+            return voltage;
+        }
+
+        public PaceData ProcessPace(int[] data)
+        {
+            paceData = new PaceData(data);
+
+            return paceData;
+        }
+
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HspGuiSourceV301/HSPGui/Presenter/TemperaturePresenter.cs	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,299 @@
+/*******************************************************************************
+* Copyright (C) 2016 Maxim Integrated Products, Inc., All rights Reserved.
+* 
+* This software is protected by copyright laws of the United States and
+* of foreign countries. This material may also be protected by patent laws
+* and technology transfer regulations of the United States and of foreign
+* countries. This software is furnished under a license agreement and/or a
+* nondisclosure agreement and may only be used or reproduced in accordance
+* with the terms of those agreements. Dissemination of this information to
+* any party or parties not specified in the license agreement and/or
+* nondisclosure agreement is expressly prohibited.
+*
+* The above copyright notice and this permission notice shall be included
+* in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+* OTHER DEALINGS IN THE SOFTWARE.
+*
+* Except as contained in this notice, the name of Maxim Integrated
+* Products, Inc. shall not be used except as stated in the Maxim Integrated
+* Products, Inc. Branding Policy.
+*
+* The mere transfer of this software does not imply any licenses
+* of trade secrets, proprietary technology, copyrights, patents,
+* trademarks, maskwork rights, or any other form of intellectual
+* property whatsoever. Maxim Integrated Products, Inc. retains all
+* ownership rights.
+*******************************************************************************
+*/
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Timers;
+using System.Windows.Forms;
+using MAX30205EVKit.Model;
+using MAX30205EVKit.View;
+
+using HealthSensorPlatform.CustomControls;
+using HealthSensorPlatform;
+
+using Maxim.Utility;
+
+namespace MAX30205EVKit.Presenter
+{
+    class TemperaturePresenter 
+    {
+        ITemperatureModel[] model;
+        ITemperatureView view;
+        IDeviceView connected;
+        //IFileLogView fileLogView;
+
+        TemperatureValue temperature;
+        TemperatureValue overTemperature;
+        TemperatureValue hystersis;
+
+        //bool firstTime = true;
+        //double time = 0.0;
+
+        public TemperaturePresenter(ITemperatureModel[] model, IDeviceView connected, ITemperatureView view) 
+        {
+            this.model = model;
+            this.view = view;
+            this.connected = connected;
+
+            //this.fileLogView = fileLogView;
+
+            view.ReadAll += new EventHandler<EventArgs>(OnReadAll);
+            view.RequestReadTemperature += new EventHandler<EventArgs>(OnReadTemperature);
+            view.OverTemperatureChanged += new EventHandler<TemperatureEventArgs>(OnOverTemperatureChanged);
+            view.HystersisChanged += new EventHandler<TemperatureEventArgs>(OnHystersisChanged);
+            view.WriteRegister += new EventHandler<WriteRegisterEventArgs>(OnWriteRegister);
+            view.DataFormatChanged += new EventHandler<DataFormatEventArgs>(OnDataFormatChanged);
+        }
+
+        /*
+        public TemperaturePresenter(ITemperatureModel model, IDeviceView connected, ITemperatureView view, IFileLogView fileLogView)
+        {
+            this.model = model;
+            this.view = view;
+            this.connected = connected;
+
+            this.fileLogView = fileLogView;
+
+            view.ReadAll += new EventHandler<EventArgs>(OnReadAll);
+            view.RequestReadTemperature += new EventHandler<EventArgs>(OnReadTemperature);
+            view.OverTemperatureChanged += new EventHandler<TemperatureEventArgs>(OnOverTemperatureChanged);
+            view.HystersisChanged += new EventHandler<TemperatureEventArgs>(OnHystersisChanged);
+            view.WriteRegister += new EventHandler<WriteRegisterEventArgs>(OnWriteRegister);
+
+        } 
+        */
+
+        public void WriteRegister(int index, int register, int data)
+        {
+            if (connected.Connected)
+                model[index].RegWrite(register, data);
+        }
+
+        public void OnReadAll(object sender, EventArgs e)
+        {
+            int temperatureHex;
+            int configuration;
+            int hystersisHex;
+            int overTemperatureHex;
+
+
+            if (connected.Connected)
+            {
+                for (int i = 0; i < model.Length; i++)
+                {
+                    temperatureHex = model[i].RegRead(0x00);
+                    configuration = model[i].RegRead(0x01);
+                    hystersisHex = model[i].RegRead(0x02);
+                    overTemperatureHex = model[i].RegRead(0x03);
+
+                    temperature = new TemperatureValue(temperatureHex, model[i].DataFormat);
+                    overTemperature = new TemperatureValue(overTemperatureHex, model[i].DataFormat);
+                    hystersis = new TemperatureValue(hystersisHex, model[i].DataFormat);
+
+                    view.DisplayTemperature(i, temperature);
+                    view.DisplayConfigurationRegister(i, configuration);
+                    view.DisplayOverTemperature(i, overTemperature);
+                    view.DisplayHysteresis(i, hystersis);
+                }
+            }
+        }
+
+        public void OnDataFormatChanged(object sender, DataFormatEventArgs e)
+        {
+            int hysteresisHex = model[e.Index].Registers[0x02];
+            int overtemperature = model[e.Index].Registers[0x03];
+
+            if (connected.Connected)
+            {
+                overTemperature = new TemperatureValue(overtemperature, e.DataFormat);
+                hystersis = new TemperatureValue(hysteresisHex, e.DataFormat);
+
+                view.DisplayOverTemperature(e.Index, overTemperature);
+                view.DisplayHysteresis(e.Index, hystersis);
+            }
+        }
+
+        void OnReadTemperature(object sender, EventArgs e)
+        {
+            if (connected.Connected)
+            {
+                for (int i = 0; i < model.Length; i++)
+                {
+                    int configuration = model[i].RegRead(0x01);
+
+                    //model[i].RegWrite(0x01, configuration | 0x81);
+                    model[i].RegWrite(0x01, configuration | 0x80);
+                    System.Threading.Thread.Sleep(50);
+                    int temp = model[i].RegRead(0x00);
+
+                    TemperatureValue tempValue = new TemperatureValue(temp, model[i].DataFormat);
+                    view.DisplayTemperature(i, tempValue);
+
+                    //If user chooses to log Temperature, write lines to CSV
+                    WriteTempToFileLog(tempValue);
+                }
+            }
+        }
+
+
+
+        void OnOverTemperatureChanged(object sender, TemperatureEventArgs e)
+        {
+            if (!IsWithinRange(e.Temperature.ToString(), model[e.Index].DataFormat))
+                view.DisplayError(e.Control, "Temperature Out of Range");
+            else
+            {
+                overTemperature = new TemperatureValue(e.Temperature, model[e.Index].DataFormat);
+
+                view.DisplayOverTemperature(e.Index, overTemperature);
+
+                if (connected.Connected)
+                    model[e.Index].RegWrite(0x03, overTemperature.TemperatureHex);
+            }
+            
+        }
+
+        void OnHystersisChanged(object sender, TemperatureEventArgs e)
+        {
+            if (!IsWithinRange(e.Temperature.ToString(), model[e.Index].DataFormat))
+                view.DisplayError(e.Control, "Temperature Out of Range");
+            else
+            {
+                hystersis = new TemperatureValue(e.Temperature, model[e.Index].DataFormat);
+
+                view.DisplayHysteresis(e.Index, hystersis);
+
+                if (connected.Connected)
+                    model[e.Index].RegWrite(0x02, hystersis.TemperatureHex);
+            }
+
+            
+        }
+
+        void OnWriteRegister(object sender, WriteRegisterEventArgs e)
+        {
+            WriteRegister(e.Index, e.Register, e.Data);
+        }
+
+        void WriteTempToFileLog(TemperatureValue tempValue)
+        {
+            /*
+            if (fileLogView.Enable)
+            {
+                if (firstTime)
+                {
+                    firstTime = false;
+                    fileLogView.WriteLine("Time (s), Temperature (°C)");
+                }
+                else
+                {
+                    time = time + view.RefreshRate;
+                }
+                var temp = Math.Round(tempValue.TemperatureC, 3);
+                fileLogView.WriteTemp(time, temp);
+            }
+             */
+        }
+
+        bool IsWithinRange(string str, bool dataFormat)
+        {
+            double temp;
+            if (Double.TryParse(str, out temp))
+            {
+                if (!dataFormat)
+
+                    return (temp >= -128.00) && (temp < 127.997);
+
+                return (temp >= -64.00) && (temp < 191.997);
+            }
+
+            return false;
+        }
+
+        /*        void OnTimerTick(object sender, ElapsedEventArgs e)
+                {
+                    if (connected.Connected)
+                    {
+                        int temperature;
+
+                        model.RegWrite(0x01, model.Registers[0x01] | 0x81);
+                        System.Threading.Thread.Sleep(50);
+                        temperature = model.RegRead(0x00);
+
+                        TemperatureValue tempValue = new TemperatureValue(temperature, model.DataFormat);
+                        view.DisplayTemperature(0, tempValue);
+                    }
+                }*/
+
+
+
+        /*        double hexToTemperature(int hex, bool dataFormat, bool unitCelsius)
+                {
+                    int normalCode;
+                    int rawCode = hex;
+                    double celsius;
+
+                    if (rawCode > 0x7fff)
+                        normalCode = rawCode - 0x10000;
+                    else
+                        normalCode = rawCode;
+
+                    if (dataFormat == false)
+                        celsius = normalCode / Math.Pow(2, 8);
+                    else
+                        celsius = normalCode / Math.Pow(2, 8) + 64;
+
+                    if (unitCelsius == true)
+                        return celsius;
+                    else
+                        return celsiusToFahrenheit(celsius);
+
+                }*/
+
+        //        short temperatureToHex(double temperature)
+        //        {
+        //            return (short)(temperature * Math.Pow(2, 8));
+        //        }
+        //
+        //        double celsiusToFahrenheit(double temperature)
+        //        {
+        //            return temperature * 9 / 5 + 32;
+        //        }
+
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HspGuiSourceV301/HSPGui/Program.cs	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,27 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Windows.Forms;
+
+namespace HealthSensorPlatform
+{
+    static class Program
+    {
+        /// <summary>
+        /// The main entry point for the application.
+        /// </summary>
+        [STAThread]
+        static void Main()
+        {
+            if (Environment.OSVersion.Version.Major >= 6)
+                SetProcessDPIAware();
+
+            Application.EnableVisualStyles();
+            Application.SetCompatibleTextRenderingDefault(false);
+            Application.Run(new HspForm());
+        }
+
+        [System.Runtime.InteropServices.DllImport("user32.dll")]
+        private static extern bool SetProcessDPIAware();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HspGuiSourceV301/HSPGui/Properties/AssemblyInfo.cs	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,36 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following 
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("Health Sensor Platform")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("Maxim Integrated")]
+[assembly: AssemblyProduct("MAXREFDES100#")]
+[assembly: AssemblyCopyright("Copyright ©  2016")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible 
+// to COM components.  If you need to access a type in this assembly from 
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("a8307c61-71df-4746-97e1-fd3caf234a69")]
+
+// Version information for an assembly consists of the following four values:
+//
+//      Major Version
+//      Minor Version 
+//      Build Number
+//      Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers 
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("3.0.0.0")]
+[assembly: AssemblyFileVersion("3.0.0.0")]
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HspGuiSourceV301/HSPGui/Properties/Resources.Designer.cs	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,583 @@
+//------------------------------------------------------------------------------
+// <auto-generated>
+//     This code was generated by a tool.
+//     Runtime Version:4.0.30319.42000
+//
+//     Changes to this file may cause incorrect behavior and will be lost if
+//     the code is regenerated.
+// </auto-generated>
+//------------------------------------------------------------------------------
+
+namespace HealthSensorPlatform.Properties {
+    using System;
+    
+    
+    /// <summary>
+    ///   A strongly-typed resource class, for looking up localized strings, etc.
+    /// </summary>
+    // This class was auto-generated by the StronglyTypedResourceBuilder
+    // class via a tool like ResGen or Visual Studio.
+    // To add or remove a member, edit your .ResX file then rerun ResGen
+    // with the /str option, or rebuild your VS project.
+    [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+    [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+    internal class Resources {
+        
+        private static global::System.Resources.ResourceManager resourceMan;
+        
+        private static global::System.Globalization.CultureInfo resourceCulture;
+        
+        [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
+        internal Resources() {
+        }
+        
+        /// <summary>
+        ///   Returns the cached ResourceManager instance used by this class.
+        /// </summary>
+        [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+        internal static global::System.Resources.ResourceManager ResourceManager {
+            get {
+                if (object.ReferenceEquals(resourceMan, null)) {
+                    global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("HealthSensorPlatform.Properties.Resources", typeof(Resources).Assembly);
+                    resourceMan = temp;
+                }
+                return resourceMan;
+            }
+        }
+        
+        /// <summary>
+        ///   Overrides the current thread's CurrentUICulture property for all
+        ///   resource lookups using this strongly typed resource class.
+        /// </summary>
+        [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+        internal static global::System.Globalization.CultureInfo Culture {
+            get {
+                return resourceCulture;
+            }
+            set {
+                resourceCulture = value;
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized resource of type System.Drawing.Bitmap.
+        /// </summary>
+        internal static System.Drawing.Bitmap bio_impedance_block {
+            get {
+                object obj = ResourceManager.GetObject("bio_impedance_block", resourceCulture);
+                return ((System.Drawing.Bitmap)(obj));
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized resource of type System.Drawing.Bitmap.
+        /// </summary>
+        internal static System.Drawing.Bitmap bioz_input_mux {
+            get {
+                object obj = ResourceManager.GetObject("bioz_input_mux", resourceCulture);
+                return ((System.Drawing.Bitmap)(obj));
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized resource of type System.Drawing.Bitmap.
+        /// </summary>
+        internal static System.Drawing.Bitmap bioz_input_mux1 {
+            get {
+                object obj = ResourceManager.GetObject("bioz_input_mux1", resourceCulture);
+                return ((System.Drawing.Bitmap)(obj));
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized resource of type System.Drawing.Bitmap.
+        /// </summary>
+        internal static System.Drawing.Bitmap bioz_input_muxcal1 {
+            get {
+                object obj = ResourceManager.GetObject("bioz_input_muxcal1", resourceCulture);
+                return ((System.Drawing.Bitmap)(obj));
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized resource of type System.Drawing.Bitmap.
+        /// </summary>
+        internal static System.Drawing.Bitmap bioz_input_muxcal2 {
+            get {
+                object obj = ResourceManager.GetObject("bioz_input_muxcal2", resourceCulture);
+                return ((System.Drawing.Bitmap)(obj));
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized resource of type System.Drawing.Bitmap.
+        /// </summary>
+        internal static System.Drawing.Bitmap bioz_input_muxlb1 {
+            get {
+                object obj = ResourceManager.GetObject("bioz_input_muxlb1", resourceCulture);
+                return ((System.Drawing.Bitmap)(obj));
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized resource of type System.Drawing.Bitmap.
+        /// </summary>
+        internal static System.Drawing.Bitmap bioz_input_muxlb2 {
+            get {
+                object obj = ResourceManager.GetObject("bioz_input_muxlb2", resourceCulture);
+                return ((System.Drawing.Bitmap)(obj));
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized resource of type System.Drawing.Bitmap.
+        /// </summary>
+        internal static System.Drawing.Bitmap bioz_input_muxloff1 {
+            get {
+                object obj = ResourceManager.GetObject("bioz_input_muxloff1", resourceCulture);
+                return ((System.Drawing.Bitmap)(obj));
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized resource of type System.Drawing.Bitmap.
+        /// </summary>
+        internal static System.Drawing.Bitmap bioz_input_muxloff2 {
+            get {
+                object obj = ResourceManager.GetObject("bioz_input_muxloff2", resourceCulture);
+                return ((System.Drawing.Bitmap)(obj));
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized resource of type System.Drawing.Bitmap.
+        /// </summary>
+        internal static System.Drawing.Bitmap bioz_input_muxlon {
+            get {
+                object obj = ResourceManager.GetObject("bioz_input_muxlon", resourceCulture);
+                return ((System.Drawing.Bitmap)(obj));
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized resource of type System.Drawing.Bitmap.
+        /// </summary>
+        internal static System.Drawing.Bitmap bioz_input_muxsw1 {
+            get {
+                object obj = ResourceManager.GetObject("bioz_input_muxsw1", resourceCulture);
+                return ((System.Drawing.Bitmap)(obj));
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized resource of type System.Drawing.Bitmap.
+        /// </summary>
+        internal static System.Drawing.Bitmap bioz_input_muxsw2 {
+            get {
+                object obj = ResourceManager.GetObject("bioz_input_muxsw2", resourceCulture);
+                return ((System.Drawing.Bitmap)(obj));
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized resource of type System.Drawing.Bitmap.
+        /// </summary>
+        internal static System.Drawing.Bitmap bioz_load {
+            get {
+                object obj = ResourceManager.GetObject("bioz_load", resourceCulture);
+                return ((System.Drawing.Bitmap)(obj));
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized resource of type System.Drawing.Bitmap.
+        /// </summary>
+        internal static System.Drawing.Bitmap bioz_load_cal1 {
+            get {
+                object obj = ResourceManager.GetObject("bioz_load_cal1", resourceCulture);
+                return ((System.Drawing.Bitmap)(obj));
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized resource of type System.Drawing.Bitmap.
+        /// </summary>
+        internal static System.Drawing.Bitmap bioz_load_cal2 {
+            get {
+                object obj = ResourceManager.GetObject("bioz_load_cal2", resourceCulture);
+                return ((System.Drawing.Bitmap)(obj));
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized resource of type System.Drawing.Bitmap.
+        /// </summary>
+        internal static System.Drawing.Bitmap bioz_load_lb1 {
+            get {
+                object obj = ResourceManager.GetObject("bioz_load_lb1", resourceCulture);
+                return ((System.Drawing.Bitmap)(obj));
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized resource of type System.Drawing.Bitmap.
+        /// </summary>
+        internal static System.Drawing.Bitmap bioz_load_lb2 {
+            get {
+                object obj = ResourceManager.GetObject("bioz_load_lb2", resourceCulture);
+                return ((System.Drawing.Bitmap)(obj));
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized resource of type System.Drawing.Bitmap.
+        /// </summary>
+        internal static System.Drawing.Bitmap bioz_load_leadon {
+            get {
+                object obj = ResourceManager.GetObject("bioz_load_leadon", resourceCulture);
+                return ((System.Drawing.Bitmap)(obj));
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized resource of type System.Drawing.Bitmap.
+        /// </summary>
+        internal static System.Drawing.Bitmap bioz_load_resload {
+            get {
+                object obj = ResourceManager.GetObject("bioz_load_resload", resourceCulture);
+                return ((System.Drawing.Bitmap)(obj));
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized resource of type System.Drawing.Bitmap.
+        /// </summary>
+        internal static System.Drawing.Bitmap bioz_load_sw1 {
+            get {
+                object obj = ResourceManager.GetObject("bioz_load_sw1", resourceCulture);
+                return ((System.Drawing.Bitmap)(obj));
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized resource of type System.Drawing.Bitmap.
+        /// </summary>
+        internal static System.Drawing.Bitmap bioz_load_sw2 {
+            get {
+                object obj = ResourceManager.GetObject("bioz_load_sw2", resourceCulture);
+                return ((System.Drawing.Bitmap)(obj));
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized resource of type System.Drawing.Bitmap.
+        /// </summary>
+        internal static System.Drawing.Bitmap bioz_load1 {
+            get {
+                object obj = ResourceManager.GetObject("bioz_load1", resourceCulture);
+                return ((System.Drawing.Bitmap)(obj));
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized resource of type System.Drawing.Bitmap.
+        /// </summary>
+        internal static System.Drawing.Bitmap bioz_load2 {
+            get {
+                object obj = ResourceManager.GetObject("bioz_load2", resourceCulture);
+                return ((System.Drawing.Bitmap)(obj));
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized resource of type System.Drawing.Bitmap.
+        /// </summary>
+        internal static System.Drawing.Bitmap bioz_loadloff1 {
+            get {
+                object obj = ResourceManager.GetObject("bioz_loadloff1", resourceCulture);
+                return ((System.Drawing.Bitmap)(obj));
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized resource of type System.Drawing.Bitmap.
+        /// </summary>
+        internal static System.Drawing.Bitmap bioz_loadloff2 {
+            get {
+                object obj = ResourceManager.GetObject("bioz_loadloff2", resourceCulture);
+                return ((System.Drawing.Bitmap)(obj));
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized resource of type System.Drawing.Bitmap.
+        /// </summary>
+        internal static System.Drawing.Bitmap bioz_loadrz {
+            get {
+                object obj = ResourceManager.GetObject("bioz_loadrz", resourceCulture);
+                return ((System.Drawing.Bitmap)(obj));
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized resource of type System.Drawing.Bitmap.
+        /// </summary>
+        internal static System.Drawing.Bitmap ecg_channel_block {
+            get {
+                object obj = ResourceManager.GetObject("ecg_channel_block", resourceCulture);
+                return ((System.Drawing.Bitmap)(obj));
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized resource of type System.Drawing.Bitmap.
+        /// </summary>
+        internal static System.Drawing.Bitmap ecg_lead_config {
+            get {
+                object obj = ResourceManager.GetObject("ecg_lead_config", resourceCulture);
+                return ((System.Drawing.Bitmap)(obj));
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized resource of type System.Drawing.Bitmap.
+        /// </summary>
+        internal static System.Drawing.Bitmap ecg_lead_config_closed_swOnly {
+            get {
+                object obj = ResourceManager.GetObject("ecg_lead_config_closed_swOnly", resourceCulture);
+                return ((System.Drawing.Bitmap)(obj));
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized resource of type System.Drawing.Bitmap.
+        /// </summary>
+        internal static System.Drawing.Bitmap ecg_lead_config1 {
+            get {
+                object obj = ResourceManager.GetObject("ecg_lead_config1", resourceCulture);
+                return ((System.Drawing.Bitmap)(obj));
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized resource of type System.Drawing.Bitmap.
+        /// </summary>
+        internal static System.Drawing.Bitmap open {
+            get {
+                object obj = ResourceManager.GetObject("open", resourceCulture);
+                return ((System.Drawing.Bitmap)(obj));
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized resource of type System.Drawing.Bitmap.
+        /// </summary>
+        internal static System.Drawing.Bitmap pace_block_diagrams {
+            get {
+                object obj = ResourceManager.GetObject("pace_block_diagrams", resourceCulture);
+                return ((System.Drawing.Bitmap)(obj));
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized resource of type System.Drawing.Bitmap.
+        /// </summary>
+        internal static System.Drawing.Bitmap pace_falling {
+            get {
+                object obj = ResourceManager.GetObject("pace_falling", resourceCulture);
+                return ((System.Drawing.Bitmap)(obj));
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized resource of type System.Drawing.Bitmap.
+        /// </summary>
+        internal static System.Drawing.Bitmap pace_rising {
+            get {
+                object obj = ResourceManager.GetObject("pace_rising", resourceCulture);
+                return ((System.Drawing.Bitmap)(obj));
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized resource of type System.Drawing.Bitmap.
+        /// </summary>
+        internal static System.Drawing.Bitmap sw1 {
+            get {
+                object obj = ResourceManager.GetObject("sw1", resourceCulture);
+                return ((System.Drawing.Bitmap)(obj));
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized resource of type System.Drawing.Bitmap.
+        /// </summary>
+        internal static System.Drawing.Bitmap sw10 {
+            get {
+                object obj = ResourceManager.GetObject("sw10", resourceCulture);
+                return ((System.Drawing.Bitmap)(obj));
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized resource of type System.Drawing.Bitmap.
+        /// </summary>
+        internal static System.Drawing.Bitmap sw11 {
+            get {
+                object obj = ResourceManager.GetObject("sw11", resourceCulture);
+                return ((System.Drawing.Bitmap)(obj));
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized resource of type System.Drawing.Bitmap.
+        /// </summary>
+        internal static System.Drawing.Bitmap sw12 {
+            get {
+                object obj = ResourceManager.GetObject("sw12", resourceCulture);
+                return ((System.Drawing.Bitmap)(obj));
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized resource of type System.Drawing.Bitmap.
+        /// </summary>
+        internal static System.Drawing.Bitmap sw13 {
+            get {
+                object obj = ResourceManager.GetObject("sw13", resourceCulture);
+                return ((System.Drawing.Bitmap)(obj));
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized resource of type System.Drawing.Bitmap.
+        /// </summary>
+        internal static System.Drawing.Bitmap sw14 {
+            get {
+                object obj = ResourceManager.GetObject("sw14", resourceCulture);
+                return ((System.Drawing.Bitmap)(obj));
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized resource of type System.Drawing.Bitmap.
+        /// </summary>
+        internal static System.Drawing.Bitmap sw1bmp {
+            get {
+                object obj = ResourceManager.GetObject("sw1bmp", resourceCulture);
+                return ((System.Drawing.Bitmap)(obj));
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized resource of type System.Drawing.Bitmap.
+        /// </summary>
+        internal static System.Drawing.Bitmap sw1rz {
+            get {
+                object obj = ResourceManager.GetObject("sw1rz", resourceCulture);
+                return ((System.Drawing.Bitmap)(obj));
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized resource of type System.Drawing.Bitmap.
+        /// </summary>
+        internal static System.Drawing.Bitmap sw2 {
+            get {
+                object obj = ResourceManager.GetObject("sw2", resourceCulture);
+                return ((System.Drawing.Bitmap)(obj));
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized resource of type System.Drawing.Bitmap.
+        /// </summary>
+        internal static System.Drawing.Bitmap sw3 {
+            get {
+                object obj = ResourceManager.GetObject("sw3", resourceCulture);
+                return ((System.Drawing.Bitmap)(obj));
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized resource of type System.Drawing.Bitmap.
+        /// </summary>
+        internal static System.Drawing.Bitmap sw4 {
+            get {
+                object obj = ResourceManager.GetObject("sw4", resourceCulture);
+                return ((System.Drawing.Bitmap)(obj));
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized resource of type System.Drawing.Bitmap.
+        /// </summary>
+        internal static System.Drawing.Bitmap sw5 {
+            get {
+                object obj = ResourceManager.GetObject("sw5", resourceCulture);
+                return ((System.Drawing.Bitmap)(obj));
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized resource of type System.Drawing.Bitmap.
+        /// </summary>
+        internal static System.Drawing.Bitmap sw6 {
+            get {
+                object obj = ResourceManager.GetObject("sw6", resourceCulture);
+                return ((System.Drawing.Bitmap)(obj));
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized resource of type System.Drawing.Bitmap.
+        /// </summary>
+        internal static System.Drawing.Bitmap sw7 {
+            get {
+                object obj = ResourceManager.GetObject("sw7", resourceCulture);
+                return ((System.Drawing.Bitmap)(obj));
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized resource of type System.Drawing.Bitmap.
+        /// </summary>
+        internal static System.Drawing.Bitmap sw8 {
+            get {
+                object obj = ResourceManager.GetObject("sw8", resourceCulture);
+                return ((System.Drawing.Bitmap)(obj));
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized resource of type System.Drawing.Bitmap.
+        /// </summary>
+        internal static System.Drawing.Bitmap sw9 {
+            get {
+                object obj = ResourceManager.GetObject("sw9", resourceCulture);
+                return ((System.Drawing.Bitmap)(obj));
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized resource of type System.Drawing.Bitmap.
+        /// </summary>
+        internal static System.Drawing.Bitmap system_block_diagram {
+            get {
+                object obj = ResourceManager.GetObject("system_block_diagram", resourceCulture);
+                return ((System.Drawing.Bitmap)(obj));
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized resource of type System.Drawing.Bitmap.
+        /// </summary>
+        internal static System.Drawing.Bitmap system_block_diagram_max30003 {
+            get {
+                object obj = ResourceManager.GetObject("system_block_diagram_max30003", resourceCulture);
+                return ((System.Drawing.Bitmap)(obj));
+            }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HspGuiSourceV301/HSPGui/Properties/Resources.resx	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,277 @@
+<?xml version="1.0" encoding="utf-8"?>
+<root>
+  <!-- 
+    Microsoft ResX Schema 
+    
+    Version 2.0
+    
+    The primary goals of this format is to allow a simple XML format 
+    that is mostly human readable. The generation and parsing of the 
+    various data types are done through the TypeConverter classes 
+    associated with the data types.
+    
+    Example:
+    
+    ... ado.net/XML headers & schema ...
+    <resheader name="resmimetype">text/microsoft-resx</resheader>
+    <resheader name="version">2.0</resheader>
+    <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+    <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+    <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
+    <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+    <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+        <value>[base64 mime encoded serialized .NET Framework object]</value>
+    </data>
+    <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+        <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
+        <comment>This is a comment</comment>
+    </data>
+                
+    There are any number of "resheader" rows that contain simple 
+    name/value pairs.
+    
+    Each data row contains a name, and value. The row also contains a 
+    type or mimetype. Type corresponds to a .NET class that support 
+    text/value conversion through the TypeConverter architecture. 
+    Classes that don't support this are serialized and stored with the 
+    mimetype set.
+    
+    The mimetype is used for serialized objects, and tells the 
+    ResXResourceReader how to depersist the object. This is currently not 
+    extensible. For a given mimetype the value must be set accordingly:
+    
+    Note - application/x-microsoft.net.object.binary.base64 is the format 
+    that the ResXResourceWriter will generate, however the reader can 
+    read any of the formats listed below.
+    
+    mimetype: application/x-microsoft.net.object.binary.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
+            : and then encoded with base64 encoding.
+    
+    mimetype: application/x-microsoft.net.object.soap.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+            : and then encoded with base64 encoding.
+
+    mimetype: application/x-microsoft.net.object.bytearray.base64
+    value   : The object must be serialized into a byte array 
+            : using a System.ComponentModel.TypeConverter
+            : and then encoded with base64 encoding.
+    -->
+  <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+    <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
+    <xsd:element name="root" msdata:IsDataSet="true">
+      <xsd:complexType>
+        <xsd:choice maxOccurs="unbounded">
+          <xsd:element name="metadata">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" />
+              </xsd:sequence>
+              <xsd:attribute name="name" use="required" type="xsd:string" />
+              <xsd:attribute name="type" type="xsd:string" />
+              <xsd:attribute name="mimetype" type="xsd:string" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="assembly">
+            <xsd:complexType>
+              <xsd:attribute name="alias" type="xsd:string" />
+              <xsd:attribute name="name" type="xsd:string" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="data">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+                <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
+              <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+              <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="resheader">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" />
+            </xsd:complexType>
+          </xsd:element>
+        </xsd:choice>
+      </xsd:complexType>
+    </xsd:element>
+  </xsd:schema>
+  <resheader name="resmimetype">
+    <value>text/microsoft-resx</value>
+  </resheader>
+  <resheader name="version">
+    <value>2.0</value>
+  </resheader>
+  <resheader name="reader">
+    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <resheader name="writer">
+    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <assembly alias="System.Windows.Forms" name="System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
+  <data name="system_block_diagram_max30003" type="System.Resources.ResXFileRef, System.Windows.Forms">
+    <value>..\resources\system_block_diagram_max30003.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
+  </data>
+  <data name="sw1" type="System.Resources.ResXFileRef, System.Windows.Forms">
+    <value>..\Resources\sw1.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
+  </data>
+  <data name="bioz_load_sw1" type="System.Resources.ResXFileRef, System.Windows.Forms">
+    <value>..\Resources\bioz_load_sw1.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
+  </data>
+  <data name="bioz_input_muxlb1" type="System.Resources.ResXFileRef, System.Windows.Forms">
+    <value>..\Resources\bioz_input_muxlb1.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
+  </data>
+  <data name="sw7" type="System.Resources.ResXFileRef, System.Windows.Forms">
+    <value>..\Resources\sw7.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
+  </data>
+  <data name="bioz_input_muxlon" type="System.Resources.ResXFileRef, System.Windows.Forms">
+    <value>..\Resources\bioz_input_muxlon.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
+  </data>
+  <data name="sw10" type="System.Resources.ResXFileRef, System.Windows.Forms">
+    <value>..\Resources\sw10.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
+  </data>
+  <data name="bioz_load_lb2" type="System.Resources.ResXFileRef, System.Windows.Forms">
+    <value>..\Resources\bioz_load_lb2.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
+  </data>
+  <data name="sw6" type="System.Resources.ResXFileRef, System.Windows.Forms">
+    <value>..\Resources\sw6.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
+  </data>
+  <data name="sw11" type="System.Resources.ResXFileRef, System.Windows.Forms">
+    <value>..\Resources\sw11.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
+  </data>
+  <data name="bioz_load_cal1" type="System.Resources.ResXFileRef, System.Windows.Forms">
+    <value>..\Resources\bioz_load_cal1.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
+  </data>
+  <data name="sw1rz" type="System.Resources.ResXFileRef, System.Windows.Forms">
+    <value>..\Resources\sw1rz.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
+  </data>
+  <data name="pace_block_diagrams" type="System.Resources.ResXFileRef, System.Windows.Forms">
+    <value>..\Resources\pace_block_diagrams.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
+  </data>
+  <data name="bioz_input_mux" type="System.Resources.ResXFileRef, System.Windows.Forms">
+    <value>..\Resources\bioz_input_mux.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
+  </data>
+  <data name="bioz_input_muxsw1" type="System.Resources.ResXFileRef, System.Windows.Forms">
+    <value>..\Resources\bioz_input_muxsw1.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
+  </data>
+  <data name="bioz_input_muxloff2" type="System.Resources.ResXFileRef, System.Windows.Forms">
+    <value>..\Resources\bioz_input_muxloff2.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
+  </data>
+  <data name="bio_impedance_block" type="System.Resources.ResXFileRef, System.Windows.Forms">
+    <value>..\Resources\bio-impedance_block.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
+  </data>
+  <data name="bioz_load_resload" type="System.Resources.ResXFileRef, System.Windows.Forms">
+    <value>..\Resources\bioz_load_resload.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
+  </data>
+  <data name="bioz_load_sw2" type="System.Resources.ResXFileRef, System.Windows.Forms">
+    <value>..\Resources\bioz_load_sw2.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
+  </data>
+  <data name="bioz_load1" type="System.Resources.ResXFileRef, System.Windows.Forms">
+    <value>..\Resources\bioz_load.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
+  </data>
+  <data name="bioz_load_leadon" type="System.Resources.ResXFileRef, System.Windows.Forms">
+    <value>..\Resources\bioz_load_leadon.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
+  </data>
+  <data name="pace_falling" type="System.Resources.ResXFileRef, System.Windows.Forms">
+    <value>..\Resources\pace_falling.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
+  </data>
+  <data name="sw5" type="System.Resources.ResXFileRef, System.Windows.Forms">
+    <value>..\Resources\sw5.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
+  </data>
+  <data name="bioz_input_mux1" type="System.Resources.ResXFileRef, System.Windows.Forms">
+    <value>..\Resources\bioz_input_mux1.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
+  </data>
+  <data name="bioz_loadloff1" type="System.Resources.ResXFileRef, System.Windows.Forms">
+    <value>..\Resources\bioz_loadloff1.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
+  </data>
+  <data name="ecg_channel_block" type="System.Resources.ResXFileRef, System.Windows.Forms">
+    <value>..\resources\ecg_channel_block.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
+  </data>
+  <data name="ecg_lead_config1" type="System.Resources.ResXFileRef, System.Windows.Forms">
+    <value>..\Resources\ecg_lead_config1.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
+  </data>
+  <data name="ecg_lead_config" type="System.Resources.ResXFileRef, System.Windows.Forms">
+    <value>..\Resources\ecg_lead_config.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
+  </data>
+  <data name="pace_rising" type="System.Resources.ResXFileRef, System.Windows.Forms">
+    <value>..\Resources\pace_rising.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
+  </data>
+  <data name="sw4" type="System.Resources.ResXFileRef, System.Windows.Forms">
+    <value>..\Resources\sw4.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
+  </data>
+  <data name="sw12" type="System.Resources.ResXFileRef, System.Windows.Forms">
+    <value>..\Resources\sw12.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
+  </data>
+  <data name="bioz_loadloff2" type="System.Resources.ResXFileRef, System.Windows.Forms">
+    <value>..\Resources\bioz_loadloff2.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
+  </data>
+  <data name="sw9" type="System.Resources.ResXFileRef, System.Windows.Forms">
+    <value>..\Resources\sw9.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
+  </data>
+  <data name="ecg_lead_config_closed_swOnly" type="System.Resources.ResXFileRef, System.Windows.Forms">
+    <value>..\Resources\ecg_lead_config_closed_swOnly.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
+  </data>
+  <data name="bioz_input_muxlb2" type="System.Resources.ResXFileRef, System.Windows.Forms">
+    <value>..\Resources\bioz_input_muxlb2.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
+  </data>
+  <data name="sw13" type="System.Resources.ResXFileRef, System.Windows.Forms">
+    <value>..\Resources\sw13.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
+  </data>
+  <data name="bioz_load_cal2" type="System.Resources.ResXFileRef, System.Windows.Forms">
+    <value>..\Resources\bioz_load_cal2.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
+  </data>
+  <data name="bioz_input_muxsw2" type="System.Resources.ResXFileRef, System.Windows.Forms">
+    <value>..\Resources\bioz_input_muxsw2.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
+  </data>
+  <data name="bioz_load_lb1" type="System.Resources.ResXFileRef, System.Windows.Forms">
+    <value>..\Resources\bioz_load_lb1.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
+  </data>
+  <data name="bioz_input_muxloff1" type="System.Resources.ResXFileRef, System.Windows.Forms">
+    <value>..\Resources\bioz_input_muxloff1.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
+  </data>
+  <data name="sw3" type="System.Resources.ResXFileRef, System.Windows.Forms">
+    <value>..\Resources\sw3.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
+  </data>
+  <data name="bioz_input_muxcal1" type="System.Resources.ResXFileRef, System.Windows.Forms">
+    <value>..\Resources\bioz_input_muxcal1.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
+  </data>
+  <data name="system_block_diagram" type="System.Resources.ResXFileRef, System.Windows.Forms">
+    <value>..\Resources\system_block_diagram.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
+  </data>
+  <data name="sw14" type="System.Resources.ResXFileRef, System.Windows.Forms">
+    <value>..\Resources\sw14.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
+  </data>
+  <data name="bioz_load2" type="System.Resources.ResXFileRef, System.Windows.Forms">
+    <value>..\Resources\bioz_load.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
+  </data>
+  <data name="bioz_load" type="System.Resources.ResXFileRef, System.Windows.Forms">
+    <value>..\Resources\bioz_load.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
+  </data>
+  <data name="sw2" type="System.Resources.ResXFileRef, System.Windows.Forms">
+    <value>..\Resources\sw2.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
+  </data>
+  <data name="open" type="System.Resources.ResXFileRef, System.Windows.Forms">
+    <value>..\Resources\open.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
+  </data>
+  <data name="bioz_input_muxcal2" type="System.Resources.ResXFileRef, System.Windows.Forms">
+    <value>..\Resources\bioz_input_muxcal2.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
+  </data>
+  <data name="sw8" type="System.Resources.ResXFileRef, System.Windows.Forms">
+    <value>..\Resources\sw8.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
+  </data>
+  <data name="sw1bmp" type="System.Resources.ResXFileRef, System.Windows.Forms">
+    <value>..\Resources\sw1bmp.bmp;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
+  </data>
+  <data name="bioz_loadrz" type="System.Resources.ResXFileRef, System.Windows.Forms">
+    <value>..\Resources\bioz_loadrz.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
+  </data>
+</root>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HspGuiSourceV301/HSPGui/Properties/Settings.Designer.cs	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,50 @@
+//------------------------------------------------------------------------------
+// <auto-generated>
+//     This code was generated by a tool.
+//     Runtime Version:4.0.30319.42000
+//
+//     Changes to this file may cause incorrect behavior and will be lost if
+//     the code is regenerated.
+// </auto-generated>
+//------------------------------------------------------------------------------
+
+namespace HealthSensorPlatform.Properties {
+    
+    
+    [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+    [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "14.0.0.0")]
+    internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
+        
+        private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
+        
+        public static Settings Default {
+            get {
+                return defaultInstance;
+            }
+        }
+        
+        [global::System.Configuration.UserScopedSettingAttribute()]
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+        [global::System.Configuration.DefaultSettingValueAttribute("False")]
+        public bool DisableSplash {
+            get {
+                return ((bool)(this["DisableSplash"]));
+            }
+            set {
+                this["DisableSplash"] = value;
+            }
+        }
+        
+        [global::System.Configuration.UserScopedSettingAttribute()]
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+        [global::System.Configuration.DefaultSettingValueAttribute("")]
+        public string ComPort {
+            get {
+                return ((string)(this["ComPort"]));
+            }
+            set {
+                this["ComPort"] = value;
+            }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HspGuiSourceV301/HSPGui/RegisterField.cs	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,154 @@
+/*******************************************************************************
+* Copyright (C) 2016 Maxim Integrated Products, Inc., All rights Reserved.
+* 
+* This software is protected by copyright laws of the United States and
+* of foreign countries. This material may also be protected by patent laws
+* and technology transfer regulations of the United States and of foreign
+* countries. This software is furnished under a license agreement and/or a
+* nondisclosure agreement and may only be used or reproduced in accordance
+* with the terms of those agreements. Dissemination of this information to
+* any party or parties not specified in the license agreement and/or
+* nondisclosure agreement is expressly prohibited.
+*
+* The above copyright notice and this permission notice shall be included
+* in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+* OTHER DEALINGS IN THE SOFTWARE.
+*
+* Except as contained in this notice, the name of Maxim Integrated
+* Products, Inc. shall not be used except as stated in the Maxim Integrated
+* Products, Inc. Branding Policy.
+*
+* The mere transfer of this software does not imply any licenses
+* of trade secrets, proprietary technology, copyrights, patents,
+* trademarks, maskwork rights, or any other form of intellectual
+* property whatsoever. Maxim Integrated Products, Inc. retains all
+* ownership rights.
+*******************************************************************************
+*/
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Windows.Forms;
+using RPCSupport;
+using RPCSupport.Devices;
+
+namespace HealthSensorPlatform
+{
+    class RegisterField : IRegisterFieldView
+    {
+        /// <summary>
+        /// Device which is connected to this RegisterField
+        /// </summary>
+        public IRegisterDevice Device;
+        /// <summary>
+        /// Bit name in data sheet
+        /// </summary>
+        public string Name;
+        /// <summary>
+        /// Register number
+        /// </summary>
+        public int Register;
+        /// <summary>
+        /// LSB Bit index number of bit field
+        /// </summary>
+        public int Index; 
+        /// <summary>
+        /// Length of bit field
+        /// </summary>
+        public int Width;
+        /// <summary>
+        /// Description array of field settings
+        /// </summary>
+        public string[] Descriptions;
+        /// <summary>
+        /// Control associated with bit field
+        /// </summary>
+        Control control;
+        public Control Control
+        {
+            get
+            {
+                return control;
+            }
+            set
+            {
+                control = value;
+                if (control.GetType() == typeof(MaximStyle.MaximComboBox))
+                {
+                    MaximStyle.MaximComboBox cb = (MaximStyle.MaximComboBox)control;
+                    cb.Items.Clear();
+                    foreach (string s in Descriptions)
+                    {
+                        cb.Items.Add(s);
+                    }
+                }
+            }
+        }
+
+        /// <summary>
+        /// Label (Text) associated with register field
+        /// </summary>
+        Label label;
+        public Label Label
+        { 
+            set
+            {
+                LabelDescription = value.Text;
+                label = value;
+            }
+
+            get
+            {
+                return label;
+            }
+        }
+
+        /// <summary>
+        /// Text value of label
+        /// </summary>
+        public string LabelDescription;
+
+        /// <summary>
+        /// Automatically update register field 
+        /// </summary>
+        public bool AutoUpdate = true;
+
+        /// <summary>
+        /// Read register field value
+        /// </summary>
+        /// <returns></returns>
+        public int ReadField()
+        {
+            int registerData;
+
+            registerData = Device.ReadReg((byte)Register);
+
+            return (registerData >> Index) & ((1 << Width) - 1);
+        }
+        
+        /// <summary>
+        /// Write register field value
+        /// </summary>
+        /// <param name="data">value to write to field</param>
+        public void WriteField(int data)
+        {
+            int registerData;
+
+            registerData = Device.ReadReg((byte)Register);
+            registerData &= ~(((1 << Width) - 1) << Index); // Mask and Clear Bits
+            registerData |= data << Index; // Set Bits 
+
+            Device.WriteReg((byte)Register, registerData);
+        }
+
+    }
+}
Binary file HspGuiSourceV301/HSPGui/Resources/bio-impedance_block.png has changed
Binary file HspGuiSourceV301/HSPGui/Resources/bioz_input_mux.png has changed
Binary file HspGuiSourceV301/HSPGui/Resources/bioz_input_mux1.png has changed
Binary file HspGuiSourceV301/HSPGui/Resources/bioz_input_muxcal1.png has changed
Binary file HspGuiSourceV301/HSPGui/Resources/bioz_input_muxcal2.png has changed
Binary file HspGuiSourceV301/HSPGui/Resources/bioz_input_muxlb1.png has changed
Binary file HspGuiSourceV301/HSPGui/Resources/bioz_input_muxlb2.png has changed
Binary file HspGuiSourceV301/HSPGui/Resources/bioz_input_muxloff1.png has changed
Binary file HspGuiSourceV301/HSPGui/Resources/bioz_input_muxloff2.png has changed
Binary file HspGuiSourceV301/HSPGui/Resources/bioz_input_muxlon.png has changed
Binary file HspGuiSourceV301/HSPGui/Resources/bioz_input_muxsw1.png has changed
Binary file HspGuiSourceV301/HSPGui/Resources/bioz_input_muxsw2.png has changed
Binary file HspGuiSourceV301/HSPGui/Resources/bioz_load.png has changed
Binary file HspGuiSourceV301/HSPGui/Resources/bioz_loadOLD.png has changed
Binary file HspGuiSourceV301/HSPGui/Resources/bioz_load_cal1.png has changed
Binary file HspGuiSourceV301/HSPGui/Resources/bioz_load_cal2.png has changed
Binary file HspGuiSourceV301/HSPGui/Resources/bioz_load_lb1.png has changed
Binary file HspGuiSourceV301/HSPGui/Resources/bioz_load_lb2.png has changed
Binary file HspGuiSourceV301/HSPGui/Resources/bioz_load_leadon.png has changed
Binary file HspGuiSourceV301/HSPGui/Resources/bioz_load_resload.png has changed
Binary file HspGuiSourceV301/HSPGui/Resources/bioz_load_sw1.png has changed
Binary file HspGuiSourceV301/HSPGui/Resources/bioz_load_sw2.png has changed
Binary file HspGuiSourceV301/HSPGui/Resources/bioz_loadloff1.png has changed
Binary file HspGuiSourceV301/HSPGui/Resources/bioz_loadloff2.png has changed
Binary file HspGuiSourceV301/HSPGui/Resources/bioz_loadrz.png has changed
Binary file HspGuiSourceV301/HSPGui/Resources/ecg_channel_block.png has changed
Binary file HspGuiSourceV301/HSPGui/Resources/ecg_lead_config.png has changed
Binary file HspGuiSourceV301/HSPGui/Resources/ecg_lead_config1.png has changed
Binary file HspGuiSourceV301/HSPGui/Resources/ecg_lead_config_closed_swOnly.png has changed
Binary file HspGuiSourceV301/HSPGui/Resources/open.png has changed
Binary file HspGuiSourceV301/HSPGui/Resources/pace_block_diagrams.png has changed
Binary file HspGuiSourceV301/HSPGui/Resources/pace_falling.png has changed
Binary file HspGuiSourceV301/HSPGui/Resources/pace_rising.png has changed
Binary file HspGuiSourceV301/HSPGui/Resources/sw1.png has changed
Binary file HspGuiSourceV301/HSPGui/Resources/sw10.png has changed
Binary file HspGuiSourceV301/HSPGui/Resources/sw11.png has changed
Binary file HspGuiSourceV301/HSPGui/Resources/sw12.png has changed
Binary file HspGuiSourceV301/HSPGui/Resources/sw13.png has changed
Binary file HspGuiSourceV301/HSPGui/Resources/sw14.png has changed
Binary file HspGuiSourceV301/HSPGui/Resources/sw1bmp.bmp has changed
Binary file HspGuiSourceV301/HSPGui/Resources/sw1rz.png has changed
Binary file HspGuiSourceV301/HSPGui/Resources/sw2.png has changed
Binary file HspGuiSourceV301/HSPGui/Resources/sw3.png has changed
Binary file HspGuiSourceV301/HSPGui/Resources/sw4.png has changed
Binary file HspGuiSourceV301/HSPGui/Resources/sw5.png has changed
Binary file HspGuiSourceV301/HSPGui/Resources/sw6.png has changed
Binary file HspGuiSourceV301/HSPGui/Resources/sw7.png has changed
Binary file HspGuiSourceV301/HSPGui/Resources/sw8.png has changed
Binary file HspGuiSourceV301/HSPGui/Resources/sw9.png has changed
Binary file HspGuiSourceV301/HSPGui/Resources/system_block_diagram.png has changed
Binary file HspGuiSourceV301/HSPGui/Resources/system_block_diagram_max30003.png has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HspGuiSourceV301/HSPGui/RpcClientExample.csproj	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,103 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <PropertyGroup>
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <Platform Condition=" '$(Platform)' == '' ">x86</Platform>
+    <ProductVersion>8.0.30703</ProductVersion>
+    <SchemaVersion>2.0</SchemaVersion>
+    <ProjectGuid>{CEF8731E-362F-407C-86A7-F65ACE2A1ACB}</ProjectGuid>
+    <OutputType>WinExe</OutputType>
+    <AppDesignerFolder>Properties</AppDesignerFolder>
+    <RootNamespace>RpcClientExample</RootNamespace>
+    <AssemblyName>SimpleHID</AssemblyName>
+    <TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
+    <TargetFrameworkProfile>
+    </TargetFrameworkProfile>
+    <FileAlignment>512</FileAlignment>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
+    <PlatformTarget>x86</PlatformTarget>
+    <DebugSymbols>true</DebugSymbols>
+    <DebugType>full</DebugType>
+    <Optimize>false</Optimize>
+    <OutputPath>bin\Debug\</OutputPath>
+    <DefineConstants>DEBUG;TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
+    <PlatformTarget>x86</PlatformTarget>
+    <DebugType>pdbonly</DebugType>
+    <Optimize>true</Optimize>
+    <OutputPath>bin\Release\</OutputPath>
+    <DefineConstants>TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+  </PropertyGroup>
+  <ItemGroup>
+    <Reference Include="MaximStyle">
+      <HintPath>.\MaximStyle.dll</HintPath>
+    </Reference>
+    <Reference Include="System" />
+    <Reference Include="System.Core" />
+    <Reference Include="System.Xml.Linq" />
+    <Reference Include="System.Data.DataSetExtensions" />
+    <Reference Include="Microsoft.CSharp" />
+    <Reference Include="System.Data" />
+    <Reference Include="System.Deployment" />
+    <Reference Include="System.Drawing" />
+    <Reference Include="System.Windows.Forms" />
+    <Reference Include="System.Xml" />
+  </ItemGroup>
+  <ItemGroup>
+    <Compile Include="Form1.cs">
+      <SubType>Form</SubType>
+    </Compile>
+    <Compile Include="Form1.Designer.cs">
+      <DependentUpon>Form1.cs</DependentUpon>
+    </Compile>
+    <Compile Include="Program.cs" />
+    <Compile Include="Properties\AssemblyInfo.cs" />
+    <EmbeddedResource Include="Form1.resx">
+      <DependentUpon>Form1.cs</DependentUpon>
+    </EmbeddedResource>
+    <EmbeddedResource Include="Properties\Resources.resx">
+      <Generator>ResXFileCodeGenerator</Generator>
+      <LastGenOutput>Resources.Designer.cs</LastGenOutput>
+      <SubType>Designer</SubType>
+    </EmbeddedResource>
+    <Compile Include="Properties\Resources.Designer.cs">
+      <AutoGen>True</AutoGen>
+      <DependentUpon>Resources.resx</DependentUpon>
+      <DesignTime>True</DesignTime>
+    </Compile>
+    <None Include="app.config" />
+    <None Include="Properties\Settings.settings">
+      <Generator>SettingsSingleFileGenerator</Generator>
+      <LastGenOutput>Settings.Designer.cs</LastGenOutput>
+    </None>
+    <Compile Include="Properties\Settings.Designer.cs">
+      <AutoGen>True</AutoGen>
+      <DependentUpon>Settings.settings</DependentUpon>
+      <DesignTimeSharedInput>True</DesignTimeSharedInput>
+    </Compile>
+  </ItemGroup>
+  <ItemGroup>
+    <ProjectReference Include="..\GuiDLLs\MAX30101\HSPDevices.csproj">
+      <Project>{B068077E-189F-4CEA-89F7-9E91EF39EC5D}</Project>
+      <Name>HSPDevices</Name>
+    </ProjectReference>
+    <ProjectReference Include="..\GuiDLLs\RPCSupport\RPCSupport.csproj">
+      <Project>{170A27F5-0680-485D-8B90-EA736719016E}</Project>
+      <Name>RPCSupport</Name>
+    </ProjectReference>
+  </ItemGroup>
+  <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+  <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 
+       Other similar extension points exist, see Microsoft.Common.targets.
+  <Target Name="BeforeBuild">
+  </Target>
+  <Target Name="AfterBuild">
+  </Target>
+  -->
+</Project>
\ No newline at end of file
Binary file HspGuiSourceV301/HSPGui/SKA.dll has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HspGuiSourceV301/HSPGui/SimpleHID.sln	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,42 @@
+
+Microsoft Visual Studio Solution File, Format Version 11.00
+# Visual Studio 2010
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SimpleHID", "SimpleHID.csproj", "{CEF8731E-362F-407C-86A7-F65ACE2A1ACB}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HSPDevices", "..\..\..\..\..\..\..\HspGuiApp\GuiDLLs\MAX30101\HSPDevices.csproj", "{B068077E-189F-4CEA-89F7-9E91EF39EC5D}"
+EndProject
+Global
+	GlobalSection(SolutionConfigurationPlatforms) = preSolution
+		Debug|Any CPU = Debug|Any CPU
+		Debug|Mixed Platforms = Debug|Mixed Platforms
+		Debug|x86 = Debug|x86
+		Release|Any CPU = Release|Any CPU
+		Release|Mixed Platforms = Release|Mixed Platforms
+		Release|x86 = Release|x86
+	EndGlobalSection
+	GlobalSection(ProjectConfigurationPlatforms) = postSolution
+		{CEF8731E-362F-407C-86A7-F65ACE2A1ACB}.Debug|Any CPU.ActiveCfg = Debug|x86
+		{CEF8731E-362F-407C-86A7-F65ACE2A1ACB}.Debug|Mixed Platforms.ActiveCfg = Debug|x86
+		{CEF8731E-362F-407C-86A7-F65ACE2A1ACB}.Debug|Mixed Platforms.Build.0 = Debug|x86
+		{CEF8731E-362F-407C-86A7-F65ACE2A1ACB}.Debug|x86.ActiveCfg = Debug|x86
+		{CEF8731E-362F-407C-86A7-F65ACE2A1ACB}.Debug|x86.Build.0 = Debug|x86
+		{CEF8731E-362F-407C-86A7-F65ACE2A1ACB}.Release|Any CPU.ActiveCfg = Release|x86
+		{CEF8731E-362F-407C-86A7-F65ACE2A1ACB}.Release|Mixed Platforms.ActiveCfg = Release|x86
+		{CEF8731E-362F-407C-86A7-F65ACE2A1ACB}.Release|Mixed Platforms.Build.0 = Release|x86
+		{CEF8731E-362F-407C-86A7-F65ACE2A1ACB}.Release|x86.ActiveCfg = Release|x86
+		{CEF8731E-362F-407C-86A7-F65ACE2A1ACB}.Release|x86.Build.0 = Release|x86
+		{B068077E-189F-4CEA-89F7-9E91EF39EC5D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{B068077E-189F-4CEA-89F7-9E91EF39EC5D}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{B068077E-189F-4CEA-89F7-9E91EF39EC5D}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
+		{B068077E-189F-4CEA-89F7-9E91EF39EC5D}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
+		{B068077E-189F-4CEA-89F7-9E91EF39EC5D}.Debug|x86.ActiveCfg = Debug|Any CPU
+		{B068077E-189F-4CEA-89F7-9E91EF39EC5D}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{B068077E-189F-4CEA-89F7-9E91EF39EC5D}.Release|Any CPU.Build.0 = Release|Any CPU
+		{B068077E-189F-4CEA-89F7-9E91EF39EC5D}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
+		{B068077E-189F-4CEA-89F7-9E91EF39EC5D}.Release|Mixed Platforms.Build.0 = Release|Any CPU
+		{B068077E-189F-4CEA-89F7-9E91EF39EC5D}.Release|x86.ActiveCfg = Release|Any CPU
+	EndGlobalSection
+	GlobalSection(SolutionProperties) = preSolution
+		HideSolutionNode = FALSE
+	EndGlobalSection
+EndGlobal
Binary file HspGuiSourceV301/HSPGui/SimpleHID.suo has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HspGuiSourceV301/HSPGui/SplashScreen.Designer.cs	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,90 @@
+namespace HealthSensorPlatform
+{
+    partial class SplashScreen
+    {
+        /// <summary>
+        /// Required designer variable.
+        /// </summary>
+        private System.ComponentModel.IContainer components = null;
+
+        /// <summary>
+        /// Clean up any resources being used.
+        /// </summary>
+        /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
+        protected override void Dispose(bool disposing)
+        {
+            if (disposing && (components != null))
+            {
+                components.Dispose();
+            }
+            base.Dispose(disposing);
+        }
+
+        #region Windows Form Designer generated code
+
+        /// <summary>
+        /// Required method for Designer support - do not modify
+        /// the contents of this method with the code editor.
+        /// </summary>
+        private void InitializeComponent()
+        {
+            System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(SplashScreen));
+            this.maximSplashScreen1 = new MaximStyle.MaximSplashScreen();
+            this.btn_OK = new MaximStyle.MaximButton();
+            this.SuspendLayout();
+            // 
+            // maximSplashScreen1
+            // 
+            this.maximSplashScreen1.ApplicationIconImage = null;
+            this.maximSplashScreen1.ApplicationName = "RpcClientExample";
+            this.maximSplashScreen1.BackColor = System.Drawing.Color.White;
+            this.maximSplashScreen1.Checked = false;
+            this.maximSplashScreen1.CopyrightString = "© June 2013 Maxim Integrated Products, Inc.";
+            this.maximSplashScreen1.Font = new System.Drawing.Font("Arial", 11F);
+            this.maximSplashScreen1.Location = new System.Drawing.Point(0, 0);
+            this.maximSplashScreen1.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5);
+            this.maximSplashScreen1.Name = "maximSplashScreen1";
+            this.maximSplashScreen1.NonMaximCopyrightString = "";
+            this.maximSplashScreen1.Size = new System.Drawing.Size(400, 320);
+            this.maximSplashScreen1.TabIndex = 0;
+            this.maximSplashScreen1.VersionString = ", Version X.X";
+            // 
+            // btn_OK
+            // 
+            this.btn_OK.Location = new System.Drawing.Point(296, 272);
+            this.btn_OK.Name = "btn_OK";
+            this.btn_OK.Size = new System.Drawing.Size(75, 23);
+            this.btn_OK.TabIndex = 1;
+            this.btn_OK.Text = "OK";
+            this.btn_OK.UseVisualStyleBackColor = true;
+            this.btn_OK.Visible = false;
+            this.btn_OK.Click += new System.EventHandler(this.btn_OK_Click);
+            // 
+            // SplashScreen
+            // 
+            this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 16F);
+            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+            this.BackColor = System.Drawing.Color.White;
+            this.BackgroundImageLayout = System.Windows.Forms.ImageLayout.None;
+            this.ClientSize = new System.Drawing.Size(400, 320);
+            this.Controls.Add(this.btn_OK);
+            this.Controls.Add(this.maximSplashScreen1);
+            this.Font = new System.Drawing.Font("Arial Narrow", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+            this.ForeColor = System.Drawing.Color.Black;
+            this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None;
+            this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon")));
+            this.Margin = new System.Windows.Forms.Padding(3, 4, 3, 4);
+            this.Name = "SplashScreen";
+            this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
+            this.Text = "SplashScreen";
+            this.Load += new System.EventHandler(this.SplashScreen_Load);
+            this.ResumeLayout(false);
+
+        }
+
+        #endregion
+
+        internal MaximStyle.MaximSplashScreen maximSplashScreen1;
+        internal MaximStyle.MaximButton btn_OK;
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HspGuiSourceV301/HSPGui/SplashScreen.cs	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,138 @@
+/*******************************************************************************
+* Copyright (C) 2016 Maxim Integrated Products, Inc., All rights Reserved.
+* 
+* This software is protected by copyright laws of the United States and
+* of foreign countries. This material may also be protected by patent laws
+* and technology transfer regulations of the United States and of foreign
+* countries. This software is furnished under a license agreement and/or a
+* nondisclosure agreement and may only be used or reproduced in accordance
+* with the terms of those agreements. Dissemination of this information to
+* any party or parties not specified in the license agreement and/or
+* nondisclosure agreement is expressly prohibited.
+*
+* The above copyright notice and this permission notice shall be included
+* in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+* OTHER DEALINGS IN THE SOFTWARE.
+*
+* Except as contained in this notice, the name of Maxim Integrated
+* Products, Inc. shall not be used except as stated in the Maxim Integrated
+* Products, Inc. Branding Policy.
+*
+* The mere transfer of this software does not imply any licenses
+* of trade secrets, proprietary technology, copyrights, patents,
+* trademarks, maskwork rights, or any other form of intellectual
+* property whatsoever. Maxim Integrated Products, Inc. retains all
+* ownership rights.
+*******************************************************************************
+*/
+
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Data;
+using System.Drawing;
+using System.Linq;
+using System.Text;
+using System.Windows.Forms;
+
+//------------------------------------------------------------------------------------------
+// OS24EVK-59 split into HeartRateApp EXE and MAX30101 DLL.
+// Moved all MAX30101 DLL classes into namespace Maxim.MAX30101GUI
+// Moved all HeartRateApp GUI classes into namespace Maxim.MAX30101
+// OS24EVK-59 Create separate project that builds Maxim.MAX30101GUI DLL library
+
+namespace HealthSensorPlatform
+{
+    public partial class SplashScreen : Form
+    {
+        private Timer timer = new Timer();
+        internal bool EnableTimer = true;
+
+
+        public SplashScreen()
+        {
+            InitializeComponent();
+
+            //create event handler for timer event
+            maximSplashScreen1.ConfigureTimer(timer, new EventHandler(timer_Tick));
+
+            //create event handlers for the links and disable checkbox
+            maximSplashScreen1.LinkClicked += new LinkLabelLinkClickedEventHandler(LinkClicked);
+            maximSplashScreen1.DisableSplashScreenClicked += new EventHandler(DisableSplashScreenClicked);
+        }
+
+        public SplashScreen(int numberOfSeconds)
+        {
+            InitializeComponent();
+
+            maximSplashScreen1.DismissTime = numberOfSeconds;
+
+            //create event handler for timer event
+            maximSplashScreen1.ConfigureTimer(timer, new EventHandler(timer_Tick));
+
+            //create event handlers for the links and disable checkbox
+            maximSplashScreen1.LinkClicked += new LinkLabelLinkClickedEventHandler(LinkClicked);
+            maximSplashScreen1.DisableSplashScreenClicked += new EventHandler(DisableSplashScreenClicked);
+        }
+
+        public bool SplashDisabled()
+        {
+            return Properties.Settings.Default.DisableSplash;
+        }
+
+        public void ShowOKButton()
+        {
+            btn_OK.Visible = true;
+        }
+
+        private void SplashScreen_Load(object sender, EventArgs e)
+        {
+            if (EnableTimer)//start timer if enabled
+                timer.Start();
+            else
+                timer.Stop();
+
+            if (Properties.Settings.Default.DisableSplash == true)
+                maximSplashScreen1.Checked = true;
+        }
+        void timer_Tick(object sender, EventArgs e)
+        {
+            //stop timer and close splash screen when time is up
+            timer.Stop();
+            this.Hide();
+        }
+
+        void LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
+        {
+            //get the linkLabel that was clicked
+            LinkLabel linkLabel = (LinkLabel)sender;
+
+            //linkLabel.LinkVisited = true;
+
+            //Launch link in browser
+            System.Diagnostics.Process.Start("http://" + linkLabel.Text);
+        }
+
+        void DisableSplashScreenClicked(object sender, EventArgs e)
+        {
+            //get the checkbox that was clicked
+            CheckBox checkBox = (CheckBox)sender;
+
+            //save the checked status in the app settings
+            Properties.Settings.Default.DisableSplash = checkBox.Checked;
+            Properties.Settings.Default.Save();
+        }
+
+        private void btn_OK_Click(object sender, EventArgs e)
+        {
+            this.Hide();
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HspGuiSourceV301/HSPGui/SplashScreen.resx	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,287 @@
+<?xml version="1.0" encoding="utf-8"?>
+<root>
+  <!-- 
+    Microsoft ResX Schema 
+    
+    Version 2.0
+    
+    The primary goals of this format is to allow a simple XML format 
+    that is mostly human readable. The generation and parsing of the 
+    various data types are done through the TypeConverter classes 
+    associated with the data types.
+    
+    Example:
+    
+    ... ado.net/XML headers & schema ...
+    <resheader name="resmimetype">text/microsoft-resx</resheader>
+    <resheader name="version">2.0</resheader>
+    <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+    <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+    <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
+    <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+    <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+        <value>[base64 mime encoded serialized .NET Framework object]</value>
+    </data>
+    <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+        <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
+        <comment>This is a comment</comment>
+    </data>
+                
+    There are any number of "resheader" rows that contain simple 
+    name/value pairs.
+    
+    Each data row contains a name, and value. The row also contains a 
+    type or mimetype. Type corresponds to a .NET class that support 
+    text/value conversion through the TypeConverter architecture. 
+    Classes that don't support this are serialized and stored with the 
+    mimetype set.
+    
+    The mimetype is used for serialized objects, and tells the 
+    ResXResourceReader how to depersist the object. This is currently not 
+    extensible. For a given mimetype the value must be set accordingly:
+    
+    Note - application/x-microsoft.net.object.binary.base64 is the format 
+    that the ResXResourceWriter will generate, however the reader can 
+    read any of the formats listed below.
+    
+    mimetype: application/x-microsoft.net.object.binary.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
+            : and then encoded with base64 encoding.
+    
+    mimetype: application/x-microsoft.net.object.soap.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+            : and then encoded with base64 encoding.
+
+    mimetype: application/x-microsoft.net.object.bytearray.base64
+    value   : The object must be serialized into a byte array 
+            : using a System.ComponentModel.TypeConverter
+            : and then encoded with base64 encoding.
+    -->
+  <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+    <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
+    <xsd:element name="root" msdata:IsDataSet="true">
+      <xsd:complexType>
+        <xsd:choice maxOccurs="unbounded">
+          <xsd:element name="metadata">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" />
+              </xsd:sequence>
+              <xsd:attribute name="name" use="required" type="xsd:string" />
+              <xsd:attribute name="type" type="xsd:string" />
+              <xsd:attribute name="mimetype" type="xsd:string" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="assembly">
+            <xsd:complexType>
+              <xsd:attribute name="alias" type="xsd:string" />
+              <xsd:attribute name="name" type="xsd:string" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="data">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+                <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
+              <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+              <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="resheader">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" />
+            </xsd:complexType>
+          </xsd:element>
+        </xsd:choice>
+      </xsd:complexType>
+    </xsd:element>
+  </xsd:schema>
+  <resheader name="resmimetype">
+    <value>text/microsoft-resx</value>
+  </resheader>
+  <resheader name="version">
+    <value>2.0</value>
+  </resheader>
+  <resheader name="reader">
+    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <resheader name="writer">
+    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <assembly alias="System.Drawing" name="System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
+  <data name="$this.Icon" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+    <value>
+        AAABAAEAMDAAAAEAIACoJQAAFgAAACgAAAAwAAAAYAAAAAEAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAqbEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAqLEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAKmyAAAAAAAAAAAAAAAAAACpsgABqLEACqmyABGpsgAWqbIAGaixABqosQAaqbIAGaix
+        ABapsgARqLEAC6myAAIAAAAAAAAAAAAAAACpsgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAACpsgAAAAAAAAAAAAAAAAAAqLEAE6ixACuosQBUqLEAkqmyAMGpsgDlqbIA/aix
+        AP+osQD/qLEA/qmyAOiosQDFqbIAl6myAFqpsgAuqbIAFQAAAAAAAAAAAAAAAKixAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAqbIAAKixAAAAAAAAAAAAAKmyAB6psgBUqbIApKmyAOupsgD/qLEA/6my
+        AP+osQD/qLEA/6ixAP+psgD/qLEA/6ixAP+osQD/qbIA/6ixAP+osQDyqLEAqqmyAFmpsgAiAAAAAAAA
+        AACpsgAAqLEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACpsgAAAAAAAAAAAACosQANqbIAXKmyALiosQD/qLEA/6my
+        AP+osQD+qLEA/qmyAP+psgD/qbIA/6myAP+psgD/qbIA/6myAP+psgD/qLEA/qixAP6psgD/qLEA/6my
+        AP+osQC/qbIAZKixABEAAAAAAAAAAKmyAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKmyAAAAAAAAAAAAAKixACuosQCjqbIA9aix
+        AP+psgD/qLEA/qmyAP+psgD/qbIA/6myAP+psgD/qbIA/6myAP+psgD/qbIA/6myAP+psgD/qbIA/6my
+        AP+psgD/qbIA/qmyAP+psgD/qbIA+aixAKupsgA0AAAAAAAAAACpsgAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAqbIARqix
+        ANWosQD/qbIA/6ixAP+osQD+qbIA/6myAP+psgD/qbIA/6myAP+psgD/qbIA/6myAP+psgD/qbIA/6my
+        AP+psgD/qbIA/6myAP+psgD/qbIA/6ixAP6osQD+qbIA/6myAP+osQDcqbIAUwAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAqbIAAAAA
+        AACosQBVqLEA76myAP+psgD/qLEA/qmyAP+psgD/qbIA/6myAP+psgD/qbIA/6myAP+psgD/qbIA/6my
+        AP+psgD/qbIA/6myAP+psgD/qbIA/6myAP+psgD/qbIA/6myAP+psgD/qLEA/qmyAP+psgD/qLEA86my
+        AGUAAAAAqbIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AACpsgAAAAAAAKmyAE6psgD8qbIA/6myAP+osQD+qbIA/6myAP+psgD/qbIA/6myAP+psgD/qbIA/6my
+        AP+psgD/qbIA/6myAP+psgD/qbIA/6myAP+psgD/qbIA/6myAP+psgD/qbIA/6myAP+psgD/qbIA/6ix
+        AP6psgD+qLEA/6myAP6psgBhAAAAAKixAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAKixAAAAAAAAqbIANKixAP2osQD/qLEA/6ixAP6psgD/qbIA/6myAP+psgD/qbIA/6my
+        AP+psgD/qbIA/6myAP+psgD/qbIA/6myAP+psgD/qbIA/6myAP+psgD/qbIA/6myAP+psgD/qbIA/6my
+        AP+psgD/qbIA/6myAP+psgD+qLEA/qmyAP+osQD/qLEARwAAAACpsgAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAqLEAAAAAAACosQASqbIA6KmyAP+psgD+qbIA/6myAP+psgD/qbIA/6my
+        AP+psgD/qbIA/6myAP+psgD/qbIA/6myAP+psgD/qbIA/6myAP+psgD/qbIA/6myAP+psgD/qbIA/6my
+        AP+psgD/qbIA/6myAP+psgD/qbIA/6myAP+psgD/qbIA/6myAP6psgD/qbIA8qixAB8AAAAAqLEAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACosQAAAAAAAAAAAACpsgCvqbIA/qmyAP6psgD/qLEA/6ix
+        AP+osQD/qLEA/6ixAP+osQD/qLEA/6ixAP+osQD/qLEA/6ixAP+osQD/qbIA/6myAP+psgD/qbIA/6ix
+        AP+osQD/qLEA/6ixAP+osQD/qLEA/6ixAP+osQD/qLEA/6ixAP+osQD/qLEA/6myAP+psgD+qbIA/qix
+        AMGosgAAAAAAAKixAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACosQAAAAAAAKixAFuosQD1qLEA/6my
+        AP+osQD/q7QI/7a9J/+3vyv/t78r/7i/Lf+stAn/rbYN/7jALv+3viv/t78r/7i/LP+stAn/qLEA/6my
+        AP+psgD/qLEA/6u0B/+3vin/t78r/7e/K/+4vy7/r7cS/6u0Bv+4vy3/t78r/7e/K/+2vin/rLQJ/6ix
+        AP+psgD/qbIA/6ixAPepsgBuAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKmyAAAAAAAAqbIADqmy
+        AMSosQD/qbIA/6myAP+osQD/t78q/+zuxv/09N3/8/Ta//b35f+5wC//tbwk//Lz2P/z9Nz/8/Tb//X1
+        4v/GzFj/qbIC/6ixAP+osQD/qbIA/8PIS//z9N3/8/Tb//P02//09d7/ucEy/7S8Iv/39+b/8/Ta//T0
+        3f/v8M//uMAv/6ixAP+psgD/qbIA/qmyAP+psgDPqLEAGQAAAACpsgAAAAAAAAAAAAAAAAAAAAAAAKix
+        AAAAAAAAqLEAY6myAPKosQD/qLEA/qmyAP+osQD/usEz//j57P////////////////+9xDr/qbIB/97i
+        nf/////////////////w8tX/sLkX/6ixAP+osQD/rrcQ/+vtxP/////////////////m6LT/qrMD/7e+
+        Kf/////////////////8/Pb/u8M4/6exAP+psgD/qLEA/qixAP+osQD3qLEAcgAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAACpsgALqLEAqqmyAP+psgD/qbIA/6myAP+osQD/ucEy//f45///////////////
+        //+9wzj/qLEA/7e+Kv/5+e3/////////////////ztRx/6myAP+psgD/yc5e//////////////////39
+        +f+6wjX/qLEA/7e+Kf/////////////////6+/L/u8I3/6ixAP+psgD/qbIA/6ixAP6osQD/qbIAtqmy
+        ABQAAAAAAAAAAAAAAAAAAAAAqLEAAAAAAACosQA7qLEA3amyAP+osQD+qbIA/6myAP+osQD/ucEy//f4
+        5/////////////////+9wzj/qLEA/6qzBf/T13z///////7+/v//////+frw/7C4FP+ttQr/9fbi////
+        ///+/v7//////9ndkP+rtAj/qLEA/7e+Kf/////////////////6+/L/u8I3/6ixAP+psgD/qbIA/6ix
+        AP6psgD/qLEA6KmyAEUAAAAAqbIAAAAAAAAAAAAAAAAAAAAAAACpsgBlqbIA/6myAP+psgD/qbIA/6my
+        AP+osQD/ucEy//f45/////////////////+9wzj/qLEA/6ixAP+3vyv/8fLW///////+/v7//////9rd
+        kP/S1nj/////////////////9vfk/7vCNf+osQD/qLEA/7e+Kf/////////////////6+/L/u8I3/6ix
+        AP+psgD/qbIA/6myAP+psgD/qbIA/6myAHMAAAAAAAAAAAAAAAAAAAAAAAAAAKmyAAqosQCTqLEA/6ix
+        AP+psgD/qbIA/6myAP+osQD/ucEy//f45/////////////////+9wzj/qLEA/6ixAP+osQD/0NV1////
+        //////////////z9+f/7+/P/////////////////1tqE/6qzA/+osQD/qLEA/7e+Kf//////////////
+        ///6+/L/u8I3/6ixAP+psgD/qbIA/6myAP+osQD+qbIA/6ixAKKosQARAAAAAAAAAAAAAAAAAAAAAKmy
+        AByosQC5qbIA/6myAP+psgD/qbIA/6myAP+osQD/ucEy//f45/////////////////+9wzj/qLEA/6my
+        AP+nsAD/tr0n/+zuyP/////////////+/////////v7+///////w8tX/usEz/6ewAP+psgD/qLEA/7e+
+        Kf/////////////////6+/L/u8I3/6ixAP+psgD/qbIA/6myAP+psgD/qbIA/6ixAMqosQAkAAAAAAAA
+        AAAAAAAAAAAAAKixACqosQDYqbIA/6myAP+psgD/qbIA/6myAP+osQD/ucEy//f45///////////////
+        //+9wzj/qLEA/6myAP+psQD/pa4A/9DVdP/9/fn///////7+/v/+/v7///////7+/v/V2oX/prAA/6ix
+        AP+psgD/qLEA/7e+Kf/////////////////6+/L/u8I3/6ixAP+psgD/qbIA/6myAP+psgD/qbIA/6my
+        AOipsgAyAAAAAAAAAAAAAAAAAAAAAKixADSosQDtqLEA/6myAP+psgD/qbIA/6myAP+osQD/ucEy//f4
+        5/////////////////+9wzj/qLEA/6myAP+psgD/p7AA/7C5Fv/r7cb//////////////////////+7w
+        zv+1vSX/p7AA/6myAP+psgD/qLEA/7e+Kf/////////////////6+/L/u8I3/6ixAP+psgD/qbIA/6my
+        AP+psgD/qLEA/6ixAPypsgA7AAAAAAAAAAAAAAAAAAAAAKmyADqosQD6qbIA/6myAP+psgD/qbIA/6my
+        AP+osQD/ucEy//f45/////////////////+9wzj/qLEA/6myAP+psgD/qbIA/6StAP/L0Gb/+/z2////
+        /////////v79/93gm/+irAD/qbIA/6myAP+psgD/qLEA/7e+Kf/////////////////6+/L/u8I3/6ix
+        AP+psgD/qbIA/6myAP+psgD/qbIA/6ixAP+psgBCAAAAAAAAAAAAAAAAAAAAAKixADyosQD9qbIA/6my
+        AP+psgD/qbIA/6myAP+osQD/ucEy//f45/////////////////+9wzj/qLEA/6myAP+psgD/qLEA/6ew
+        AP+psgH/6+3F//7+/v///////////+jqvP+utxD/p7AA/6myAP+psgD/qLEA/7e+Kf//////////////
+        ///6+/L/u8I3/6ixAP+psgD/qbIA/6myAP+psgD/qbIA/qixAP+psgBFAAAAAAAAAAAAAAAAAAAAAKmy
+        ADqosQD6qLEA/6myAP+psgD/qbIA/6myAP+osQD/ucEy//f45/////////////////+9wzj/qLEA/6my
+        AP+psgD/qLEA/663Ef+osQD/wMZF//7+/P/+/v7///////v89v/O023/pq8A/6ixAP+psgD/qLEA/7e+
+        Kf/////////////////6+/L/u8I3/6ixAP+psgD/qbIA/6myAP+psgD/qbIA/6ixAP+psgBDAAAAAAAA
+        AAAAAAAAAAAAAKixADWosQDvqLEA/6myAP+psgD/qbIA/6myAP+osQD/ucEy//f45///////////////
+        //+9wzj/qLEA/6myAP+nsQD/srob/9vflv+4wC7/pq8A/+Tnsf///////v7+///////r7cX/tLwh/6ew
+        AP+psgD/qLEA/7e+Kf/////////////////6+/L/u8I3/6ixAP+psgD/qbIA/6myAP+psgD/qLEA/6ix
+        AP2osQA8AAAAAAAAAAAAAAAAAAAAAKmyACupsgDZqLEA/6myAP+psgD/qbIA/6myAP+osQD/ucEy//f4
+        5/////////////////+9wzj/qLEA/6ixAP+nsAD/ys9h///////X24n/qrME/7W8Iv//////////////
+        ////////z9Nw/6ixAP+osQD/qLEA/7e+Kf/////////////////6+/L/u8I3/6ixAP+psgD/qbIA/6my
+        AP+psgD/qLEA/6myAOqpsgAzAAAAAAAAAAAAAAAAAAAAAKixAB2osQC8qLEA/6myAP+psgD/qbIA/6my
+        AP+osQD/ucEy//f45/////////////////+9wzj/qLEA/6ixAP+zux//6uzD///////9/Pj/tr0m/6ix
+        AP/Y3Iz///////7+/v//////8PLU/7W9Jf+osQD/qLEA/7e+Kf/////////////////6+/L/u8I3/6ix
+        AP+psgD/qbIA/6myAP+psgD/qLEA/6ixAMuosQAkAAAAAAAAAAAAAAAAAAAAAKixAAuosQCVqLEA/6ix
+        AP6psgD/qbIA/6myAP+osQD/ucEy//f45/////////////////+8wzj/qLEA/6myAv/L0GP/////////
+        ////////3+Ki/6qzBP+vtxH/+vvy/////////////////9HVdf+qswX/qLEA/7a+KP//////////////
+        ///6+/L/u8I3/6ixAP+psgD/qbIA/6myAP+osQD+qLEA/6ixAKWpsgASAAAAAAAAAAAAAAAAAAAAAAAA
+        AACosQBpqLEA/6ixAP+psgD/qbIA/6myAP+osQD/ucEy//f45//////////////////HzVr/t74p/77F
+        Pv/z89r/////////////////2d2O/6qzBP+psgL/z9Nu//////////////////j56v+/xkH/t74p/8PK
+        Tf/////////////////6+/L/u8I3/6ixAP+psgD/qbIA/6myAP+psgD/qLEA/6ixAHYAAAAAAAAAAAAA
+        AAAAAAAAqLEAAAAAAACpsgA+qLEA4KixAP+psgD+qbIA/6myAP+osQD/usEy//f46P////////////7+
+        /v///////////////////////v7+///////3+en/srsc/6ixAP+osQD/sLcU//Hz1////////v7+////
+        ///////////////////+/v7////////////6+/L/u8I3/6exAP+psgD/qbIA/6myAP6psgD/qLEA7Kix
+        AEoAAAAAqbIAAAAAAAAAAAAAAAAAAAAAAACosQAOqbIAramyAP+osQD/qbIA/6myAP+osQD/ucAx//b3
+        5v///////v7+///////////////////////+/v7////////////P1HH/qrME/6ixAP+osQD/qbIC/8jO
+        Xf////////////7+/v///////////////////////v7+///////6+/H/u8I2/6ixAP+psgD/qbIA/6my
+        AP+osQD/qbIAuqmyABkAAAAAAAAAAAAAAAAAAAAAAAAAAKmyAAAAAAAAqbIAaamyAPWosQD/qbIA/qmy
+        AP+osQD/sroc/+jqvP///////////////////////////////////////////+3vyv+zux7/qLEA/6my
+        AP+psgD/qLEA/7G5GP/n6rr////////////////////////////////////////////t78v/tLwj/6ix
+        AP+psgD/qbIA/qmyAP+osQD6qLEAeAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKmyAAAAAAAAqbIAFamy
+        AMiosQD/qLEA/6myAP+osQD/qbIA/77FP//f46H/5Oev/+Pnrv/j567/4+eu/+Pnrv/k56//3+Oi/77F
+        QP+psgD/qLEA/6myAP+psgD/qLEA/6ixAP+8wzj/3uKe/+Tnr//j567/4+eu/+Pnrv/j567/5Oev/+Hk
+        pf/Bx0j/qrIC/6ixAP+psgD/qbIA/qmyAP+psgDTqLEAIQAAAACosQAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AACosQAAAAAAAKixAGSosQD3qLEA/6myAP+psgD/qLEA/6ewAP+stQr/sLkW/7C5Fv+wuRb/sLkW/7C5
+        Fv+wuRb/rLUK/6ewAP+osQD/qbIA/6myAP+psgD/qbIA/6ixAP+nsAD/rLQJ/7C5Fv+wuRb/sLkW/7C5
+        Fv+wuRb/sLkW/621DP+nsAD/qLEA/6myAP+psgD/qLEA/6ixAPmpsgB3AAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAACpsgAAAAAAAAAAAACosQC2qLEA/6myAP6psgD/qbIA/6ixAP+osQD/qLEA/6ix
+        AP+osQD/qLEA/6ixAP+osQD/qLEA/6ixAP+psgD/qbIA/6myAP+psgD/qbIA/6myAP+osQD/qLEA/6ix
+        AP+osQD/qLEA/6ixAP+osQD/qLEA/6ixAP+osQD/qbIA/6myAP+osQD+qLEA/6myAMaosQAGAAAAAKix
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAqbIAAAAAAACpsgAbqLEA7aixAP+osQD+qbIA/6my
+        AP+psgD/qbIA/6myAP+psgD/qbIA/6myAP+psgD/qbIA/6myAP+psgD/qbIA/6myAP+psgD/qbIA/6my
+        AP+psgD/qbIA/6myAP+psgD/qbIA/6myAP+psgD/qbIA/6myAP+psgD/qbIA/6ixAP6psgD/qLEA9aix
+        ACoAAAAAqLEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAqLEAPKix
+        AP+osQD/qLEA/qmyAP+psgD/qbIA/6myAP+psgD/qbIA/6myAP+psgD/qbIA/6myAP+psgD/qbIA/6my
+        AP+psgD/qbIA/6myAP+psgD/qbIA/6myAP+psgD/qbIA/6myAP+psgD/qbIA/6myAP+psgD/qLEA/qix
+        AP6osQD/qLEATgAAAAAAAAAAqLEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AACosQAAAAAAAKmyAFWosQD/qbIA/6ixAP+psgD+qbIA/6myAP+psgD/qbIA/6myAP+psgD/qbIA/6my
+        AP+psgD/qbIA/6myAP+psgD/qbIA/6myAP+psgD/qbIA/6myAP+psgD/qbIA/6myAP+psgD/qbIA/6my
+        AP6osQD/qbIA/6ixAP+psgBqAAAAAKixAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAqLEAAAAAAACpsgBbqLEA+qixAP+psgD/qLEA/qmyAP+psgD/qbIA/6my
+        AP+psgD/qbIA/6myAP+psgD/qbIA/6myAP+psgD/qbIA/6myAP+psgD/qbIA/6myAP+psgD/qbIA/6my
+        AP+psgD/qLEA/qixAP+osQD/qbIA/qmyAG4AAAAAqbIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAqbIAT6ixAOKosQD/qLEA/6ix
+        AP+psgD+qbIA/6myAP+psgD/qbIA/6myAP+psgD/qbIA/6myAP+psgD/qbIA/6myAP+psgD/qbIA/6my
+        AP+psgD/qbIA/6myAP6osQD/qLEA/6ixAP+osQDpqbIAXAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKixAAAAAAAAAAAAAKix
+        ADGosQC0qLEA96ixAP+osQD/qbIA/qmyAP+psgD/qbIA/6myAP+psgD/qbIA/6myAP+psgD/qbIA/6my
+        AP+psgD/qbIA/6myAP+psgD/qbIA/qmyAP+osQD/qLEA+amyALypsgA8AAAAAAAAAACosQAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AACpsgAAAAAAAAAAAACosQAOqbIAcKixAMWosQD/qbIA/6myAP+osQD+qbIA/qmyAP+psgD/qbIA/6my
+        AP+psgD/qbIA/6myAP+psgD/qbIA/qmyAP6osQD/qbIA/6myAP+osQDKqLEAeaixABMAAAAAAAAAAKix
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAqLEAAKixAAAAAAAAAAAAAKmyACapsgBrqbIAsKixAO2osQD/qLEA/6ix
+        AP+osQD/qLEA/6ixAP+osQD/qLEA/6ixAP+osQD/qLEA/6ixAP+osQDwqbIAtqixAHGosQArAAAAAAAA
+        AACosQAAqbIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACpsgAAAAAAAAAAAAAAAAAAqbIAGamy
+        AECosQBpqLEAnamyAMeosQDlqLEA+qixAP+psgD/qbIA/KmyAOipsgDKqLEAoaixAG6psgBCqbIAHQAA
+        AAAAAAAAAAAAAKixAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKmy
+        AAAAAAAAAAAAAAAAAACosQAAqLEAEamyAB6psgAoqbIAL6ixADKpsgAyqLEAL6ixACmpsgAfqLEAEqmy
+        AAEAAAAAAAAAAAAAAACosQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAqLEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAqLEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD///////8AAP///////wAA///gB///
+        AAD//wAA//8AAP/8AAA//wAA//AAAA//AAD/4AAAB/8AAP/AAAAD/wAA/4AAAAH/AAD/AAAAAP8AAP4A
+        AAAAfwAA/AAAAAA/AAD8AAAAAD8AAPgAAAAAHwAA+AAAAAAfAADwAAAAAA8AAPAAAAAADwAA8AAAAAAP
+        AADgAAAAAAcAAOAAAAAABwAA4AAAAAAHAADgAAAAAAcAAOAAAAAABwAA4AAAAAAHAADgAAAAAAcAAOAA
+        AAAABwAA4AAAAAAHAADgAAAAAAcAAOAAAAAABwAA8AAAAAAPAADwAAAAAA8AAPAAAAAADwAA+AAAAAAf
+        AAD4AAAAAB8AAPwAAAAAPwAA/AAAAAA/AAD+AAAAAH8AAP8AAAAA/wAA/4AAAAH/AAD/wAAAA/8AAP/g
+        AAAH/wAA//AAAA//AAD//AAAP/8AAP//AAD//wAA///gB///AAD///////8AAP///////wAA////////
+        AAA=
+</value>
+  </data>
+</root>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HspGuiSourceV301/HSPGui/Streaming.cs	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,98 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.ComponentModel;
+using System.Collections;
+
+namespace HealthSensorPlatform
+{
+    class Streaming
+    {
+        BackgroundWorker _testWorker;
+
+        public ArrayList ArrayListRed = new ArrayList();
+        public ArrayList ArrayListIR = new ArrayList();
+        public ArrayList ArrayListGreen = new ArrayList();
+        public event EventHandler<PartialArrayIntAvailableEventArgs> PartialArrayIntAvailable;
+
+        public void Init()
+        {
+            _testWorker = new BackgroundWorker();
+            _testWorker.WorkerSupportsCancellation = true;
+            _testWorker.ProgressChanged += new ProgressChangedEventHandler(_testWorker_ProgressChanged);
+            _testWorker.DoWork += new DoWorkEventHandler(_testWorker_DoWork);
+            _testWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(_testWorker_RunWorkerCompleted);
+            _testWorker.WorkerReportsProgress = true;
+        }
+
+        protected virtual void OnPartialArrayIntAvailable(PartialArrayIntAvailableEventArgs e)
+        {
+            EventHandler<PartialArrayIntAvailableEventArgs> handler = PartialArrayIntAvailable;
+            if (handler != null)
+            {
+                handler(this, e);
+            }
+        }
+
+        public void Start()
+        {
+            ArrayListRed.Clear();
+            ArrayListIR.Clear();
+            ArrayListGreen.Clear();
+            _testWorker.RunWorkerAsync();
+        }
+        public void Stop()
+        {
+            _testWorker.CancelAsync();
+        }
+        void _testWorker_ProgressChanged(object sender, ProgressChangedEventArgs e)
+        {
+            var data = (System.Tuple<int, int, int[], int[], int[]>)(e.UserState);
+            int reportID = data.Item1;
+            int sampleNumberOffset = data.Item2;
+            int[] list1_Red___or_X = data.Item3;
+            int[] list2_IR____or_Y = data.Item4;
+            int[] list3_Green_or_Z = data.Item5;
+
+            for (int index = 0; index < list1_Red___or_X.Length; index++)
+            {
+                ArrayListRed.Add(list1_Red___or_X[index]);
+            }
+            for (int index = 0; index < list2_IR____or_Y.Length; index++)
+            {
+                ArrayListIR.Add(list2_IR____or_Y[index]);
+            }
+            for (int index = 0; index < list3_Green_or_Z.Length; index++)
+            {
+                ArrayListGreen.Add(list3_Green_or_Z[index]);
+            }
+
+            // https://jira.maxim-ic.com/browse/OS24EVK-59 matlab: PartialArrayIntAvailable based on PartialDataBufferAvailable of r14194 (broken)
+            // https://jira.maxim-ic.com/browse/OS24EVK-59 matlab: What about using System.Array<int> instead of System.Collections.ArrayList?
+            // https://jira.maxim-ic.com/browse/OS24EVK-59 matlab: Changed PartialDataBufferAvailableEventArgs and FinalDataBufferAvailableEventArgs to use int[] rawRedData, int[] rawIRData, int[] rawGreenData
+            // int[] RawRedData replaces ArrayList ArrayListRed
+            // example: https://jira.maxim-ic.com/browse/OS24EVK-59 standard event handler: Fire the PartialArrayIntAvailable event
+            OnPartialArrayIntAvailable(new PartialArrayIntAvailableEventArgs()
+            {
+                sampleNumberOffset = sampleNumberOffset,
+                rawRedData = (int[])ArrayListRed.ToArray(typeof(int)),
+                rawIRData = (int[])ArrayListIR.ToArray(typeof(int)),
+                rawGreenData = (int[])ArrayListGreen.ToArray(typeof(int))
+            });
+        }
+        private void _testWorker_DoWork(object sender, DoWorkEventArgs e)
+        {
+            while (true)
+            {
+                if (_testWorker.CancellationPending)
+                {
+                    return;
+                }
+            }
+        }
+        void _testWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
+        {
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HspGuiSourceV301/HSPGui/StreamingParameters.cs	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,26 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace HealthSensorPlatform
+{
+    class StreamingParameters
+    {
+        // MAX30101 Parameters
+        public int SampleRate;
+        public int SampleAverage;
+        public int PulseWidth;
+        public int AdcFullScaleRange;
+        public int RedCurrent;
+        public int IrCurrent;
+        public int Greencurrent;
+        public int PilotPa;
+        public int ProxIntThresh;
+        public int LedSlot1;
+        public int LedSlot2;
+        public int LedSlot3;
+        public int LedSlot4;
+        //
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HspGuiSourceV301/HSPGui/Temperature/TemperatureValue.cs	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,159 @@
+/*******************************************************************************
+* Copyright (C) 2016 Maxim Integrated Products, Inc., All rights Reserved.
+* 
+* This software is protected by copyright laws of the United States and
+* of foreign countries. This material may also be protected by patent laws
+* and technology transfer regulations of the United States and of foreign
+* countries. This software is furnished under a license agreement and/or a
+* nondisclosure agreement and may only be used or reproduced in accordance
+* with the terms of those agreements. Dissemination of this information to
+* any party or parties not specified in the license agreement and/or
+* nondisclosure agreement is expressly prohibited.
+*
+* The above copyright notice and this permission notice shall be included
+* in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+* OTHER DEALINGS IN THE SOFTWARE.
+*
+* Except as contained in this notice, the name of Maxim Integrated
+* Products, Inc. shall not be used except as stated in the Maxim Integrated
+* Products, Inc. Branding Policy.
+*
+* The mere transfer of this software does not imply any licenses
+* of trade secrets, proprietary technology, copyrights, patents,
+* trademarks, maskwork rights, or any other form of intellectual
+* property whatsoever. Maxim Integrated Products, Inc. retains all
+* ownership rights.
+*******************************************************************************
+*/
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace HealthSensorPlatform
+{
+    public class TemperatureValue
+    {
+        double temperature;
+        int temperatureHex;
+        //bool units;
+        bool dataFormat;
+
+
+        public TemperatureValue(double temperature)
+        {
+            this.temperature = temperature;
+            temperatureHex = temperatureToHex(temperature, false);
+        }
+
+        public TemperatureValue(double temperature, bool dataFormat)
+        {
+            this.temperature = temperature;
+            temperatureHex = temperatureToHex(temperature, dataFormat);
+            this.dataFormat = dataFormat;
+        }
+
+        public TemperatureValue(int hex)
+        {
+            temperatureHex = hex;
+            temperature = hexToTemperature(hex, false);
+        }
+
+        public TemperatureValue(int hex, bool dataFormat)
+        {
+            temperatureHex = hex;
+            temperature = hexToTemperature(hex, dataFormat);
+        }
+
+        public double TemperatureC
+        {
+            get
+            {
+                return temperature;
+            }
+        }
+
+        public double TemperatureF
+        {
+            get
+            {
+                return temperature * 9 / 5 + 32;
+            }
+        }
+        public int TemperatureHex
+        {
+            get
+            {
+                return temperatureHex;
+            }
+        }
+        /*public bool UnitsCelsius
+        {
+            get
+            {
+                return units;
+            }
+        }*/
+        public bool DataFormat
+        {
+            get
+            {
+                return dataFormat;
+            }
+            set
+            {
+                dataFormat = DataFormat;
+            }
+        }
+
+        double hexToTemperature(int hex, bool dataFormat)
+        {
+            int normalCode;
+            int rawCode = hex;
+            double celsius;
+
+            if (rawCode > 0x7fff)
+                normalCode = rawCode - 0x10000;
+            else
+                normalCode = rawCode;
+
+            if (dataFormat == false)
+                celsius = normalCode / Math.Pow(2, 8);
+            else
+                celsius = normalCode / Math.Pow(2, 8) + 64;
+
+            return celsius;
+        }
+
+        int temperatureToHex(double temperature, bool dataFormat)
+        {
+            int code = 0;
+            double temp = 0;
+
+            if (dataFormat)
+            {
+                temp = temperature - 64;
+            }
+            else
+            {
+                temp = temperature;
+            }
+
+                code = (short)(temp * Math.Pow(2, 8));
+
+                if (code < 0)
+                    code += 0x10000;
+
+                return code;
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HspGuiSourceV301/HSPGui/View/CompleteEventArgs.cs	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,47 @@
+/*******************************************************************************
+* Copyright (C) 2016 Maxim Integrated Products, Inc., All rights Reserved.
+* 
+* This software is protected by copyright laws of the United States and
+* of foreign countries. This material may also be protected by patent laws
+* and technology transfer regulations of the United States and of foreign
+* countries. This software is furnished under a license agreement and/or a
+* nondisclosure agreement and may only be used or reproduced in accordance
+* with the terms of those agreements. Dissemination of this information to
+* any party or parties not specified in the license agreement and/or
+* nondisclosure agreement is expressly prohibited.
+*
+* The above copyright notice and this permission notice shall be included
+* in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+* OTHER DEALINGS IN THE SOFTWARE.
+*
+* Except as contained in this notice, the name of Maxim Integrated
+* Products, Inc. shall not be used except as stated in the Maxim Integrated
+* Products, Inc. Branding Policy.
+*
+* The mere transfer of this software does not imply any licenses
+* of trade secrets, proprietary technology, copyrights, patents,
+* trademarks, maskwork rights, or any other form of intellectual
+* property whatsoever. Maxim Integrated Products, Inc. retains all
+* ownership rights.
+*******************************************************************************
+*/
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace HealthSensorPlatform.View
+{
+    public class CompleteEventArgs : EventArgs
+    {
+        public bool Complete;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HspGuiSourceV301/HSPGui/View/DataFormatEventArgs.cs	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,48 @@
+/*******************************************************************************
+* Copyright (C) 2016 Maxim Integrated Products, Inc., All rights Reserved.
+* 
+* This software is protected by copyright laws of the United States and
+* of foreign countries. This material may also be protected by patent laws
+* and technology transfer regulations of the United States and of foreign
+* countries. This software is furnished under a license agreement and/or a
+* nondisclosure agreement and may only be used or reproduced in accordance
+* with the terms of those agreements. Dissemination of this information to
+* any party or parties not specified in the license agreement and/or
+* nondisclosure agreement is expressly prohibited.
+*
+* The above copyright notice and this permission notice shall be included
+* in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+* OTHER DEALINGS IN THE SOFTWARE.
+*
+* Except as contained in this notice, the name of Maxim Integrated
+* Products, Inc. shall not be used except as stated in the Maxim Integrated
+* Products, Inc. Branding Policy.
+*
+* The mere transfer of this software does not imply any licenses
+* of trade secrets, proprietary technology, copyrights, patents,
+* trademarks, maskwork rights, or any other form of intellectual
+* property whatsoever. Maxim Integrated Products, Inc. retains all
+* ownership rights.
+*******************************************************************************
+*/
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace MAX30205EVKit.View
+{
+    public class DataFormatEventArgs : EventArgs
+    {
+        public int Index;
+        public bool DataFormat;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HspGuiSourceV301/HSPGui/View/EnableEventArgs.cs	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,67 @@
+/*******************************************************************************
+* Copyright (C) 2016 Maxim Integrated Products, Inc., All rights Reserved.
+* 
+* This software is protected by copyright laws of the United States and
+* of foreign countries. This material may also be protected by patent laws
+* and technology transfer regulations of the United States and of foreign
+* countries. This software is furnished under a license agreement and/or a
+* nondisclosure agreement and may only be used or reproduced in accordance
+* with the terms of those agreements. Dissemination of this information to
+* any party or parties not specified in the license agreement and/or
+* nondisclosure agreement is expressly prohibited.
+*
+* The above copyright notice and this permission notice shall be included
+* in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+* OTHER DEALINGS IN THE SOFTWARE.
+*
+* Except as contained in this notice, the name of Maxim Integrated
+* Products, Inc. shall not be used except as stated in the Maxim Integrated
+* Products, Inc. Branding Policy.
+*
+* The mere transfer of this software does not imply any licenses
+* of trade secrets, proprietary technology, copyrights, patents,
+* trademarks, maskwork rights, or any other form of intellectual
+* property whatsoever. Maxim Integrated Products, Inc. retains all
+* ownership rights.
+*******************************************************************************
+*/
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace HealthSensorPlatform.View
+{
+    public class EnableEventArgs : EventArgs
+    {
+        public bool Enable;
+        public StreamType Stream;
+
+        public EnableEventArgs(StreamType stream, bool enable)
+        {
+            Enable = enable;
+            Stream = stream;
+        }
+    }
+
+    public enum StreamType
+    {
+        Optical,
+        Accelerometer,
+        Ecg,
+        Pace,
+        RToR,
+        BioZ,
+        Temperature1,
+        Temperature2,
+        Barometer
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HspGuiSourceV301/HSPGui/View/FileLogView/FileLogHeader.cs	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,67 @@
+/*******************************************************************************
+* Copyright (C) 2016 Maxim Integrated Products, Inc., All rights Reserved.
+* 
+* This software is protected by copyright laws of the United States and
+* of foreign countries. This material may also be protected by patent laws
+* and technology transfer regulations of the United States and of foreign
+* countries. This software is furnished under a license agreement and/or a
+* nondisclosure agreement and may only be used or reproduced in accordance
+* with the terms of those agreements. Dissemination of this information to
+* any party or parties not specified in the license agreement and/or
+* nondisclosure agreement is expressly prohibited.
+*
+* The above copyright notice and this permission notice shall be included
+* in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+* OTHER DEALINGS IN THE SOFTWARE.
+*
+* Except as contained in this notice, the name of Maxim Integrated
+* Products, Inc. shall not be used except as stated in the Maxim Integrated
+* Products, Inc. Branding Policy.
+*
+* The mere transfer of this software does not imply any licenses
+* of trade secrets, proprietary technology, copyrights, patents,
+* trademarks, maskwork rights, or any other form of intellectual
+* property whatsoever. Maxim Integrated Products, Inc. retains all
+* ownership rights.
+*******************************************************************************
+*/
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace HealthSensorPlatform.View.FileLogView
+{
+    class FileLogHeader
+    {
+        private string temperature1 = "Temperature 1 [15:0], Temperature (°C)";
+        private string temperature2 = "Temperature 2 [15:0], Temperature (°C)";
+        private string pressure = "Temperature, Temperature (°C), Pressure, Pressure (Pa)";
+        private string ecg = "Time (s), ECG_DATA[17:0], ETAG[2:0], PTAG[2:0], ECG (mV), LDOFF_PH, LDOFF_PL, LDOFF_NH, LDOFF_NL";
+        private string bioz = "Time (s), BIOZ_DATA[19:0], BTAG[2:0], BioZ (ohm), LDOFF_PH, LDOFF_PL, LDOFF_NH, LDOFF_NL, BOVER, BUNDR";
+        private string rToR = "RTOR[13:0], R-To-R Corrected Time of R-peak (s)";
+        private string pace = "Time (s), PACEn_mDATA[9:0], Rising/Falling, Last";
+        private string optical = "Time (s), Red, IR (Infrared), Green";
+        private string accelerometer = "Time (s), X-Axis, Y-Axis, Z-Axis";
+
+        public string Prefix = "% ";
+
+        public string Temperature1 { get { return Prefix + temperature1; } }
+        public string Temperature2 { get { return Prefix + temperature2; } }
+        public string Pressure { get { return Prefix + pressure; } }
+        public string Ecg { get { return Prefix + ecg; } }
+        public string BioZ { get { return Prefix + bioz; } }
+        public string RToR { get { return Prefix + rToR; } }
+        public string Pace { get { return Prefix + pace; } }
+        public string Optical { get { return Prefix + optical; } }
+        public string Accelerometer { get { return Prefix + accelerometer; } }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HspGuiSourceV301/HSPGui/View/FileLogView/IRawFileLogView.cs	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,88 @@
+/*******************************************************************************
+* Copyright (C) 2016 Maxim Integrated Products, Inc., All rights Reserved.
+* 
+* This software is protected by copyright laws of the United States and
+* of foreign countries. This material may also be protected by patent laws
+* and technology transfer regulations of the United States and of foreign
+* countries. This software is furnished under a license agreement and/or a
+* nondisclosure agreement and may only be used or reproduced in accordance
+* with the terms of those agreements. Dissemination of this information to
+* any party or parties not specified in the license agreement and/or
+* nondisclosure agreement is expressly prohibited.
+*
+* The above copyright notice and this permission notice shall be included
+* in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+* OTHER DEALINGS IN THE SOFTWARE.
+*
+* Except as contained in this notice, the name of Maxim Integrated
+* Products, Inc. shall not be used except as stated in the Maxim Integrated
+* Products, Inc. Branding Policy.
+*
+* The mere transfer of this software does not imply any licenses
+* of trade secrets, proprietary technology, copyrights, patents,
+* trademarks, maskwork rights, or any other form of intellectual
+* property whatsoever. Maxim Integrated Products, Inc. retains all
+* ownership rights.
+*******************************************************************************
+*/
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+using HealthSensorPlatform.Model;
+using Maxim.Global;
+
+namespace HealthSensorPlatform.View
+{
+    public interface IRawFileLogView
+    {
+        bool Enable { get; set; }
+
+        string FileDirectory { get; set; }
+
+        event EventHandler<ErrorEventArgs> Error;
+
+        bool SelectCSVFile(string fileName);
+
+        void StreamStartStop();
+
+        void WriteLine(string str);
+
+        void DisplayEcg(double[] time, EcgFifo[] ecgData);
+        void DisplayEcg(double[] time, EcgFifo[] ecgData, DCLeadOff leadOff);
+
+        void DisplayBioZ(double[] time, BioZFifo[] bioZData);
+        void DisplayBioZ(double[] time, BioZFifo[] bioZData, DCLeadOff leadOff);
+        void DisplayBioZ(double[] time, BioZFifo[] bioZData, ACLeadOff acLeadOff);
+        void DisplayBioZ(double[] time, BioZFifo[] bioZData, DCLeadOff leadOff, ACLeadOff acLeadOff);
+
+        void DisplayRToR(int rToRData, double rToRCorrectedSeconds);
+
+        void DisplayPace(double[] time, PaceData.PaceEdge[] paceData);
+
+        void DisplayPressure(int[] hexTemperature, double[] temperature, int[] hexPressure, double[] pressure);
+
+        void DisplayTemperature(int[] hex, double[] temperature);
+
+        /// <summary>
+        /// Save Fifo Data for optical
+        /// </summary>
+        //void DisplayPpg(int[][] data);
+        void DisplayPpg(double[] time, int[][] data);
+        /// <summary>
+        /// Save Fifo data for accelerometer 
+        /// </summary>
+        /// <param name="data"></param>
+        //void DisplayXYZ(int[][] data);
+        void DisplayXYZ(double[] time, int[][] data);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HspGuiSourceV301/HSPGui/View/FileLogView/RawFileLogView.cs	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,387 @@
+/*******************************************************************************
+* Copyright (C) 2016 Maxim Integrated Products, Inc., All rights Reserved.
+* 
+* This software is protected by copyright laws of the United States and
+* of foreign countries. This material may also be protected by patent laws
+* and technology transfer regulations of the United States and of foreign
+* countries. This software is furnished under a license agreement and/or a
+* nondisclosure agreement and may only be used or reproduced in accordance
+* with the terms of those agreements. Dissemination of this information to
+* any party or parties not specified in the license agreement and/or
+* nondisclosure agreement is expressly prohibited.
+*
+* The above copyright notice and this permission notice shall be included
+* in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+* OTHER DEALINGS IN THE SOFTWARE.
+*
+* Except as contained in this notice, the name of Maxim Integrated
+* Products, Inc. shall not be used except as stated in the Maxim Integrated
+* Products, Inc. Branding Policy.
+*
+* The mere transfer of this software does not imply any licenses
+* of trade secrets, proprietary technology, copyrights, patents,
+* trademarks, maskwork rights, or any other form of intellectual
+* property whatsoever. Maxim Integrated Products, Inc. retains all
+* ownership rights.
+*******************************************************************************
+*/
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+using Maxim.Utility;
+using HealthSensorPlatform.Model;
+
+namespace HealthSensorPlatform.View
+{
+    class RawFileLogView : FileLog, IRawFileLogView
+    {
+        /* Fields */
+        private bool enable = false;
+        //private double sampleRate = 0;
+        //private int count = 0;
+
+        /* Constructors */
+
+        /* Events */
+        public new event EventHandler<Maxim.Global.ErrorEventArgs> Error;
+
+        /* Properties */
+        public bool Enable
+        {
+            get
+            {
+                return enable;
+            }
+            set
+            {
+                enable = value;
+                if (enable == false)
+                    Close();
+            }
+        }
+
+        /* Methods */
+        public void StreamStartStop()
+        {
+        }
+
+        public void DisplayEcg(double[] time, EcgFifo[] ecgData)
+        {
+            DisplayEcg(time, ecgData, null);
+        }
+
+        public void DisplayEcg(double[] time, EcgFifo[] ecgData, DCLeadOff leadOff)
+        {
+            StringBuilder sb = new StringBuilder();
+
+            for (int i = 0; i < ecgData.Length; i++)
+            {
+                sb.Append(time[i]);
+                sb.Append(", ");
+                sb.Append(ecgData[i].EcgData);
+                sb.Append(", ");
+                sb.Append(ecgData[i].ETag);
+                sb.Append(", ");
+                sb.Append(ecgData[i].PTag);
+                sb.Append(", ");
+                sb.Append(ecgData[i].Data);
+                sb.Append(", ");
+
+                if (leadOff != null)
+                {
+                    sb.Append(leadOff.PostiveHigh ? 1 : 0); 
+                    sb.Append(", ");
+                    sb.Append(leadOff.PostiveLow ? 1 : 0); 
+                    sb.Append(", ");
+                    sb.Append(leadOff.NegativeHigh ? 1 : 0);
+                    sb.Append(", ");
+                    sb.Append(leadOff.NegativeLow ? 1 : 0);
+                }
+
+
+                if (i != ecgData.Length - 1)
+                    sb.Append(Environment.NewLine);
+            }
+
+            WriteLine(sb.ToString());
+
+        }
+
+        public void DisplayBioZ(double[] time, BioZFifo[] bioZData)
+        {
+            DisplayBioZ(time, bioZData, null, null);
+        }
+
+        public void DisplayBioZ(double[] time, BioZFifo[] bioZData, DCLeadOff leadOff)
+        {
+            DisplayBioZ(time, bioZData, leadOff, null);
+        }
+
+        public void DisplayBioZ(double[] time, BioZFifo[] bioZData, ACLeadOff acLeadOff)
+        {
+            DisplayBioZ(time, bioZData, null, acLeadOff);
+        }
+
+        public void DisplayBioZ(double[] time, BioZFifo[] bioZData, DCLeadOff leadOff, ACLeadOff acLeadOff)
+        {
+             StringBuilder sb = new StringBuilder();
+
+            for (int i = 0; i < bioZData.Length; i++)
+            {
+                sb.Append(time[i]);
+                sb.Append(", ");
+                sb.Append(bioZData[i].BioZData);
+                sb.Append(", ");
+                sb.Append(bioZData[i].BTag);
+                sb.Append(", ");
+                sb.Append(bioZData[i].Data);
+                sb.Append(", ");
+
+                if (leadOff != null)
+                {
+                    sb.Append(leadOff.PostiveHigh ? 1 : 0);
+                    sb.Append(", ");
+                    sb.Append(leadOff.PostiveLow ? 1 : 0);
+                    sb.Append(", ");
+                    sb.Append(leadOff.NegativeHigh ? 1 : 0);
+                    sb.Append(", ");
+                    sb.Append(leadOff.NegativeLow ? 1 : 0);
+                    sb.Append(", ");
+                }
+                else
+                    sb.Append(", , , ,");
+
+                if (acLeadOff != null)
+                {
+                    sb.Append(acLeadOff.BioZOverRange ? 1 : 0);
+                    sb.Append(", ");
+                    sb.Append(acLeadOff.BioZUnderRange ? 1 : 0);
+                    sb.Append(", ");
+                }
+
+                if (i != bioZData.Length - 1)
+                    sb.Append(Environment.NewLine);
+            }
+
+            WriteLine(sb.ToString());
+
+        }
+
+        public void DisplayRToR(int rToRData, double rToRCorrectedSeconds)
+        {
+            StringBuilder sb = new StringBuilder();
+
+            sb.Append(rToRData);
+            sb.Append(", ");
+            sb.Append(rToRCorrectedSeconds);
+
+            WriteLine(sb.ToString());
+        }
+
+        public void DisplayPace(double[] time, PaceData.PaceEdge[] paceData)
+        {
+            StringBuilder sb = new StringBuilder();
+
+            for (int i = 0; i < time.Length; i++)
+            {
+                sb.Append(time[i]);
+                sb.Append(", ");
+                sb.Append(paceData[i].Data);
+                sb.Append(", ");
+                sb.Append(paceData[i].Polarity ? 'R' : 'F');
+                sb.Append(", ");
+                sb.Append(paceData[i].Last ? '1' : '0');
+
+                if (i != time.Length - 1)
+                    sb.Append(Environment.NewLine);
+
+            }
+
+            WriteLine(sb.ToString());
+        }
+
+        public void DisplayPressure(int[] hexTemperature, double[] temperature, int[] hexPressure, double[] pressure)
+        {
+            StringBuilder sb = new StringBuilder();
+
+            for (int i = 0; i < hexTemperature.Length; i++)
+            {
+                sb.Append(hexTemperature[i]);
+                sb.Append(", ");
+                sb.Append(temperature[i]);
+                sb.Append(", ");
+                sb.Append(hexPressure[i]);
+                sb.Append(", ");
+                sb.Append(pressure[i]);
+                sb.Append(", ");
+
+                if (i != hexTemperature.Length - 1)
+                    sb.Append(Environment.NewLine);
+            }
+
+            WriteLine(sb.ToString());
+        }
+
+        public void DisplayTemperature(int[] hex, double[] temperature)
+        {
+            StringBuilder sb = new StringBuilder();
+
+            for (int i = 0; i < hex.Length; i++)
+            {
+                sb.Append(hex[i]);
+                sb.Append(", ");
+                sb.Append(temperature[i].ToString("F3"));
+
+                if (i != hex.Length - 1)
+                    sb.Append(Environment.NewLine);
+            }
+
+            WriteLine(sb.ToString());
+        }
+
+        public void DisplayPpg(double[] time, int[][] data)
+        {
+            StringBuilder strBuilder = new StringBuilder();
+
+            int channelCount = 0;
+
+            int[] data1 = data[0];
+            int[] data2 = data[1];
+            int[] data3 = data[2];
+            //int[] data4 = data[3];
+
+            //if (data4.Length != 0)
+            //    channelCount = 4;
+            if (data3.Length != 0)
+                channelCount = 3;
+            else if (data2.Length != 0)
+                channelCount = 2;
+            else if (data1.Length != 0)
+                channelCount = 1;
+
+            for (int i = 0; i < data1.Length; i++)
+            {
+                strBuilder.Append(time[i]);
+                strBuilder.Append(",");
+                for (int j = 0; j < channelCount; j++)
+                {
+                    //strBuilder.Append(data[j][i] & 0x7FFFF); // Data Code
+                    //strBuilder.Append(",");
+                    //strBuilder.Append(data[j][i] >> 19); // DAC code
+                    //strBuilder.Append(data[j][i] & 0x7FFFF); // Data Code
+                    strBuilder.Append(data[j][i]);
+                    strBuilder.Append(",");
+                }
+                WriteLine(strBuilder.ToString());
+                strBuilder.Clear();
+            }
+        }
+
+        public void DisplayPpg(int[][] data)
+        {
+            long time = DateTime.Now.Ticks;
+            long startTime = DateTime.Now.Ticks;
+            string timeStr;
+            StringBuilder strBuilder = new StringBuilder();
+
+            int channelCount = 0;
+
+            //string datetime = string.Format("{0:HH-mm-ss.fff}", DateTime.Now) + ", "; 
+            timeStr = ((time - startTime) / 10000000.0).ToString() + ", ";
+
+            int[] data1 = data[0];
+            int[] data2 = data[1];
+            int[] data3 = data[2];
+            //int[] data4 = data[3];
+
+            //if (data4.Length != 0)
+            //    channelCount = 4;
+            if (data3.Length != 0)
+                channelCount = 3;
+            else if (data2.Length != 0)
+                channelCount = 2;
+            else if (data1.Length != 0)
+                channelCount = 1;
+
+            for (int i = 0; i < data1.Length; i++)
+            {
+                strBuilder.Append(timeStr);
+                for (int j = 0; j < channelCount; j++)
+                {
+                    //strBuilder.Append(data[j][i] & 0x7FFFF); // Data Code
+                    //strBuilder.Append(",");
+                    //strBuilder.Append(data[j][i] >> 19); // DAC code
+                    //strBuilder.Append(data[j][i] & 0x7FFFF); // Data Code
+                    strBuilder.Append(data[j][i]);
+                    strBuilder.Append(",");
+                }
+                WriteLine(strBuilder.ToString());
+                strBuilder.Clear();
+            }
+
+        }
+
+        public void DisplayXYZ(double[] time, int[][] data)
+        {
+            StringBuilder strBuilder = new StringBuilder();
+
+            int[] data1 = data[0];
+            int[] data2 = data[1];
+            int[] data3 = data[2];
+            //int[] data4 = data[3];
+
+            for (int i = 0; i < data3.Length; i++)
+            {
+                strBuilder.Append(time[i]);
+                strBuilder.Append(",");
+                strBuilder.Append(data[0][i]);
+                strBuilder.Append(",");
+                strBuilder.Append(data[1][i]);
+                strBuilder.Append(",");
+                strBuilder.Append(data[2][i]);
+
+                WriteLine(strBuilder.ToString());
+                strBuilder.Clear();
+            }
+        }
+
+        public void DisplayXYZ(int[][] data)
+        {
+            long time = DateTime.Now.Ticks;
+            long startTime = DateTime.Now.Ticks;
+            string timeStr;
+            StringBuilder strBuilder = new StringBuilder();
+
+            //string datetime = string.Format("{0:HH-mm-ss.fff}", DateTime.Now) + ", "; 
+            timeStr = ((time - startTime) / 10000000.0).ToString() + ", ";
+
+            int[] data1 = data[0];
+            int[] data2 = data[1];
+            int[] data3 = data[2];
+            //int[] data4 = data[3];
+
+            for (int i = 0; i < data3.Length; i++)
+            {
+                strBuilder.Append(time);
+                strBuilder.Append(data[0][i]);
+                strBuilder.Append(",");
+                strBuilder.Append(data[1][i]);
+                strBuilder.Append(",");
+                strBuilder.Append(data[2][i]);
+
+                WriteLine(strBuilder.ToString());
+                strBuilder.Clear();
+            }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HspGuiSourceV301/HSPGui/View/IFormView.cs	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,98 @@
+/*******************************************************************************
+* Copyright (C) 2016 Maxim Integrated Products, Inc., All rights Reserved.
+* 
+* This software is protected by copyright laws of the United States and
+* of foreign countries. This material may also be protected by patent laws
+* and technology transfer regulations of the United States and of foreign
+* countries. This software is furnished under a license agreement and/or a
+* nondisclosure agreement and may only be used or reproduced in accordance
+* with the terms of those agreements. Dissemination of this information to
+* any party or parties not specified in the license agreement and/or
+* nondisclosure agreement is expressly prohibited.
+*
+* The above copyright notice and this permission notice shall be included
+* in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+* OTHER DEALINGS IN THE SOFTWARE.
+*
+* Except as contained in this notice, the name of Maxim Integrated
+* Products, Inc. shall not be used except as stated in the Maxim Integrated
+* Products, Inc. Branding Policy.
+*
+* The mere transfer of this software does not imply any licenses
+* of trade secrets, proprietary technology, copyrights, patents,
+* trademarks, maskwork rights, or any other form of intellectual
+* property whatsoever. Maxim Integrated Products, Inc. retains all
+* ownership rights.
+*******************************************************************************
+*/
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace HealthSensorPlatform.View
+{
+    public interface IFormView
+    {
+        /// <summary>
+        /// Occurs when view requests file logging to be enabled or disabled
+        /// </summary>
+        event EventHandler<EnableEventArgs> FileLogEnable;
+
+        event EventHandler<EventArgs> RegisterExport;
+        event EventHandler<EventArgs> RegisterImport;
+
+        event EventHandler<EventArgs> Connected;
+
+        /// <summary>
+        /// Read all device registers and update the UI to reflect what is set in the devices
+        /// </summary>
+        void UpdateRegisters();
+
+        /// <summary>
+        /// Occurs when user requests manual register reads and writes
+        /// </summary>
+        //event EventHandler<EnableEventArgs> RegisterAccess;
+
+        /// <summary>
+        /// Set view to show file logging is enabled or disabled
+        /// </summary>
+        /// <param name="state"></param>
+        void LogFileItem(StreamType stream, bool state);
+
+        void OpticalLogFileItem(bool state);
+        void EcgLogFileItem(bool state);
+        void RtoRLogFileItem(bool state);
+        void BioZLogFileItem(bool state);
+        void PaceLogFileItem(bool state);
+
+        /// <summary>
+        /// Display messages on the view
+        /// </summary>
+        /// <param name="msg"></param>
+        void MessageInfo(string msg);
+        /// <summary>
+        /// Display version information of firmware
+        /// </summary>
+        /// <param name="msg"></param>
+        //void VersionInfo(string msg);
+        /// <summary>
+        /// Display connection information on the view
+        /// </summary>
+        /// <param name="msg"></param>
+        //void ConnectionInfo(string msg);
+
+        void MessageBoxShow(string msg);
+        void MessageBoxShow(string msg, string title);
+
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HspGuiSourceV301/HSPGui/View/IHspSetting.cs	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,48 @@
+/*******************************************************************************
+* Copyright (C) 2016 Maxim Integrated Products, Inc., All rights Reserved.
+* 
+* This software is protected by copyright laws of the United States and
+* of foreign countries. This material may also be protected by patent laws
+* and technology transfer regulations of the United States and of foreign
+* countries. This software is furnished under a license agreement and/or a
+* nondisclosure agreement and may only be used or reproduced in accordance
+* with the terms of those agreements. Dissemination of this information to
+* any party or parties not specified in the license agreement and/or
+* nondisclosure agreement is expressly prohibited.
+*
+* The above copyright notice and this permission notice shall be included
+* in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+* OTHER DEALINGS IN THE SOFTWARE.
+*
+* Except as contained in this notice, the name of Maxim Integrated
+* Products, Inc. shall not be used except as stated in the Maxim Integrated
+* Products, Inc. Branding Policy.
+*
+* The mere transfer of this software does not imply any licenses
+* of trade secrets, proprietary technology, copyrights, patents,
+* trademarks, maskwork rights, or any other form of intellectual
+* property whatsoever. Maxim Integrated Products, Inc. retains all
+* ownership rights.
+*******************************************************************************
+*/
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace HealthSensorPlatform.View
+{
+    public interface IHspSetting
+    {
+        string BioZSettingString();
+        string EcgSettingString();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HspGuiSourceV301/HSPGui/View/IOpticalAlgorithmView.cs	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,50 @@
+/*******************************************************************************
+* Copyright (C) 2016 Maxim Integrated Products, Inc., All rights Reserved.
+* 
+* This software is protected by copyright laws of the United States and
+* of foreign countries. This material may also be protected by patent laws
+* and technology transfer regulations of the United States and of foreign
+* countries. This software is furnished under a license agreement and/or a
+* nondisclosure agreement and may only be used or reproduced in accordance
+* with the terms of those agreements. Dissemination of this information to
+* any party or parties not specified in the license agreement and/or
+* nondisclosure agreement is expressly prohibited.
+*
+* The above copyright notice and this permission notice shall be included
+* in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+* OTHER DEALINGS IN THE SOFTWARE.
+*
+* Except as contained in this notice, the name of Maxim Integrated
+* Products, Inc. shall not be used except as stated in the Maxim Integrated
+* Products, Inc. Branding Policy.
+*
+* The mere transfer of this software does not imply any licenses
+* of trade secrets, proprietary technology, copyrights, patents,
+* trademarks, maskwork rights, or any other form of intellectual
+* property whatsoever. Maxim Integrated Products, Inc. retains all
+* ownership rights.
+*******************************************************************************
+*/
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace HealthSensorPlatform.View
+{
+    interface IOpticalAlgorithmView
+    {
+        void DisplayAlgorithmResult(double heartRateBPM, bool heartRateBPMValid, double heartRateBPMSignalStrength, 
+            double spO2Percent, bool spO2PercentValid, double spO2PercentSignalStrength);
+
+        void DisplayAlgorithmReset();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HspGuiSourceV301/HSPGui/View/IRegisterExportView.cs	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,52 @@
+/*******************************************************************************
+* Copyright (C) 2016 Maxim Integrated Products, Inc., All rights Reserved.
+* 
+* This software is protected by copyright laws of the United States and
+* of foreign countries. This material may also be protected by patent laws
+* and technology transfer regulations of the United States and of foreign
+* countries. This software is furnished under a license agreement and/or a
+* nondisclosure agreement and may only be used or reproduced in accordance
+* with the terms of those agreements. Dissemination of this information to
+* any party or parties not specified in the license agreement and/or
+* nondisclosure agreement is expressly prohibited.
+*
+* The above copyright notice and this permission notice shall be included
+* in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+* OTHER DEALINGS IN THE SOFTWARE.
+*
+* Except as contained in this notice, the name of Maxim Integrated
+* Products, Inc. shall not be used except as stated in the Maxim Integrated
+* Products, Inc. Branding Policy.
+*
+* The mere transfer of this software does not imply any licenses
+* of trade secrets, proprietary technology, copyrights, patents,
+* trademarks, maskwork rights, or any other form of intellectual
+* property whatsoever. Maxim Integrated Products, Inc. retains all
+* ownership rights.
+*******************************************************************************
+*/
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace HealthSensorPlatform.View
+{
+    interface IRegisterExportView
+    {
+        List<string> Devices { get; set; }
+        List<string> SelectedDevices { get; set; }
+
+        event EventHandler<CompleteEventArgs> SelectionComplete;
+        
+        void Show();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HspGuiSourceV301/HSPGui/View/RegisterExportForm.Designer.cs	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,62 @@
+namespace HealthSensorPlatform
+{
+    partial class RegisterExportForm
+    {
+        /// <summary>
+        /// Required designer variable.
+        /// </summary>
+        private System.ComponentModel.IContainer components = null;
+
+        /// <summary>
+        /// Clean up any resources being used.
+        /// </summary>
+        /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
+        protected override void Dispose(bool disposing)
+        {
+            if (disposing && (components != null))
+            {
+                components.Dispose();
+            }
+            base.Dispose(disposing);
+        }
+
+        #region Windows Form Designer generated code
+
+        /// <summary>
+        /// Required method for Designer support - do not modify
+        /// the contents of this method with the code editor.
+        /// </summary>
+        private void InitializeComponent()
+        {
+            System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(RegisterExportForm));
+            this.registerExport1 = new HealthSensorPlatform.CustomControls.RegisterExportView();
+            this.SuspendLayout();
+            // 
+            // registerExport1
+            // 
+            this.registerExport1.BackColor = System.Drawing.Color.White;
+            this.registerExport1.Dock = System.Windows.Forms.DockStyle.Fill;
+            this.registerExport1.Location = new System.Drawing.Point(0, 0);
+            this.registerExport1.Name = "registerExport1";
+            this.registerExport1.Size = new System.Drawing.Size(385, 307);
+            this.registerExport1.TabIndex = 0;
+            // 
+            // RegisterExportForm
+            // 
+            this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
+            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+            this.ClientSize = new System.Drawing.Size(385, 307);
+            this.Controls.Add(this.registerExport1);
+            this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon")));
+            this.Name = "RegisterExportForm";
+            this.Text = "Export Register Settings";
+            this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.RegisterExportForm_FormClosing);
+            this.ResumeLayout(false);
+
+        }
+
+        #endregion
+
+        private CustomControls.RegisterExportView registerExport1;
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HspGuiSourceV301/HSPGui/View/RegisterExportForm.cs	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,127 @@
+/*******************************************************************************
+* Copyright (C) 2016 Maxim Integrated Products, Inc., All rights Reserved.
+* 
+* This software is protected by copyright laws of the United States and
+* of foreign countries. This material may also be protected by patent laws
+* and technology transfer regulations of the United States and of foreign
+* countries. This software is furnished under a license agreement and/or a
+* nondisclosure agreement and may only be used or reproduced in accordance
+* with the terms of those agreements. Dissemination of this information to
+* any party or parties not specified in the license agreement and/or
+* nondisclosure agreement is expressly prohibited.
+*
+* The above copyright notice and this permission notice shall be included
+* in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+* OTHER DEALINGS IN THE SOFTWARE.
+*
+* Except as contained in this notice, the name of Maxim Integrated
+* Products, Inc. shall not be used except as stated in the Maxim Integrated
+* Products, Inc. Branding Policy.
+*
+* The mere transfer of this software does not imply any licenses
+* of trade secrets, proprietary technology, copyrights, patents,
+* trademarks, maskwork rights, or any other form of intellectual
+* property whatsoever. Maxim Integrated Products, Inc. retains all
+* ownership rights.
+*******************************************************************************
+*/
+
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Data;
+using System.Drawing;
+using System.Linq;
+using System.Text;
+using System.Windows.Forms;
+
+using HealthSensorPlatform.View;
+using Maxim.CustomControls;
+
+namespace HealthSensorPlatform
+{
+    public partial class RegisterExportForm : Form, IRegisterExportView
+    {
+        public RegisterExportForm()
+        {
+            InitializeComponent();
+
+            registerExport1.Complete += new EventHandler<CustomControls.RegisterExportEventArgs>(OnComplete);
+        }
+
+        public List<string> Devices
+        {
+            get
+            {
+                List<string> devicesList = new List<string>();
+
+                foreach(string str in registerExport1.ItemsLeft)
+                {
+                    devicesList.Add(str);
+                }
+
+                return devicesList;
+            }
+            set
+            {
+                registerExport1.ItemsLeft.Clear();
+                registerExport1.ItemsLeft.AddRange(value.ToArray());
+            }
+        }
+
+        public List<string> SelectedDevices
+        {
+            get
+            {
+                List<string> devicesList = new List<string>();
+
+                foreach (string str in registerExport1.ItemsRight)
+                {
+                    devicesList.Add(str);
+                }
+
+                return devicesList;
+            }
+            set
+            {
+                registerExport1.ItemsRight.Clear();
+                registerExport1.ItemsRight.AddRange(value.ToArray());
+            }
+        }
+
+        public event EventHandler<CompleteEventArgs> SelectionComplete;
+
+        void OnComplete(object sender, CustomControls.RegisterExportEventArgs e)
+        {
+            if (e.Button == CustomControls.RegisterExportView.Button.Export)
+            {
+                if (SelectionComplete != null)
+                    SelectionComplete(this, new CompleteEventArgs() { Complete = true });
+            }
+            else
+            {
+                if (SelectionComplete != null)
+                    SelectionComplete(this, new CompleteEventArgs() { Complete = false});
+            }
+
+            Hide();
+        }
+
+        private void RegisterExportForm_FormClosing(object sender, FormClosingEventArgs e)
+        {
+            // Override closing of the window with hiding
+            if (e.CloseReason == CloseReason.UserClosing)
+            {
+                e.Cancel = true;
+                Hide();
+            }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HspGuiSourceV301/HSPGui/View/RegisterExportForm.resx	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,287 @@
+<?xml version="1.0" encoding="utf-8"?>
+<root>
+  <!-- 
+    Microsoft ResX Schema 
+    
+    Version 2.0
+    
+    The primary goals of this format is to allow a simple XML format 
+    that is mostly human readable. The generation and parsing of the 
+    various data types are done through the TypeConverter classes 
+    associated with the data types.
+    
+    Example:
+    
+    ... ado.net/XML headers & schema ...
+    <resheader name="resmimetype">text/microsoft-resx</resheader>
+    <resheader name="version">2.0</resheader>
+    <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+    <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+    <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
+    <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+    <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+        <value>[base64 mime encoded serialized .NET Framework object]</value>
+    </data>
+    <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+        <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
+        <comment>This is a comment</comment>
+    </data>
+                
+    There are any number of "resheader" rows that contain simple 
+    name/value pairs.
+    
+    Each data row contains a name, and value. The row also contains a 
+    type or mimetype. Type corresponds to a .NET class that support 
+    text/value conversion through the TypeConverter architecture. 
+    Classes that don't support this are serialized and stored with the 
+    mimetype set.
+    
+    The mimetype is used for serialized objects, and tells the 
+    ResXResourceReader how to depersist the object. This is currently not 
+    extensible. For a given mimetype the value must be set accordingly:
+    
+    Note - application/x-microsoft.net.object.binary.base64 is the format 
+    that the ResXResourceWriter will generate, however the reader can 
+    read any of the formats listed below.
+    
+    mimetype: application/x-microsoft.net.object.binary.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
+            : and then encoded with base64 encoding.
+    
+    mimetype: application/x-microsoft.net.object.soap.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+            : and then encoded with base64 encoding.
+
+    mimetype: application/x-microsoft.net.object.bytearray.base64
+    value   : The object must be serialized into a byte array 
+            : using a System.ComponentModel.TypeConverter
+            : and then encoded with base64 encoding.
+    -->
+  <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+    <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
+    <xsd:element name="root" msdata:IsDataSet="true">
+      <xsd:complexType>
+        <xsd:choice maxOccurs="unbounded">
+          <xsd:element name="metadata">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" />
+              </xsd:sequence>
+              <xsd:attribute name="name" use="required" type="xsd:string" />
+              <xsd:attribute name="type" type="xsd:string" />
+              <xsd:attribute name="mimetype" type="xsd:string" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="assembly">
+            <xsd:complexType>
+              <xsd:attribute name="alias" type="xsd:string" />
+              <xsd:attribute name="name" type="xsd:string" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="data">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+                <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
+              <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+              <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="resheader">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" />
+            </xsd:complexType>
+          </xsd:element>
+        </xsd:choice>
+      </xsd:complexType>
+    </xsd:element>
+  </xsd:schema>
+  <resheader name="resmimetype">
+    <value>text/microsoft-resx</value>
+  </resheader>
+  <resheader name="version">
+    <value>2.0</value>
+  </resheader>
+  <resheader name="reader">
+    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <resheader name="writer">
+    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <assembly alias="System.Drawing" name="System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
+  <data name="$this.Icon" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+    <value>
+        AAABAAEAMDAAAAEAIACoJQAAFgAAACgAAAAwAAAAYAAAAAEAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAqbEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAqLEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAKmyAAAAAAAAAAAAAAAAAACpsgABqLEACqmyABGpsgAWqbIAGaixABqosQAaqbIAGaix
+        ABapsgARqLEAC6myAAIAAAAAAAAAAAAAAACpsgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAACpsgAAAAAAAAAAAAAAAAAAqLEAE6ixACuosQBUqLEAkqmyAMGpsgDlqbIA/aix
+        AP+osQD/qLEA/qmyAOiosQDFqbIAl6myAFqpsgAuqbIAFQAAAAAAAAAAAAAAAKixAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAqbIAAKixAAAAAAAAAAAAAKmyAB6psgBUqbIApKmyAOupsgD/qLEA/6my
+        AP+osQD/qLEA/6ixAP+psgD/qLEA/6ixAP+osQD/qbIA/6ixAP+osQDyqLEAqqmyAFmpsgAiAAAAAAAA
+        AACpsgAAqLEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACpsgAAAAAAAAAAAACosQANqbIAXKmyALiosQD/qLEA/6my
+        AP+osQD+qLEA/qmyAP+psgD/qbIA/6myAP+psgD/qbIA/6myAP+psgD/qLEA/qixAP6psgD/qLEA/6my
+        AP+osQC/qbIAZKixABEAAAAAAAAAAKmyAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKmyAAAAAAAAAAAAAKixACuosQCjqbIA9aix
+        AP+psgD/qLEA/qmyAP+psgD/qbIA/6myAP+psgD/qbIA/6myAP+psgD/qbIA/6myAP+psgD/qbIA/6my
+        AP+psgD/qbIA/qmyAP+psgD/qbIA+aixAKupsgA0AAAAAAAAAACpsgAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAqbIARqix
+        ANWosQD/qbIA/6ixAP+osQD+qbIA/6myAP+psgD/qbIA/6myAP+psgD/qbIA/6myAP+psgD/qbIA/6my
+        AP+psgD/qbIA/6myAP+psgD/qbIA/6ixAP6osQD+qbIA/6myAP+osQDcqbIAUwAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAqbIAAAAA
+        AACosQBVqLEA76myAP+psgD/qLEA/qmyAP+psgD/qbIA/6myAP+psgD/qbIA/6myAP+psgD/qbIA/6my
+        AP+psgD/qbIA/6myAP+psgD/qbIA/6myAP+psgD/qbIA/6myAP+psgD/qLEA/qmyAP+psgD/qLEA86my
+        AGUAAAAAqbIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AACpsgAAAAAAAKmyAE6psgD8qbIA/6myAP+osQD+qbIA/6myAP+psgD/qbIA/6myAP+psgD/qbIA/6my
+        AP+psgD/qbIA/6myAP+psgD/qbIA/6myAP+psgD/qbIA/6myAP+psgD/qbIA/6myAP+psgD/qbIA/6ix
+        AP6psgD+qLEA/6myAP6psgBhAAAAAKixAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAKixAAAAAAAAqbIANKixAP2osQD/qLEA/6ixAP6psgD/qbIA/6myAP+psgD/qbIA/6my
+        AP+psgD/qbIA/6myAP+psgD/qbIA/6myAP+psgD/qbIA/6myAP+psgD/qbIA/6myAP+psgD/qbIA/6my
+        AP+psgD/qbIA/6myAP+psgD+qLEA/qmyAP+osQD/qLEARwAAAACpsgAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAqLEAAAAAAACosQASqbIA6KmyAP+psgD+qbIA/6myAP+psgD/qbIA/6my
+        AP+psgD/qbIA/6myAP+psgD/qbIA/6myAP+psgD/qbIA/6myAP+psgD/qbIA/6myAP+psgD/qbIA/6my
+        AP+psgD/qbIA/6myAP+psgD/qbIA/6myAP+psgD/qbIA/6myAP6psgD/qbIA8qixAB8AAAAAqLEAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACosQAAAAAAAAAAAACpsgCvqbIA/qmyAP6psgD/qLEA/6ix
+        AP+osQD/qLEA/6ixAP+osQD/qLEA/6ixAP+osQD/qLEA/6ixAP+osQD/qbIA/6myAP+psgD/qbIA/6ix
+        AP+osQD/qLEA/6ixAP+osQD/qLEA/6ixAP+osQD/qLEA/6ixAP+osQD/qLEA/6myAP+psgD+qbIA/qix
+        AMGosgAAAAAAAKixAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACosQAAAAAAAKixAFuosQD1qLEA/6my
+        AP+osQD/q7QI/7a9J/+3vyv/t78r/7i/Lf+stAn/rbYN/7jALv+3viv/t78r/7i/LP+stAn/qLEA/6my
+        AP+psgD/qLEA/6u0B/+3vin/t78r/7e/K/+4vy7/r7cS/6u0Bv+4vy3/t78r/7e/K/+2vin/rLQJ/6ix
+        AP+psgD/qbIA/6ixAPepsgBuAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKmyAAAAAAAAqbIADqmy
+        AMSosQD/qbIA/6myAP+osQD/t78q/+zuxv/09N3/8/Ta//b35f+5wC//tbwk//Lz2P/z9Nz/8/Tb//X1
+        4v/GzFj/qbIC/6ixAP+osQD/qbIA/8PIS//z9N3/8/Tb//P02//09d7/ucEy/7S8Iv/39+b/8/Ta//T0
+        3f/v8M//uMAv/6ixAP+psgD/qbIA/qmyAP+psgDPqLEAGQAAAACpsgAAAAAAAAAAAAAAAAAAAAAAAKix
+        AAAAAAAAqLEAY6myAPKosQD/qLEA/qmyAP+osQD/usEz//j57P////////////////+9xDr/qbIB/97i
+        nf/////////////////w8tX/sLkX/6ixAP+osQD/rrcQ/+vtxP/////////////////m6LT/qrMD/7e+
+        Kf/////////////////8/Pb/u8M4/6exAP+psgD/qLEA/qixAP+osQD3qLEAcgAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAACpsgALqLEAqqmyAP+psgD/qbIA/6myAP+osQD/ucEy//f45///////////////
+        //+9wzj/qLEA/7e+Kv/5+e3/////////////////ztRx/6myAP+psgD/yc5e//////////////////39
+        +f+6wjX/qLEA/7e+Kf/////////////////6+/L/u8I3/6ixAP+psgD/qbIA/6ixAP6osQD/qbIAtqmy
+        ABQAAAAAAAAAAAAAAAAAAAAAqLEAAAAAAACosQA7qLEA3amyAP+osQD+qbIA/6myAP+osQD/ucEy//f4
+        5/////////////////+9wzj/qLEA/6qzBf/T13z///////7+/v//////+frw/7C4FP+ttQr/9fbi////
+        ///+/v7//////9ndkP+rtAj/qLEA/7e+Kf/////////////////6+/L/u8I3/6ixAP+psgD/qbIA/6ix
+        AP6psgD/qLEA6KmyAEUAAAAAqbIAAAAAAAAAAAAAAAAAAAAAAACpsgBlqbIA/6myAP+psgD/qbIA/6my
+        AP+osQD/ucEy//f45/////////////////+9wzj/qLEA/6ixAP+3vyv/8fLW///////+/v7//////9rd
+        kP/S1nj/////////////////9vfk/7vCNf+osQD/qLEA/7e+Kf/////////////////6+/L/u8I3/6ix
+        AP+psgD/qbIA/6myAP+psgD/qbIA/6myAHMAAAAAAAAAAAAAAAAAAAAAAAAAAKmyAAqosQCTqLEA/6ix
+        AP+psgD/qbIA/6myAP+osQD/ucEy//f45/////////////////+9wzj/qLEA/6ixAP+osQD/0NV1////
+        //////////////z9+f/7+/P/////////////////1tqE/6qzA/+osQD/qLEA/7e+Kf//////////////
+        ///6+/L/u8I3/6ixAP+psgD/qbIA/6myAP+osQD+qbIA/6ixAKKosQARAAAAAAAAAAAAAAAAAAAAAKmy
+        AByosQC5qbIA/6myAP+psgD/qbIA/6myAP+osQD/ucEy//f45/////////////////+9wzj/qLEA/6my
+        AP+nsAD/tr0n/+zuyP/////////////+/////////v7+///////w8tX/usEz/6ewAP+psgD/qLEA/7e+
+        Kf/////////////////6+/L/u8I3/6ixAP+psgD/qbIA/6myAP+psgD/qbIA/6ixAMqosQAkAAAAAAAA
+        AAAAAAAAAAAAAKixACqosQDYqbIA/6myAP+psgD/qbIA/6myAP+osQD/ucEy//f45///////////////
+        //+9wzj/qLEA/6myAP+psQD/pa4A/9DVdP/9/fn///////7+/v/+/v7///////7+/v/V2oX/prAA/6ix
+        AP+psgD/qLEA/7e+Kf/////////////////6+/L/u8I3/6ixAP+psgD/qbIA/6myAP+psgD/qbIA/6my
+        AOipsgAyAAAAAAAAAAAAAAAAAAAAAKixADSosQDtqLEA/6myAP+psgD/qbIA/6myAP+osQD/ucEy//f4
+        5/////////////////+9wzj/qLEA/6myAP+psgD/p7AA/7C5Fv/r7cb//////////////////////+7w
+        zv+1vSX/p7AA/6myAP+psgD/qLEA/7e+Kf/////////////////6+/L/u8I3/6ixAP+psgD/qbIA/6my
+        AP+psgD/qLEA/6ixAPypsgA7AAAAAAAAAAAAAAAAAAAAAKmyADqosQD6qbIA/6myAP+psgD/qbIA/6my
+        AP+osQD/ucEy//f45/////////////////+9wzj/qLEA/6myAP+psgD/qbIA/6StAP/L0Gb/+/z2////
+        /////////v79/93gm/+irAD/qbIA/6myAP+psgD/qLEA/7e+Kf/////////////////6+/L/u8I3/6ix
+        AP+psgD/qbIA/6myAP+psgD/qbIA/6ixAP+psgBCAAAAAAAAAAAAAAAAAAAAAKixADyosQD9qbIA/6my
+        AP+psgD/qbIA/6myAP+osQD/ucEy//f45/////////////////+9wzj/qLEA/6myAP+psgD/qLEA/6ew
+        AP+psgH/6+3F//7+/v///////////+jqvP+utxD/p7AA/6myAP+psgD/qLEA/7e+Kf//////////////
+        ///6+/L/u8I3/6ixAP+psgD/qbIA/6myAP+psgD/qbIA/qixAP+psgBFAAAAAAAAAAAAAAAAAAAAAKmy
+        ADqosQD6qLEA/6myAP+psgD/qbIA/6myAP+osQD/ucEy//f45/////////////////+9wzj/qLEA/6my
+        AP+psgD/qLEA/663Ef+osQD/wMZF//7+/P/+/v7///////v89v/O023/pq8A/6ixAP+psgD/qLEA/7e+
+        Kf/////////////////6+/L/u8I3/6ixAP+psgD/qbIA/6myAP+psgD/qbIA/6ixAP+psgBDAAAAAAAA
+        AAAAAAAAAAAAAKixADWosQDvqLEA/6myAP+psgD/qbIA/6myAP+osQD/ucEy//f45///////////////
+        //+9wzj/qLEA/6myAP+nsQD/srob/9vflv+4wC7/pq8A/+Tnsf///////v7+///////r7cX/tLwh/6ew
+        AP+psgD/qLEA/7e+Kf/////////////////6+/L/u8I3/6ixAP+psgD/qbIA/6myAP+psgD/qLEA/6ix
+        AP2osQA8AAAAAAAAAAAAAAAAAAAAAKmyACupsgDZqLEA/6myAP+psgD/qbIA/6myAP+osQD/ucEy//f4
+        5/////////////////+9wzj/qLEA/6ixAP+nsAD/ys9h///////X24n/qrME/7W8Iv//////////////
+        ////////z9Nw/6ixAP+osQD/qLEA/7e+Kf/////////////////6+/L/u8I3/6ixAP+psgD/qbIA/6my
+        AP+psgD/qLEA/6myAOqpsgAzAAAAAAAAAAAAAAAAAAAAAKixAB2osQC8qLEA/6myAP+psgD/qbIA/6my
+        AP+osQD/ucEy//f45/////////////////+9wzj/qLEA/6ixAP+zux//6uzD///////9/Pj/tr0m/6ix
+        AP/Y3Iz///////7+/v//////8PLU/7W9Jf+osQD/qLEA/7e+Kf/////////////////6+/L/u8I3/6ix
+        AP+psgD/qbIA/6myAP+psgD/qLEA/6ixAMuosQAkAAAAAAAAAAAAAAAAAAAAAKixAAuosQCVqLEA/6ix
+        AP6psgD/qbIA/6myAP+osQD/ucEy//f45/////////////////+8wzj/qLEA/6myAv/L0GP/////////
+        ////////3+Ki/6qzBP+vtxH/+vvy/////////////////9HVdf+qswX/qLEA/7a+KP//////////////
+        ///6+/L/u8I3/6ixAP+psgD/qbIA/6myAP+osQD+qLEA/6ixAKWpsgASAAAAAAAAAAAAAAAAAAAAAAAA
+        AACosQBpqLEA/6ixAP+psgD/qbIA/6myAP+osQD/ucEy//f45//////////////////HzVr/t74p/77F
+        Pv/z89r/////////////////2d2O/6qzBP+psgL/z9Nu//////////////////j56v+/xkH/t74p/8PK
+        Tf/////////////////6+/L/u8I3/6ixAP+psgD/qbIA/6myAP+psgD/qLEA/6ixAHYAAAAAAAAAAAAA
+        AAAAAAAAqLEAAAAAAACpsgA+qLEA4KixAP+psgD+qbIA/6myAP+osQD/usEy//f46P////////////7+
+        /v///////////////////////v7+///////3+en/srsc/6ixAP+osQD/sLcU//Hz1////////v7+////
+        ///////////////////+/v7////////////6+/L/u8I3/6exAP+psgD/qbIA/6myAP6psgD/qLEA7Kix
+        AEoAAAAAqbIAAAAAAAAAAAAAAAAAAAAAAACosQAOqbIAramyAP+osQD/qbIA/6myAP+osQD/ucAx//b3
+        5v///////v7+///////////////////////+/v7////////////P1HH/qrME/6ixAP+osQD/qbIC/8jO
+        Xf////////////7+/v///////////////////////v7+///////6+/H/u8I2/6ixAP+psgD/qbIA/6my
+        AP+osQD/qbIAuqmyABkAAAAAAAAAAAAAAAAAAAAAAAAAAKmyAAAAAAAAqbIAaamyAPWosQD/qbIA/qmy
+        AP+osQD/sroc/+jqvP///////////////////////////////////////////+3vyv+zux7/qLEA/6my
+        AP+psgD/qLEA/7G5GP/n6rr////////////////////////////////////////////t78v/tLwj/6ix
+        AP+psgD/qbIA/qmyAP+osQD6qLEAeAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKmyAAAAAAAAqbIAFamy
+        AMiosQD/qLEA/6myAP+osQD/qbIA/77FP//f46H/5Oev/+Pnrv/j567/4+eu/+Pnrv/k56//3+Oi/77F
+        QP+psgD/qLEA/6myAP+psgD/qLEA/6ixAP+8wzj/3uKe/+Tnr//j567/4+eu/+Pnrv/j567/5Oev/+Hk
+        pf/Bx0j/qrIC/6ixAP+psgD/qbIA/qmyAP+psgDTqLEAIQAAAACosQAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AACosQAAAAAAAKixAGSosQD3qLEA/6myAP+psgD/qLEA/6ewAP+stQr/sLkW/7C5Fv+wuRb/sLkW/7C5
+        Fv+wuRb/rLUK/6ewAP+osQD/qbIA/6myAP+psgD/qbIA/6ixAP+nsAD/rLQJ/7C5Fv+wuRb/sLkW/7C5
+        Fv+wuRb/sLkW/621DP+nsAD/qLEA/6myAP+psgD/qLEA/6ixAPmpsgB3AAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAACpsgAAAAAAAAAAAACosQC2qLEA/6myAP6psgD/qbIA/6ixAP+osQD/qLEA/6ix
+        AP+osQD/qLEA/6ixAP+osQD/qLEA/6ixAP+psgD/qbIA/6myAP+psgD/qbIA/6myAP+osQD/qLEA/6ix
+        AP+osQD/qLEA/6ixAP+osQD/qLEA/6ixAP+osQD/qbIA/6myAP+osQD+qLEA/6myAMaosQAGAAAAAKix
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAqbIAAAAAAACpsgAbqLEA7aixAP+osQD+qbIA/6my
+        AP+psgD/qbIA/6myAP+psgD/qbIA/6myAP+psgD/qbIA/6myAP+psgD/qbIA/6myAP+psgD/qbIA/6my
+        AP+psgD/qbIA/6myAP+psgD/qbIA/6myAP+psgD/qbIA/6myAP+psgD/qbIA/6ixAP6psgD/qLEA9aix
+        ACoAAAAAqLEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAqLEAPKix
+        AP+osQD/qLEA/qmyAP+psgD/qbIA/6myAP+psgD/qbIA/6myAP+psgD/qbIA/6myAP+psgD/qbIA/6my
+        AP+psgD/qbIA/6myAP+psgD/qbIA/6myAP+psgD/qbIA/6myAP+psgD/qbIA/6myAP+psgD/qLEA/qix
+        AP6osQD/qLEATgAAAAAAAAAAqLEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AACosQAAAAAAAKmyAFWosQD/qbIA/6ixAP+psgD+qbIA/6myAP+psgD/qbIA/6myAP+psgD/qbIA/6my
+        AP+psgD/qbIA/6myAP+psgD/qbIA/6myAP+psgD/qbIA/6myAP+psgD/qbIA/6myAP+psgD/qbIA/6my
+        AP6osQD/qbIA/6ixAP+psgBqAAAAAKixAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAqLEAAAAAAACpsgBbqLEA+qixAP+psgD/qLEA/qmyAP+psgD/qbIA/6my
+        AP+psgD/qbIA/6myAP+psgD/qbIA/6myAP+psgD/qbIA/6myAP+psgD/qbIA/6myAP+psgD/qbIA/6my
+        AP+psgD/qLEA/qixAP+osQD/qbIA/qmyAG4AAAAAqbIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAqbIAT6ixAOKosQD/qLEA/6ix
+        AP+psgD+qbIA/6myAP+psgD/qbIA/6myAP+psgD/qbIA/6myAP+psgD/qbIA/6myAP+psgD/qbIA/6my
+        AP+psgD/qbIA/6myAP6osQD/qLEA/6ixAP+osQDpqbIAXAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKixAAAAAAAAAAAAAKix
+        ADGosQC0qLEA96ixAP+osQD/qbIA/qmyAP+psgD/qbIA/6myAP+psgD/qbIA/6myAP+psgD/qbIA/6my
+        AP+psgD/qbIA/6myAP+psgD/qbIA/qmyAP+osQD/qLEA+amyALypsgA8AAAAAAAAAACosQAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AACpsgAAAAAAAAAAAACosQAOqbIAcKixAMWosQD/qbIA/6myAP+osQD+qbIA/qmyAP+psgD/qbIA/6my
+        AP+psgD/qbIA/6myAP+psgD/qbIA/qmyAP6osQD/qbIA/6myAP+osQDKqLEAeaixABMAAAAAAAAAAKix
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAqLEAAKixAAAAAAAAAAAAAKmyACapsgBrqbIAsKixAO2osQD/qLEA/6ix
+        AP+osQD/qLEA/6ixAP+osQD/qLEA/6ixAP+osQD/qLEA/6ixAP+osQDwqbIAtqixAHGosQArAAAAAAAA
+        AACosQAAqbIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACpsgAAAAAAAAAAAAAAAAAAqbIAGamy
+        AECosQBpqLEAnamyAMeosQDlqLEA+qixAP+psgD/qbIA/KmyAOipsgDKqLEAoaixAG6psgBCqbIAHQAA
+        AAAAAAAAAAAAAKixAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKmy
+        AAAAAAAAAAAAAAAAAACosQAAqLEAEamyAB6psgAoqbIAL6ixADKpsgAyqLEAL6ixACmpsgAfqLEAEqmy
+        AAEAAAAAAAAAAAAAAACosQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAqLEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAqLEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD///////8AAP///////wAA///gB///
+        AAD//wAA//8AAP/8AAA//wAA//AAAA//AAD/4AAAB/8AAP/AAAAD/wAA/4AAAAH/AAD/AAAAAP8AAP4A
+        AAAAfwAA/AAAAAA/AAD8AAAAAD8AAPgAAAAAHwAA+AAAAAAfAADwAAAAAA8AAPAAAAAADwAA8AAAAAAP
+        AADgAAAAAAcAAOAAAAAABwAA4AAAAAAHAADgAAAAAAcAAOAAAAAABwAA4AAAAAAHAADgAAAAAAcAAOAA
+        AAAABwAA4AAAAAAHAADgAAAAAAcAAOAAAAAABwAA8AAAAAAPAADwAAAAAA8AAPAAAAAADwAA+AAAAAAf
+        AAD4AAAAAB8AAPwAAAAAPwAA/AAAAAA/AAD+AAAAAH8AAP8AAAAA/wAA/4AAAAH/AAD/wAAAA/8AAP/g
+        AAAH/wAA//AAAA//AAD//AAAP/8AAP//AAD//wAA///gB///AAD///////8AAP///////wAA////////
+        AAA=
+</value>
+  </data>
+</root>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HspGuiSourceV301/HSPGui/View/StatusForm.Designer.cs	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,62 @@
+namespace HealthSensorPlatform.View
+{
+    partial class StatusForm
+    {
+        /// <summary>
+        /// Required designer variable.
+        /// </summary>
+        private System.ComponentModel.IContainer components = null;
+
+        /// <summary>
+        /// Clean up any resources being used.
+        /// </summary>
+        /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
+        protected override void Dispose(bool disposing)
+        {
+            if (disposing && (components != null))
+            {
+                components.Dispose();
+            }
+            base.Dispose(disposing);
+        }
+
+        #region Windows Form Designer generated code
+
+        /// <summary>
+        /// Required method for Designer support - do not modify
+        /// the contents of this method with the code editor.
+        /// </summary>
+        private void InitializeComponent()
+        {
+            System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(StatusForm));
+            this.label1 = new System.Windows.Forms.Label();
+            this.SuspendLayout();
+            // 
+            // label1
+            // 
+            this.label1.Font = new System.Drawing.Font("Arial", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+            this.label1.Location = new System.Drawing.Point(12, 9);
+            this.label1.Name = "label1";
+            this.label1.Size = new System.Drawing.Size(260, 102);
+            this.label1.TabIndex = 0;
+            this.label1.Text = "Erasing flash data and writing mission parameters, please wait...";
+            // 
+            // StatusForm
+            // 
+            this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
+            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+            this.BackColor = System.Drawing.Color.White;
+            this.ClientSize = new System.Drawing.Size(284, 120);
+            this.Controls.Add(this.label1);
+            this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon")));
+            this.Name = "StatusForm";
+            this.Text = "Write Mission";
+            this.ResumeLayout(false);
+
+        }
+
+        #endregion
+
+        private System.Windows.Forms.Label label1;
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HspGuiSourceV301/HSPGui/View/StatusForm.cs	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,69 @@
+/*******************************************************************************
+* Copyright (C) 2016 Maxim Integrated Products, Inc., All rights Reserved.
+* 
+* This software is protected by copyright laws of the United States and
+* of foreign countries. This material may also be protected by patent laws
+* and technology transfer regulations of the United States and of foreign
+* countries. This software is furnished under a license agreement and/or a
+* nondisclosure agreement and may only be used or reproduced in accordance
+* with the terms of those agreements. Dissemination of this information to
+* any party or parties not specified in the license agreement and/or
+* nondisclosure agreement is expressly prohibited.
+*
+* The above copyright notice and this permission notice shall be included
+* in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+* OTHER DEALINGS IN THE SOFTWARE.
+*
+* Except as contained in this notice, the name of Maxim Integrated
+* Products, Inc. shall not be used except as stated in the Maxim Integrated
+* Products, Inc. Branding Policy.
+*
+* The mere transfer of this software does not imply any licenses
+* of trade secrets, proprietary technology, copyrights, patents,
+* trademarks, maskwork rights, or any other form of intellectual
+* property whatsoever. Maxim Integrated Products, Inc. retains all
+* ownership rights.
+*******************************************************************************
+*/
+
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Data;
+using System.Drawing;
+using System.Linq;
+using System.Text;
+using System.Windows.Forms;
+
+namespace HealthSensorPlatform.View
+{
+    public partial class StatusForm : Form
+    {
+        public StatusForm()
+        {
+            InitializeComponent();
+
+            this.CenterToParent();
+            this.ControlBox = false;
+        }
+
+        public string Message
+        {
+            get
+            {
+                return label1.Text;
+            }
+            set
+            {
+                label1.Text = value;
+            }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HspGuiSourceV301/HSPGui/View/StatusForm.resx	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,287 @@
+<?xml version="1.0" encoding="utf-8"?>
+<root>
+  <!-- 
+    Microsoft ResX Schema 
+    
+    Version 2.0
+    
+    The primary goals of this format is to allow a simple XML format 
+    that is mostly human readable. The generation and parsing of the 
+    various data types are done through the TypeConverter classes 
+    associated with the data types.
+    
+    Example:
+    
+    ... ado.net/XML headers & schema ...
+    <resheader name="resmimetype">text/microsoft-resx</resheader>
+    <resheader name="version">2.0</resheader>
+    <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+    <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+    <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
+    <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+    <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+        <value>[base64 mime encoded serialized .NET Framework object]</value>
+    </data>
+    <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+        <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
+        <comment>This is a comment</comment>
+    </data>
+                
+    There are any number of "resheader" rows that contain simple 
+    name/value pairs.
+    
+    Each data row contains a name, and value. The row also contains a 
+    type or mimetype. Type corresponds to a .NET class that support 
+    text/value conversion through the TypeConverter architecture. 
+    Classes that don't support this are serialized and stored with the 
+    mimetype set.
+    
+    The mimetype is used for serialized objects, and tells the 
+    ResXResourceReader how to depersist the object. This is currently not 
+    extensible. For a given mimetype the value must be set accordingly:
+    
+    Note - application/x-microsoft.net.object.binary.base64 is the format 
+    that the ResXResourceWriter will generate, however the reader can 
+    read any of the formats listed below.
+    
+    mimetype: application/x-microsoft.net.object.binary.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
+            : and then encoded with base64 encoding.
+    
+    mimetype: application/x-microsoft.net.object.soap.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+            : and then encoded with base64 encoding.
+
+    mimetype: application/x-microsoft.net.object.bytearray.base64
+    value   : The object must be serialized into a byte array 
+            : using a System.ComponentModel.TypeConverter
+            : and then encoded with base64 encoding.
+    -->
+  <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+    <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
+    <xsd:element name="root" msdata:IsDataSet="true">
+      <xsd:complexType>
+        <xsd:choice maxOccurs="unbounded">
+          <xsd:element name="metadata">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" />
+              </xsd:sequence>
+              <xsd:attribute name="name" use="required" type="xsd:string" />
+              <xsd:attribute name="type" type="xsd:string" />
+              <xsd:attribute name="mimetype" type="xsd:string" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="assembly">
+            <xsd:complexType>
+              <xsd:attribute name="alias" type="xsd:string" />
+              <xsd:attribute name="name" type="xsd:string" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="data">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+                <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
+              <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+              <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="resheader">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" />
+            </xsd:complexType>
+          </xsd:element>
+        </xsd:choice>
+      </xsd:complexType>
+    </xsd:element>
+  </xsd:schema>
+  <resheader name="resmimetype">
+    <value>text/microsoft-resx</value>
+  </resheader>
+  <resheader name="version">
+    <value>2.0</value>
+  </resheader>
+  <resheader name="reader">
+    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <resheader name="writer">
+    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <assembly alias="System.Drawing" name="System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
+  <data name="$this.Icon" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+    <value>
+        AAABAAEAMDAAAAEAIACoJQAAFgAAACgAAAAwAAAAYAAAAAEAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAqbEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAqLEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAKmyAAAAAAAAAAAAAAAAAACpsgABqLEACqmyABGpsgAWqbIAGaixABqosQAaqbIAGaix
+        ABapsgARqLEAC6myAAIAAAAAAAAAAAAAAACpsgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAACpsgAAAAAAAAAAAAAAAAAAqLEAE6ixACuosQBUqLEAkqmyAMGpsgDlqbIA/aix
+        AP+osQD/qLEA/qmyAOiosQDFqbIAl6myAFqpsgAuqbIAFQAAAAAAAAAAAAAAAKixAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAqbIAAKixAAAAAAAAAAAAAKmyAB6psgBUqbIApKmyAOupsgD/qLEA/6my
+        AP+osQD/qLEA/6ixAP+psgD/qLEA/6ixAP+osQD/qbIA/6ixAP+osQDyqLEAqqmyAFmpsgAiAAAAAAAA
+        AACpsgAAqLEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACpsgAAAAAAAAAAAACosQANqbIAXKmyALiosQD/qLEA/6my
+        AP+osQD+qLEA/qmyAP+psgD/qbIA/6myAP+psgD/qbIA/6myAP+psgD/qLEA/qixAP6psgD/qLEA/6my
+        AP+osQC/qbIAZKixABEAAAAAAAAAAKmyAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKmyAAAAAAAAAAAAAKixACuosQCjqbIA9aix
+        AP+psgD/qLEA/qmyAP+psgD/qbIA/6myAP+psgD/qbIA/6myAP+psgD/qbIA/6myAP+psgD/qbIA/6my
+        AP+psgD/qbIA/qmyAP+psgD/qbIA+aixAKupsgA0AAAAAAAAAACpsgAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAqbIARqix
+        ANWosQD/qbIA/6ixAP+osQD+qbIA/6myAP+psgD/qbIA/6myAP+psgD/qbIA/6myAP+psgD/qbIA/6my
+        AP+psgD/qbIA/6myAP+psgD/qbIA/6ixAP6osQD+qbIA/6myAP+osQDcqbIAUwAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAqbIAAAAA
+        AACosQBVqLEA76myAP+psgD/qLEA/qmyAP+psgD/qbIA/6myAP+psgD/qbIA/6myAP+psgD/qbIA/6my
+        AP+psgD/qbIA/6myAP+psgD/qbIA/6myAP+psgD/qbIA/6myAP+psgD/qLEA/qmyAP+psgD/qLEA86my
+        AGUAAAAAqbIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AACpsgAAAAAAAKmyAE6psgD8qbIA/6myAP+osQD+qbIA/6myAP+psgD/qbIA/6myAP+psgD/qbIA/6my
+        AP+psgD/qbIA/6myAP+psgD/qbIA/6myAP+psgD/qbIA/6myAP+psgD/qbIA/6myAP+psgD/qbIA/6ix
+        AP6psgD+qLEA/6myAP6psgBhAAAAAKixAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAKixAAAAAAAAqbIANKixAP2osQD/qLEA/6ixAP6psgD/qbIA/6myAP+psgD/qbIA/6my
+        AP+psgD/qbIA/6myAP+psgD/qbIA/6myAP+psgD/qbIA/6myAP+psgD/qbIA/6myAP+psgD/qbIA/6my
+        AP+psgD/qbIA/6myAP+psgD+qLEA/qmyAP+osQD/qLEARwAAAACpsgAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAqLEAAAAAAACosQASqbIA6KmyAP+psgD+qbIA/6myAP+psgD/qbIA/6my
+        AP+psgD/qbIA/6myAP+psgD/qbIA/6myAP+psgD/qbIA/6myAP+psgD/qbIA/6myAP+psgD/qbIA/6my
+        AP+psgD/qbIA/6myAP+psgD/qbIA/6myAP+psgD/qbIA/6myAP6psgD/qbIA8qixAB8AAAAAqLEAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACosQAAAAAAAAAAAACpsgCvqbIA/qmyAP6psgD/qLEA/6ix
+        AP+osQD/qLEA/6ixAP+osQD/qLEA/6ixAP+osQD/qLEA/6ixAP+osQD/qbIA/6myAP+psgD/qbIA/6ix
+        AP+osQD/qLEA/6ixAP+osQD/qLEA/6ixAP+osQD/qLEA/6ixAP+osQD/qLEA/6myAP+psgD+qbIA/qix
+        AMGosgAAAAAAAKixAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACosQAAAAAAAKixAFuosQD1qLEA/6my
+        AP+osQD/q7QI/7a9J/+3vyv/t78r/7i/Lf+stAn/rbYN/7jALv+3viv/t78r/7i/LP+stAn/qLEA/6my
+        AP+psgD/qLEA/6u0B/+3vin/t78r/7e/K/+4vy7/r7cS/6u0Bv+4vy3/t78r/7e/K/+2vin/rLQJ/6ix
+        AP+psgD/qbIA/6ixAPepsgBuAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKmyAAAAAAAAqbIADqmy
+        AMSosQD/qbIA/6myAP+osQD/t78q/+zuxv/09N3/8/Ta//b35f+5wC//tbwk//Lz2P/z9Nz/8/Tb//X1
+        4v/GzFj/qbIC/6ixAP+osQD/qbIA/8PIS//z9N3/8/Tb//P02//09d7/ucEy/7S8Iv/39+b/8/Ta//T0
+        3f/v8M//uMAv/6ixAP+psgD/qbIA/qmyAP+psgDPqLEAGQAAAACpsgAAAAAAAAAAAAAAAAAAAAAAAKix
+        AAAAAAAAqLEAY6myAPKosQD/qLEA/qmyAP+osQD/usEz//j57P////////////////+9xDr/qbIB/97i
+        nf/////////////////w8tX/sLkX/6ixAP+osQD/rrcQ/+vtxP/////////////////m6LT/qrMD/7e+
+        Kf/////////////////8/Pb/u8M4/6exAP+psgD/qLEA/qixAP+osQD3qLEAcgAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAACpsgALqLEAqqmyAP+psgD/qbIA/6myAP+osQD/ucEy//f45///////////////
+        //+9wzj/qLEA/7e+Kv/5+e3/////////////////ztRx/6myAP+psgD/yc5e//////////////////39
+        +f+6wjX/qLEA/7e+Kf/////////////////6+/L/u8I3/6ixAP+psgD/qbIA/6ixAP6osQD/qbIAtqmy
+        ABQAAAAAAAAAAAAAAAAAAAAAqLEAAAAAAACosQA7qLEA3amyAP+osQD+qbIA/6myAP+osQD/ucEy//f4
+        5/////////////////+9wzj/qLEA/6qzBf/T13z///////7+/v//////+frw/7C4FP+ttQr/9fbi////
+        ///+/v7//////9ndkP+rtAj/qLEA/7e+Kf/////////////////6+/L/u8I3/6ixAP+psgD/qbIA/6ix
+        AP6psgD/qLEA6KmyAEUAAAAAqbIAAAAAAAAAAAAAAAAAAAAAAACpsgBlqbIA/6myAP+psgD/qbIA/6my
+        AP+osQD/ucEy//f45/////////////////+9wzj/qLEA/6ixAP+3vyv/8fLW///////+/v7//////9rd
+        kP/S1nj/////////////////9vfk/7vCNf+osQD/qLEA/7e+Kf/////////////////6+/L/u8I3/6ix
+        AP+psgD/qbIA/6myAP+psgD/qbIA/6myAHMAAAAAAAAAAAAAAAAAAAAAAAAAAKmyAAqosQCTqLEA/6ix
+        AP+psgD/qbIA/6myAP+osQD/ucEy//f45/////////////////+9wzj/qLEA/6ixAP+osQD/0NV1////
+        //////////////z9+f/7+/P/////////////////1tqE/6qzA/+osQD/qLEA/7e+Kf//////////////
+        ///6+/L/u8I3/6ixAP+psgD/qbIA/6myAP+osQD+qbIA/6ixAKKosQARAAAAAAAAAAAAAAAAAAAAAKmy
+        AByosQC5qbIA/6myAP+psgD/qbIA/6myAP+osQD/ucEy//f45/////////////////+9wzj/qLEA/6my
+        AP+nsAD/tr0n/+zuyP/////////////+/////////v7+///////w8tX/usEz/6ewAP+psgD/qLEA/7e+
+        Kf/////////////////6+/L/u8I3/6ixAP+psgD/qbIA/6myAP+psgD/qbIA/6ixAMqosQAkAAAAAAAA
+        AAAAAAAAAAAAAKixACqosQDYqbIA/6myAP+psgD/qbIA/6myAP+osQD/ucEy//f45///////////////
+        //+9wzj/qLEA/6myAP+psQD/pa4A/9DVdP/9/fn///////7+/v/+/v7///////7+/v/V2oX/prAA/6ix
+        AP+psgD/qLEA/7e+Kf/////////////////6+/L/u8I3/6ixAP+psgD/qbIA/6myAP+psgD/qbIA/6my
+        AOipsgAyAAAAAAAAAAAAAAAAAAAAAKixADSosQDtqLEA/6myAP+psgD/qbIA/6myAP+osQD/ucEy//f4
+        5/////////////////+9wzj/qLEA/6myAP+psgD/p7AA/7C5Fv/r7cb//////////////////////+7w
+        zv+1vSX/p7AA/6myAP+psgD/qLEA/7e+Kf/////////////////6+/L/u8I3/6ixAP+psgD/qbIA/6my
+        AP+psgD/qLEA/6ixAPypsgA7AAAAAAAAAAAAAAAAAAAAAKmyADqosQD6qbIA/6myAP+psgD/qbIA/6my
+        AP+osQD/ucEy//f45/////////////////+9wzj/qLEA/6myAP+psgD/qbIA/6StAP/L0Gb/+/z2////
+        /////////v79/93gm/+irAD/qbIA/6myAP+psgD/qLEA/7e+Kf/////////////////6+/L/u8I3/6ix
+        AP+psgD/qbIA/6myAP+psgD/qbIA/6ixAP+psgBCAAAAAAAAAAAAAAAAAAAAAKixADyosQD9qbIA/6my
+        AP+psgD/qbIA/6myAP+osQD/ucEy//f45/////////////////+9wzj/qLEA/6myAP+psgD/qLEA/6ew
+        AP+psgH/6+3F//7+/v///////////+jqvP+utxD/p7AA/6myAP+psgD/qLEA/7e+Kf//////////////
+        ///6+/L/u8I3/6ixAP+psgD/qbIA/6myAP+psgD/qbIA/qixAP+psgBFAAAAAAAAAAAAAAAAAAAAAKmy
+        ADqosQD6qLEA/6myAP+psgD/qbIA/6myAP+osQD/ucEy//f45/////////////////+9wzj/qLEA/6my
+        AP+psgD/qLEA/663Ef+osQD/wMZF//7+/P/+/v7///////v89v/O023/pq8A/6ixAP+psgD/qLEA/7e+
+        Kf/////////////////6+/L/u8I3/6ixAP+psgD/qbIA/6myAP+psgD/qbIA/6ixAP+psgBDAAAAAAAA
+        AAAAAAAAAAAAAKixADWosQDvqLEA/6myAP+psgD/qbIA/6myAP+osQD/ucEy//f45///////////////
+        //+9wzj/qLEA/6myAP+nsQD/srob/9vflv+4wC7/pq8A/+Tnsf///////v7+///////r7cX/tLwh/6ew
+        AP+psgD/qLEA/7e+Kf/////////////////6+/L/u8I3/6ixAP+psgD/qbIA/6myAP+psgD/qLEA/6ix
+        AP2osQA8AAAAAAAAAAAAAAAAAAAAAKmyACupsgDZqLEA/6myAP+psgD/qbIA/6myAP+osQD/ucEy//f4
+        5/////////////////+9wzj/qLEA/6ixAP+nsAD/ys9h///////X24n/qrME/7W8Iv//////////////
+        ////////z9Nw/6ixAP+osQD/qLEA/7e+Kf/////////////////6+/L/u8I3/6ixAP+psgD/qbIA/6my
+        AP+psgD/qLEA/6myAOqpsgAzAAAAAAAAAAAAAAAAAAAAAKixAB2osQC8qLEA/6myAP+psgD/qbIA/6my
+        AP+osQD/ucEy//f45/////////////////+9wzj/qLEA/6ixAP+zux//6uzD///////9/Pj/tr0m/6ix
+        AP/Y3Iz///////7+/v//////8PLU/7W9Jf+osQD/qLEA/7e+Kf/////////////////6+/L/u8I3/6ix
+        AP+psgD/qbIA/6myAP+psgD/qLEA/6ixAMuosQAkAAAAAAAAAAAAAAAAAAAAAKixAAuosQCVqLEA/6ix
+        AP6psgD/qbIA/6myAP+osQD/ucEy//f45/////////////////+8wzj/qLEA/6myAv/L0GP/////////
+        ////////3+Ki/6qzBP+vtxH/+vvy/////////////////9HVdf+qswX/qLEA/7a+KP//////////////
+        ///6+/L/u8I3/6ixAP+psgD/qbIA/6myAP+osQD+qLEA/6ixAKWpsgASAAAAAAAAAAAAAAAAAAAAAAAA
+        AACosQBpqLEA/6ixAP+psgD/qbIA/6myAP+osQD/ucEy//f45//////////////////HzVr/t74p/77F
+        Pv/z89r/////////////////2d2O/6qzBP+psgL/z9Nu//////////////////j56v+/xkH/t74p/8PK
+        Tf/////////////////6+/L/u8I3/6ixAP+psgD/qbIA/6myAP+psgD/qLEA/6ixAHYAAAAAAAAAAAAA
+        AAAAAAAAqLEAAAAAAACpsgA+qLEA4KixAP+psgD+qbIA/6myAP+osQD/usEy//f46P////////////7+
+        /v///////////////////////v7+///////3+en/srsc/6ixAP+osQD/sLcU//Hz1////////v7+////
+        ///////////////////+/v7////////////6+/L/u8I3/6exAP+psgD/qbIA/6myAP6psgD/qLEA7Kix
+        AEoAAAAAqbIAAAAAAAAAAAAAAAAAAAAAAACosQAOqbIAramyAP+osQD/qbIA/6myAP+osQD/ucAx//b3
+        5v///////v7+///////////////////////+/v7////////////P1HH/qrME/6ixAP+osQD/qbIC/8jO
+        Xf////////////7+/v///////////////////////v7+///////6+/H/u8I2/6ixAP+psgD/qbIA/6my
+        AP+osQD/qbIAuqmyABkAAAAAAAAAAAAAAAAAAAAAAAAAAKmyAAAAAAAAqbIAaamyAPWosQD/qbIA/qmy
+        AP+osQD/sroc/+jqvP///////////////////////////////////////////+3vyv+zux7/qLEA/6my
+        AP+psgD/qLEA/7G5GP/n6rr////////////////////////////////////////////t78v/tLwj/6ix
+        AP+psgD/qbIA/qmyAP+osQD6qLEAeAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKmyAAAAAAAAqbIAFamy
+        AMiosQD/qLEA/6myAP+osQD/qbIA/77FP//f46H/5Oev/+Pnrv/j567/4+eu/+Pnrv/k56//3+Oi/77F
+        QP+psgD/qLEA/6myAP+psgD/qLEA/6ixAP+8wzj/3uKe/+Tnr//j567/4+eu/+Pnrv/j567/5Oev/+Hk
+        pf/Bx0j/qrIC/6ixAP+psgD/qbIA/qmyAP+psgDTqLEAIQAAAACosQAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AACosQAAAAAAAKixAGSosQD3qLEA/6myAP+psgD/qLEA/6ewAP+stQr/sLkW/7C5Fv+wuRb/sLkW/7C5
+        Fv+wuRb/rLUK/6ewAP+osQD/qbIA/6myAP+psgD/qbIA/6ixAP+nsAD/rLQJ/7C5Fv+wuRb/sLkW/7C5
+        Fv+wuRb/sLkW/621DP+nsAD/qLEA/6myAP+psgD/qLEA/6ixAPmpsgB3AAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAACpsgAAAAAAAAAAAACosQC2qLEA/6myAP6psgD/qbIA/6ixAP+osQD/qLEA/6ix
+        AP+osQD/qLEA/6ixAP+osQD/qLEA/6ixAP+psgD/qbIA/6myAP+psgD/qbIA/6myAP+osQD/qLEA/6ix
+        AP+osQD/qLEA/6ixAP+osQD/qLEA/6ixAP+osQD/qbIA/6myAP+osQD+qLEA/6myAMaosQAGAAAAAKix
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAqbIAAAAAAACpsgAbqLEA7aixAP+osQD+qbIA/6my
+        AP+psgD/qbIA/6myAP+psgD/qbIA/6myAP+psgD/qbIA/6myAP+psgD/qbIA/6myAP+psgD/qbIA/6my
+        AP+psgD/qbIA/6myAP+psgD/qbIA/6myAP+psgD/qbIA/6myAP+psgD/qbIA/6ixAP6psgD/qLEA9aix
+        ACoAAAAAqLEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAqLEAPKix
+        AP+osQD/qLEA/qmyAP+psgD/qbIA/6myAP+psgD/qbIA/6myAP+psgD/qbIA/6myAP+psgD/qbIA/6my
+        AP+psgD/qbIA/6myAP+psgD/qbIA/6myAP+psgD/qbIA/6myAP+psgD/qbIA/6myAP+psgD/qLEA/qix
+        AP6osQD/qLEATgAAAAAAAAAAqLEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AACosQAAAAAAAKmyAFWosQD/qbIA/6ixAP+psgD+qbIA/6myAP+psgD/qbIA/6myAP+psgD/qbIA/6my
+        AP+psgD/qbIA/6myAP+psgD/qbIA/6myAP+psgD/qbIA/6myAP+psgD/qbIA/6myAP+psgD/qbIA/6my
+        AP6osQD/qbIA/6ixAP+psgBqAAAAAKixAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAqLEAAAAAAACpsgBbqLEA+qixAP+psgD/qLEA/qmyAP+psgD/qbIA/6my
+        AP+psgD/qbIA/6myAP+psgD/qbIA/6myAP+psgD/qbIA/6myAP+psgD/qbIA/6myAP+psgD/qbIA/6my
+        AP+psgD/qLEA/qixAP+osQD/qbIA/qmyAG4AAAAAqbIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAqbIAT6ixAOKosQD/qLEA/6ix
+        AP+psgD+qbIA/6myAP+psgD/qbIA/6myAP+psgD/qbIA/6myAP+psgD/qbIA/6myAP+psgD/qbIA/6my
+        AP+psgD/qbIA/6myAP6osQD/qLEA/6ixAP+osQDpqbIAXAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKixAAAAAAAAAAAAAKix
+        ADGosQC0qLEA96ixAP+osQD/qbIA/qmyAP+psgD/qbIA/6myAP+psgD/qbIA/6myAP+psgD/qbIA/6my
+        AP+psgD/qbIA/6myAP+psgD/qbIA/qmyAP+osQD/qLEA+amyALypsgA8AAAAAAAAAACosQAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AACpsgAAAAAAAAAAAACosQAOqbIAcKixAMWosQD/qbIA/6myAP+osQD+qbIA/qmyAP+psgD/qbIA/6my
+        AP+psgD/qbIA/6myAP+psgD/qbIA/qmyAP6osQD/qbIA/6myAP+osQDKqLEAeaixABMAAAAAAAAAAKix
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAqLEAAKixAAAAAAAAAAAAAKmyACapsgBrqbIAsKixAO2osQD/qLEA/6ix
+        AP+osQD/qLEA/6ixAP+osQD/qLEA/6ixAP+osQD/qLEA/6ixAP+osQDwqbIAtqixAHGosQArAAAAAAAA
+        AACosQAAqbIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACpsgAAAAAAAAAAAAAAAAAAqbIAGamy
+        AECosQBpqLEAnamyAMeosQDlqLEA+qixAP+psgD/qbIA/KmyAOipsgDKqLEAoaixAG6psgBCqbIAHQAA
+        AAAAAAAAAAAAAKixAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKmy
+        AAAAAAAAAAAAAAAAAACosQAAqLEAEamyAB6psgAoqbIAL6ixADKpsgAyqLEAL6ixACmpsgAfqLEAEqmy
+        AAEAAAAAAAAAAAAAAACosQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAqLEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAqLEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD///////8AAP///////wAA///gB///
+        AAD//wAA//8AAP/8AAA//wAA//AAAA//AAD/4AAAB/8AAP/AAAAD/wAA/4AAAAH/AAD/AAAAAP8AAP4A
+        AAAAfwAA/AAAAAA/AAD8AAAAAD8AAPgAAAAAHwAA+AAAAAAfAADwAAAAAA8AAPAAAAAADwAA8AAAAAAP
+        AADgAAAAAAcAAOAAAAAABwAA4AAAAAAHAADgAAAAAAcAAOAAAAAABwAA4AAAAAAHAADgAAAAAAcAAOAA
+        AAAABwAA4AAAAAAHAADgAAAAAAcAAOAAAAAABwAA8AAAAAAPAADwAAAAAA8AAPAAAAAADwAA+AAAAAAf
+        AAD4AAAAAB8AAPwAAAAAPwAA/AAAAAA/AAD+AAAAAH8AAP8AAAAA/wAA/4AAAAH/AAD/wAAAA/8AAP/g
+        AAAH/wAA//AAAA//AAD//AAAP/8AAP//AAD//wAA///gB///AAD///////8AAP///////wAA////////
+        AAA=
+</value>
+  </data>
+</root>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HspGuiSourceV301/HSPGui/app.config	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,18 @@
+<?xml version="1.0"?>
+<configuration>
+<configSections>
+    <sectionGroup name="userSettings" type="System.Configuration.UserSettingsGroup, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" >
+        <section name="HealthSensorPlatform.Properties.Settings" type="System.Configuration.ClientSettingsSection, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" allowExeDefinition="MachineToLocalUser" requirePermission="false" />
+    </sectionGroup>
+</configSections>
+<startup><supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0"/></startup><userSettings>
+        <HealthSensorPlatform.Properties.Settings>
+            <setting name="DisableSplash" serializeAs="String">
+                <value>False</value>
+            </setting>
+            <setting name="ComPort" serializeAs="String">
+                <value />
+            </setting>
+        </HealthSensorPlatform.Properties.Settings>
+    </userSettings>
+</configuration>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HspGuiSourceV301/RPCSupportTest/ComPort.cs	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,48 @@
+/*******************************************************************************
+* Copyright (C) 2016 Maxim Integrated Products, Inc., All rights Reserved.
+* 
+* This software is protected by copyright laws of the United States and
+* of foreign countries. This material may also be protected by patent laws
+* and technology transfer regulations of the United States and of foreign
+* countries. This software is furnished under a license agreement and/or a
+* nondisclosure agreement and may only be used or reproduced in accordance
+* with the terms of those agreements. Dissemination of this information to
+* any party or parties not specified in the license agreement and/or
+* nondisclosure agreement is expressly prohibited.
+*
+* The above copyright notice and this permission notice shall be included
+* in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+* OTHER DEALINGS IN THE SOFTWARE.
+*
+* Except as contained in this notice, the name of Maxim Integrated
+* Products, Inc. shall not be used except as stated in the Maxim Integrated
+* Products, Inc. Branding Policy.
+*
+* The mere transfer of this software does not imply any licenses
+* of trade secrets, proprietary technology, copyrights, patents,
+* trademarks, maskwork rights, or any other form of intellectual
+* property whatsoever. Maxim Integrated Products, Inc. retains all
+* ownership rights.
+*******************************************************************************
+*/
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace RPCSupportTest
+{
+    public class ComPort
+    {
+        public const string Port = "com32";
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HspGuiSourceV301/RPCSupportTest/I2cTest.cs	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,164 @@
+/*******************************************************************************
+* Copyright (C) 2016 Maxim Integrated Products, Inc., All rights Reserved.
+* 
+* This software is protected by copyright laws of the United States and
+* of foreign countries. This material may also be protected by patent laws
+* and technology transfer regulations of the United States and of foreign
+* countries. This software is furnished under a license agreement and/or a
+* nondisclosure agreement and may only be used or reproduced in accordance
+* with the terms of those agreements. Dissemination of this information to
+* any party or parties not specified in the license agreement and/or
+* nondisclosure agreement is expressly prohibited.
+*
+* The above copyright notice and this permission notice shall be included
+* in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+* OTHER DEALINGS IN THE SOFTWARE.
+*
+* Except as contained in this notice, the name of Maxim Integrated
+* Products, Inc. shall not be used except as stated in the Maxim Integrated
+* Products, Inc. Branding Policy.
+*
+* The mere transfer of this software does not imply any licenses
+* of trade secrets, proprietary technology, copyrights, patents,
+* trademarks, maskwork rights, or any other form of intellectual
+* property whatsoever. Maxim Integrated Products, Inc. retains all
+* ownership rights.
+*******************************************************************************
+*/
+
+using System;
+using NUnit.Framework;
+using RPCSupport.Devices;
+using RPCSupport.DeviceSupport;
+using RPCSupport;
+
+namespace RPCSupportTest
+{
+    [TestFixture]
+    [Property("Class", "I2C")]
+    public class I2cTest 
+    {
+        RPCClient rpcClient;
+        I2cDevice i2cDevice;
+
+        [TestFixtureSetUp]
+        public void Init()
+        {
+            rpcClient = new RPCClient(RPCClient.ePipeline.eSerialWrap);
+            rpcClient.InitPipeline();
+            rpcClient.Connect(ComPort.Port);
+            i2cDevice = rpcClient.Init_I2cDevice();
+        }
+
+        [TestFixtureTearDown]
+        public void Dispose()
+        {
+            rpcClient.Disconnect();
+        }
+        
+        [Test]
+        public void I2CRead()
+        {
+            byte result = i2cDevice.ReadReg(1, 0x90, 0x01);
+
+            Assert.AreEqual(true, result >= 0 && result <= 0xff);
+        }
+
+        [Test]
+        public void I2CWriteConfigurationRegister()
+        {
+            /*
+            byte data = max30205.ReadReg(0x01);
+
+            byte flipped = (byte)(data ^ 0xFF);
+
+            max30205.WriteReg(0x01, flipped);
+
+            byte result = max30205.ReadReg(0x01);
+
+            max30205.WriteReg(0x01, data); // Restore register value
+
+            Assert.AreEqual(flipped, result);
+            */
+            byte data = i2cDevice.ReadReg(1, 0x90, 0x01);
+
+            byte flipped = (byte)(data & 0xFF);
+
+            i2cDevice.WriteReg(1, 0x90, 0x01, flipped);
+
+            byte result = i2cDevice.ReadReg(1, 0x90, 0x01);
+
+            i2cDevice.WriteReg(1, 0x90, 0x01, data);
+
+            Assert.AreEqual(flipped, result);
+        }
+
+        [Test]
+        public void I2CReadMultiple()
+        {
+            byte[] data = i2cDevice.ReadMultiReg(1, 0x90, 0x03, 2);
+
+            Assert.True(data[0] == 0x50 && data[1] == 0x00);
+            Assert.AreEqual(new byte[] { 0x50, 0x00 }, data);
+        }
+
+        [Test]
+        public void I2CWriteMultiReg()
+        {
+            byte[] data = i2cDevice.ReadMultiReg(1, 0x90, 0x03, 2);
+
+            i2cDevice.WriteMultiReg(1, 0x90, 0x03, 2, new byte[] { 0x12, 0x34 });
+            byte[] result = i2cDevice.ReadMultiReg(1, 0x90, 0x03, 2);
+
+            
+            i2cDevice.WriteMultiReg(1, 0x90, 0x03, 2, data); // restore data
+
+            Assert.AreEqual(new byte[] {0x12, 0x34}, result);
+
+        }
+
+        [Test]
+        public void I2CReadRegDetails()
+        {
+            DeviceDetails details = new DeviceDetails();
+            RegisterInfo reg = new RegisterInfo("CONFIG", 0x01);
+
+            details.InitI2c(1, 0x90);
+
+            i2cDevice.ReadReg(details, reg);
+
+            Assert.True(reg.data[0] >= 0x00 && reg.data[0] <= 0xFF);
+        }
+
+        [Test]
+        public void I2CReadMultipleDetails()
+        {
+            DeviceDetails details = new DeviceDetails();
+            RegisterInfo reg = new RegisterInfo("OVERT", 0x03, 2, RegisterInfo.RegisterType.None);
+
+            details.InitI2c(1, 0x90);
+
+            i2cDevice.ReadReg(details, reg);
+
+            Assert.True(reg.data[0] == 0x50 && reg.data[1] == 0x00);
+            Assert.AreEqual(new byte[] { 0x50, 0x00 }, reg.data);
+        }
+
+        [Test]
+        public void I2CWriteRead()
+        {
+            byte[] data = i2cDevice.WriteRead(1, 0x90, new byte[] { 0x03 }, 2);
+
+            Assert.True(data[0] == 0x50 && data[1] == 0x00);
+            Assert.AreEqual(new byte[] { 0x50, 0x00 }, data);
+        }
+
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HspGuiSourceV301/RPCSupportTest/MAX30001Test.cs	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,92 @@
+/*******************************************************************************
+* Copyright (C) 2016 Maxim Integrated Products, Inc., All rights Reserved.
+* 
+* This software is protected by copyright laws of the United States and
+* of foreign countries. This material may also be protected by patent laws
+* and technology transfer regulations of the United States and of foreign
+* countries. This software is furnished under a license agreement and/or a
+* nondisclosure agreement and may only be used or reproduced in accordance
+* with the terms of those agreements. Dissemination of this information to
+* any party or parties not specified in the license agreement and/or
+* nondisclosure agreement is expressly prohibited.
+*
+* The above copyright notice and this permission notice shall be included
+* in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+* OTHER DEALINGS IN THE SOFTWARE.
+*
+* Except as contained in this notice, the name of Maxim Integrated
+* Products, Inc. shall not be used except as stated in the Maxim Integrated
+* Products, Inc. Branding Policy.
+*
+* The mere transfer of this software does not imply any licenses
+* of trade secrets, proprietary technology, copyrights, patents,
+* trademarks, maskwork rights, or any other form of intellectual
+* property whatsoever. Maxim Integrated Products, Inc. retains all
+* ownership rights.
+*******************************************************************************
+*/
+
+using System;
+using NUnit.Framework;
+
+using RPCSupport;
+using RPCSupport.Devices;
+
+namespace RPCSupportTest
+{
+    [TestFixture]
+    [Property("Class", "MAX30001")]
+    class MAX30001Test
+    {
+        RPCClient rpcClient;
+        MAX30001 max30001;
+
+        [TestFixtureSetUp]
+        public void Init()
+        {
+            rpcClient = new RPCClient(RPCClient.ePipeline.eSerialWrap);
+            rpcClient.InitPipeline();
+            rpcClient.Connect(ComPort.Port);
+            //rpcClient.ShowRpcLog(true);
+            max30001 = rpcClient.Init_MAX30001();
+        }
+
+        [TestFixtureTearDown]
+        public void Dispose()
+        {
+            rpcClient.Disconnect();
+        }
+
+        [Test]
+        public void ReadReg()
+        {
+            int data = max30001.ReadReg(0x0F);
+
+            Assert.AreEqual(0x5050DF, data);
+        }
+
+        [Test]
+        public void WriteReg()
+        {
+            int writeData = 0x123456;
+
+            int data = max30001.ReadReg(0x05);
+
+            max30001.WriteReg(0x05, writeData);
+
+            int result = max30001.ReadReg(0x05);
+
+            max30001.WriteReg(0x05, data);
+
+            Assert.AreEqual(writeData, result);
+        }
+
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HspGuiSourceV301/RPCSupportTest/MAX30003Test.cs	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,92 @@
+/*******************************************************************************
+* Copyright (C) 2016 Maxim Integrated Products, Inc., All rights Reserved.
+* 
+* This software is protected by copyright laws of the United States and
+* of foreign countries. This material may also be protected by patent laws
+* and technology transfer regulations of the United States and of foreign
+* countries. This software is furnished under a license agreement and/or a
+* nondisclosure agreement and may only be used or reproduced in accordance
+* with the terms of those agreements. Dissemination of this information to
+* any party or parties not specified in the license agreement and/or
+* nondisclosure agreement is expressly prohibited.
+*
+* The above copyright notice and this permission notice shall be included
+* in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+* OTHER DEALINGS IN THE SOFTWARE.
+*
+* Except as contained in this notice, the name of Maxim Integrated
+* Products, Inc. shall not be used except as stated in the Maxim Integrated
+* Products, Inc. Branding Policy.
+*
+* The mere transfer of this software does not imply any licenses
+* of trade secrets, proprietary technology, copyrights, patents,
+* trademarks, maskwork rights, or any other form of intellectual
+* property whatsoever. Maxim Integrated Products, Inc. retains all
+* ownership rights.
+*******************************************************************************
+*/
+
+using System;
+using NUnit.Framework;
+
+using RPCSupport;
+using RPCSupport.Devices;
+
+namespace RPCSupportTest
+{
+    [TestFixture]
+    [Property("Class", "MAX30003")]
+    class MAX30003Test
+    {
+        RPCClient rpcClient;
+        MAX30001 max30001;
+
+        [TestFixtureSetUp]
+        public void Init()
+        {
+            rpcClient = new RPCClient(RPCClient.ePipeline.eSerialWrap);
+            rpcClient.InitPipeline();
+            rpcClient.Connect(ComPort.Port);
+            //rpcClient.ShowRpcLog(true);
+            max30001 = rpcClient.Init_MAX30001();
+        }
+
+        [TestFixtureTearDown]
+        public void Dispose()
+        {
+            rpcClient.Disconnect();
+        }
+
+        [Test]
+        public void ReadReg()
+        {
+            int data = max30001.ReadReg(0x0F);
+
+            Assert.AreEqual(0x513174, data);
+        }
+
+        [Test]
+        public void WriteReg()
+        {
+            int writeData = 0x123456;
+
+            int data = max30001.ReadReg(0x05);
+
+            max30001.WriteReg(0x05, writeData);
+
+            int result = max30001.ReadReg(0x05);
+
+            max30001.WriteReg(0x05, data);
+
+            Assert.AreEqual(writeData, result);
+        }
+
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HspGuiSourceV301/RPCSupportTest/MAX30101Test.cs	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,366 @@
+/*******************************************************************************
+* Copyright (C) 2016 Maxim Integrated Products, Inc., All rights Reserved.
+* 
+* This software is protected by copyright laws of the United States and
+* of foreign countries. This material may also be protected by patent laws
+* and technology transfer regulations of the United States and of foreign
+* countries. This software is furnished under a license agreement and/or a
+* nondisclosure agreement and may only be used or reproduced in accordance
+* with the terms of those agreements. Dissemination of this information to
+* any party or parties not specified in the license agreement and/or
+* nondisclosure agreement is expressly prohibited.
+*
+* The above copyright notice and this permission notice shall be included
+* in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+* OTHER DEALINGS IN THE SOFTWARE.
+*
+* Except as contained in this notice, the name of Maxim Integrated
+* Products, Inc. shall not be used except as stated in the Maxim Integrated
+* Products, Inc. Branding Policy.
+*
+* The mere transfer of this software does not imply any licenses
+* of trade secrets, proprietary technology, copyrights, patents,
+* trademarks, maskwork rights, or any other form of intellectual
+* property whatsoever. Maxim Integrated Products, Inc. retains all
+* ownership rights.
+*******************************************************************************
+*/
+
+using System;
+using System.Threading;
+using System.Windows.Forms;
+using System.Diagnostics;
+using NUnit.Framework;
+using Moq;
+
+using RPCSupport;
+using RPCSupport.Devices;
+
+namespace RPCSupportTest
+{
+    //[TestFixture, RequiresThread]
+    [TestFixture]
+    [Property("Class", "MAX30101")]
+    class MAX30101Test
+    {
+        RPCClient rpcClient;
+        MAX30101 max30101;
+
+        int[] avg = new int[] { 1, 2, 4, 8, 16, 32 };
+        int[] sr = new int[] { 50, 100, 200, 400 };
+
+        double minFactor = 0.75;
+        double maxFactor = 1;
+        int timeSleep = 10000;
+
+        [TestFixtureSetUp]
+        public void Init()
+        {
+            rpcClient = new RPCClient(RPCClient.ePipeline.eSerialWrap);
+            rpcClient.InitPipeline();
+            rpcClient.Connect(ComPort.Port);
+            //rpcClient.Pipeline.Discard();
+            max30101 = rpcClient.Init_MAX30101(0xAE);
+            //rpcClient.streaming.Init(rpcClient.Pipeline);
+
+            //rpcClient.Version();
+        }
+
+        [TestFixtureTearDown]
+        public void Dispose()
+        {
+            rpcClient.Disconnect();
+            rpcClient.streaming.Stop();
+            Thread.Sleep(100);
+        }
+
+        [TestCase(0, 0)]
+        [TestCase(0, 1)]
+        [TestCase(0, 2)]
+        [TestCase(0, 3)]
+        [TestCase(1, 0)]
+        [TestCase(1, 1)]
+        [TestCase(1, 2)]
+        [TestCase(1, 3)]
+        [TestCase(2, 0)]
+        [TestCase(2, 1)]
+        [TestCase(2, 2)]
+        [TestCase(2, 3)]
+        //[TestCase(3, 0)]
+        [TestCase(3, 1)]
+        [TestCase(3, 2)]
+        [TestCase(3, 3)]
+        //[TestCase(4, 0)]
+        //[TestCase(4, 1)]
+        [TestCase(4, 2)]
+        [TestCase(4, 3)]
+        //[TestCase(5, 0)]
+        //[TestCase(5, 1)]
+        //[TestCase(5, 2)]
+        [TestCase(5, 3)]
+        public void HRModeTest(byte sampleAverage, byte sampleRate)
+        {
+            HRModeTest(sampleAverage, sampleRate, 3000);
+        }
+
+        [TestCase(3, 0, 4000)]
+        [TestCase(4, 0, 8000)]
+        [TestCase(4, 1, 4000)]
+        [TestCase(5, 0, 12000)]
+        [TestCase(5, 1, 8000)]
+        [TestCase(5, 2, 4000)]
+        public void HRModeTest(byte sampleAverage, byte sampleRate, int sleepMilliSecond)
+        {
+            Mock<IPlotView> plotView;
+            plotView = new Mock<IPlotView>();
+            StreamHelper streamHelper = new StreamHelper(rpcClient, plotView.Object);
+
+            rpcClient.MAX30101.HRmode_init(0x0f, sampleAverage, sampleRate, 3, 0x33, (byte)(0 + 4));
+            Thread.Sleep(sleepMilliSecond);
+            rpcClient.MAX30101.HRmode_stop();
+
+            Application.DoEvents();
+
+            plotView.Verify(p => p.Display(It.IsAny<int[]>()), Times.AtLeast(1));
+        }
+
+        [TestCase(0, 0)]
+        [TestCase(0, 1)]
+        [TestCase(0, 2)]
+        [TestCase(0, 3)]
+        [TestCase(1, 0)]
+        [TestCase(1, 1)]
+        [TestCase(1, 2)]
+        [TestCase(1, 3)]
+        [TestCase(2, 0)]
+        [TestCase(2, 1)]
+        [TestCase(2, 2)]
+        [TestCase(2, 3)]
+        //[TestCase(3, 0)]
+        [TestCase(3, 1)]
+        [TestCase(3, 2)]
+        [TestCase(3, 3)]
+        //[TestCase(4, 0)]
+        //[TestCase(4, 1)]
+        [TestCase(4, 2)]
+        [TestCase(4, 3)]
+        //[TestCase(5, 0)]
+        //[TestCase(5, 1)]
+        //[TestCase(5, 2)]
+        [TestCase(5, 3)]
+        public void SpO2ModeTest(byte sampleAverage, byte sampleRate)
+        {
+            SpO2ModeTest(sampleAverage, sampleRate, 3000);
+        }
+
+        [TestCase(3, 0, 4000)]
+        [TestCase(4, 0, 8000)]
+        [TestCase(4, 1, 4000)]
+        [TestCase(5, 0, 12000)]
+        [TestCase(5, 1, 8000)]
+        [TestCase(5, 2, 4000)]
+        public void SpO2ModeTest(byte sampleAverage, byte sampleRate, int sleepMillisecond)
+        {
+            Mock<IPlotView> plotView = new Mock<IPlotView>();
+            StreamHelper streamHelper = new StreamHelper(rpcClient, plotView.Object);
+
+            rpcClient.MAX30101.SpO2mode_init(0x0f, sampleAverage, sampleRate, 3, 0x33, 0x33, (byte)(sampleRate + 4));
+            Thread.Sleep(sleepMillisecond);
+            rpcClient.MAX30101.SpO2mode_stop();
+
+            Application.DoEvents();
+
+            plotView.Verify(p => p.Display(It.IsAny<int[]>()), Times.AtLeast(1));
+        }
+
+
+        [TestCase(0, 0)]
+        [TestCase(0, 1)]
+        [TestCase(0, 2)]
+        [TestCase(0, 3)]
+        [TestCase(1, 0)]
+        [TestCase(1, 1)]
+        [TestCase(1, 2)]
+        [TestCase(1, 3)]
+        [TestCase(2, 0)]
+        [TestCase(2, 1)]
+        [TestCase(2, 2)]
+        [TestCase(2, 3)]
+        //[TestCase(3,0)]
+        [TestCase(3, 1)]
+        [TestCase(3, 2)]
+        [TestCase(3, 3)]
+        //[TestCase(4, 0)]
+        //[TestCase(4, 1)]
+        [TestCase(4, 2)]
+        [TestCase(4, 3)]
+        //[TestCase(5, 0)]
+        //[TestCase(5, 1)]
+        //[TestCase(5, 2)]
+        [TestCase(5, 3)]
+        public void MultiModeTest(byte sampleAverage, byte sampleRate)
+        {
+            MultiModeTest(sampleAverage, sampleRate, 3000);
+        }
+
+        [TestCase(3, 0, 4000)]
+        [TestCase(4, 0, 8000)]
+        [TestCase(4, 1, 4000)]
+        [TestCase(5, 0, 12000)]
+        [TestCase(5, 1, 8000)]
+        [TestCase(5, 2, 4000)]
+        public void MultiModeTest(byte sampleAverage, byte sampleRate, int sleepMilliSecond)
+        {
+                        Mock<IPlotView> plotView = new Mock<IPlotView>();
+            StreamHelper streamHelper = new StreamHelper(rpcClient, plotView.Object);
+
+            rpcClient.MAX30101.Multimode_init(0x0f, sampleAverage, sampleRate, 0, 0x33, 0x33, 0x33, 1, 2, 3, 0, (byte)(sampleRate + 4));
+            Thread.Sleep(sleepMilliSecond);
+            rpcClient.MAX30101.Multimode_stop();
+
+            Application.DoEvents();
+
+            plotView.Verify(p => p.Display(It.IsAny<int[]>()), Times.AtLeast(1));
+        }
+
+        [TestCase(0, 0)]
+        [TestCase(0, 1)]
+        [TestCase(0, 2)]
+        [TestCase(0, 3)]
+        [TestCase(1, 0)]
+        [TestCase(1, 1)]
+        [TestCase(1, 2)]
+        [TestCase(1, 3)]
+        [TestCase(2, 0)]
+        [TestCase(2, 1)]
+        [TestCase(2, 2)]
+        [TestCase(2, 3)]
+        [TestCase(3, 0)]
+        [TestCase(3, 1)]
+        [TestCase(3, 2)]
+        [TestCase(3, 3)]
+        //[TestCase(4, 0)]
+        [TestCase(4, 1)]
+        [TestCase(4, 2)]
+        [TestCase(4, 3)]
+        //[TestCase(5, 0)]
+        //[TestCase(5, 1)]
+        [TestCase(5, 2)]
+        [TestCase(5, 3)]
+        public void HRModePointsTest(byte sampleAverage, byte sampleRate)
+        {
+            Stopwatch sw = new Stopwatch();
+            PlotView plotView = new PlotView();
+            StreamHelper streamHelper = new StreamHelper(rpcClient, plotView);
+
+            rpcClient.MAX30101.HRmode_init(0x0f, sampleAverage, sampleRate, 3, 0x33, (byte)(0 + 4));
+            sw.Start();
+            Thread.Sleep(timeSleep);
+            rpcClient.MAX30101.HRmode_stop();
+            sw.Stop();
+
+            Application.DoEvents();
+
+            Console.WriteLine("Points: " + plotView.Points + "Time: " + sw.ElapsedMilliseconds / 1000.0);
+            Assert.That(plotView.Points, Is.GreaterThan(minFactor * sw.ElapsedMilliseconds / 1000 * sr[sampleRate] / avg[sampleAverage]));
+            Assert.That(plotView.Points, Is.LessThan(maxFactor * sw.ElapsedMilliseconds / 1000 * sr[sampleRate] / avg[sampleAverage]));
+        }
+
+        [TestCase(0, 0)]
+        [TestCase(0, 1)]
+        [TestCase(0, 2)]
+        [TestCase(0, 3)]
+        [TestCase(1, 0)]
+        [TestCase(1, 1)]
+        [TestCase(1, 2)]
+        [TestCase(1, 3)]
+        [TestCase(2, 0)]
+        [TestCase(2, 1)]
+        [TestCase(2, 2)]
+        [TestCase(2, 3)]
+        [TestCase(3, 0)]
+        [TestCase(3, 1)]
+        [TestCase(3, 2)]
+        [TestCase(3, 3)]
+        //[TestCase(4, 0)]
+        [TestCase(4, 1)]
+        [TestCase(4, 2)]
+        [TestCase(4, 3)]
+        //[TestCase(5, 0)]
+        //[TestCase(5, 1)]
+        [TestCase(5, 2)]
+        [TestCase(5, 3)]
+        public void SpO2ModePointsTest(byte sampleAverage, byte sampleRate)
+        {
+            //ManualResetEvent eventRasied = new ManualResetEvent(false);
+            Stopwatch sw = new Stopwatch();
+            PlotView plotView = new PlotView();
+            StreamHelper streamHelper = new StreamHelper(rpcClient, plotView);
+
+            //rpcClient.streaming.PartialArrayIntAvailable += (sender, e) => { eventRasied.Set(); };
+
+            rpcClient.MAX30101.SpO2mode_init(0x0f, sampleAverage, sampleRate, 3, 0x33, 0x33, (byte)(sampleRate + 4));
+            sw.Start();
+            Thread.Sleep(timeSleep);
+            rpcClient.MAX30101.SpO2mode_stop();
+            sw.Stop();
+
+            Application.DoEvents();
+
+            Console.WriteLine("Points: " + plotView.Points + "Time: " + sw.ElapsedMilliseconds / 1000.0);
+            Assert.That(plotView.Points, Is.GreaterThan(minFactor * sw.ElapsedMilliseconds / 1000 * sr[sampleRate] / avg[sampleAverage]));
+            Assert.That(plotView.Points, Is.LessThan(maxFactor * sw.ElapsedMilliseconds / 1000 * sr[sampleRate] / avg[sampleAverage]));
+            //Assert.IsTrue(eventRasied.WaitOne(10000));
+        }
+
+        [TestCase(0, 0)]
+        [TestCase(0, 1)]
+        [TestCase(0, 2)]
+        [TestCase(0, 3)]
+        [TestCase(1, 0)]
+        [TestCase(1, 1)]
+        [TestCase(1, 2)]
+        [TestCase(1, 3)]
+        [TestCase(2, 0)]
+        [TestCase(2, 1)]
+        [TestCase(2, 2)]
+        [TestCase(2, 3)]
+        [TestCase(3, 0)]
+        [TestCase(3, 1)]
+        [TestCase(3, 2)]
+        [TestCase(3, 3)]
+        //[TestCase(4, 0)]
+        [TestCase(4, 1)]
+        [TestCase(4, 2)]
+        [TestCase(4, 3)]
+        //[TestCase(5, 0)]
+        //[TestCase(5, 1)]
+        [TestCase(5, 2)]
+        [TestCase(5, 3)]
+        public void MultiModePointsTest(byte sampleAverage, byte sampleRate)
+        {
+            Stopwatch sw = new Stopwatch();
+            PlotView plotView = new PlotView();
+            StreamHelper streamHelper = new StreamHelper(rpcClient, plotView);
+
+            rpcClient.MAX30101.Multimode_init(0x0f, sampleAverage, sampleRate, 0, 0x33, 0x33, 0x33, 1, 2, 3, 0, (byte)(sampleRate + 4));
+            sw.Start();
+            Thread.Sleep(timeSleep);
+            rpcClient.MAX30101.Multimode_stop();
+            sw.Stop();
+
+            Application.DoEvents();
+
+            Console.WriteLine("Points: " + plotView.Points + "Time: " + sw.ElapsedMilliseconds / 1000.0);
+            Assert.That(plotView.Points, Is.GreaterThan(minFactor * sw.ElapsedMilliseconds / 1000 * sr[sampleRate] / avg[sampleAverage]));
+            Assert.That(plotView.Points, Is.LessThan(maxFactor * sw.ElapsedMilliseconds / 1000 * sr[sampleRate] / avg[sampleAverage]));
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HspGuiSourceV301/RPCSupportTest/MAX30205Test.cs	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,102 @@
+/*******************************************************************************
+* Copyright (C) 2016 Maxim Integrated Products, Inc., All rights Reserved.
+* 
+* This software is protected by copyright laws of the United States and
+* of foreign countries. This material may also be protected by patent laws
+* and technology transfer regulations of the United States and of foreign
+* countries. This software is furnished under a license agreement and/or a
+* nondisclosure agreement and may only be used or reproduced in accordance
+* with the terms of those agreements. Dissemination of this information to
+* any party or parties not specified in the license agreement and/or
+* nondisclosure agreement is expressly prohibited.
+*
+* The above copyright notice and this permission notice shall be included
+* in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+* OTHER DEALINGS IN THE SOFTWARE.
+*
+* Except as contained in this notice, the name of Maxim Integrated
+* Products, Inc. shall not be used except as stated in the Maxim Integrated
+* Products, Inc. Branding Policy.
+*
+* The mere transfer of this software does not imply any licenses
+* of trade secrets, proprietary technology, copyrights, patents,
+* trademarks, maskwork rights, or any other form of intellectual
+* property whatsoever. Maxim Integrated Products, Inc. retains all
+* ownership rights.
+*******************************************************************************
+*/
+
+using System;
+using NUnit.Framework;
+using RPCSupport.Devices;
+using RPCSupport;
+
+namespace RPCSupportTest
+{
+    [TestFixture, Property("Hardware", "Required")]
+    public class MAX30205Test
+    {
+        RPCClient rpcClient;
+        MAX30205 max30205;
+
+        [TestFixtureSetUp]
+        public void Init()
+        {
+            rpcClient = new RPCClient(RPCClient.ePipeline.eSerialWrap);
+            rpcClient.InitPipeline();
+            rpcClient.Connect(ComPort.Port);
+            max30205 = rpcClient.Init_MAX30205(0x90);
+        }
+
+        [TestFixtureTearDown]
+        public void Dispose()
+        {
+            rpcClient.Disconnect();
+        }
+
+        [Test]
+        public void ReadTemperature()
+        {
+            float temp = max30205.ReadTemp();
+
+            Assert.AreEqual(true, temp > 20 && temp < 30);
+        }
+
+        [Test]
+        public void ReadConfigurationRegister()
+        {
+            byte data = max30205.ReadReg(0x01);
+
+            Assert.AreEqual(true, data >= 0 && data <= 0xff);
+        }
+
+        [Test]
+        public void WriteConfigurationRegister()
+        {
+            byte data = max30205.ReadReg(0x01);
+
+            byte flipped = (byte)(data ^ 0xFF);
+
+            max30205.WriteReg(0x01, flipped);
+
+            byte result = max30205.ReadReg(0x01);
+
+            max30205.WriteReg(0x01, data); // Restore register value
+
+            Assert.AreEqual(flipped, result);
+        }
+
+        [Test]
+        public void WriteOverTemperatureRegister()
+        {
+            Assert.AreEqual(true, false);
+        }
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HspGuiSourceV301/RPCSupportTest/Properties/AssemblyInfo.cs	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,36 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following 
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("RPCSupportTest")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("RPCSupportTest")]
+[assembly: AssemblyCopyright("Copyright ©  2015")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible 
+// to COM components.  If you need to access a type in this assembly from 
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("067456c0-086c-46a8-b37f-1405717b7bfc")]
+
+// Version information for an assembly consists of the following four values:
+//
+//      Major Version
+//      Minor Version 
+//      Build Number
+//      Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers 
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HspGuiSourceV301/RPCSupportTest/RPCSupportTest.csproj	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,76 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <PropertyGroup>
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+    <ProjectGuid>{067456C0-086C-46A8-B37F-1405717B7BFC}</ProjectGuid>
+    <OutputType>Library</OutputType>
+    <AppDesignerFolder>Properties</AppDesignerFolder>
+    <RootNamespace>RPCSupportTest</RootNamespace>
+    <AssemblyName>RPCSupportTest</AssemblyName>
+    <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
+    <FileAlignment>512</FileAlignment>
+    <ProjectTypeGuids>{3AC096D0-A1C2-E12C-1390-A8335801FDAB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
+    <TargetFrameworkProfile />
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+    <DebugSymbols>true</DebugSymbols>
+    <DebugType>full</DebugType>
+    <Optimize>false</Optimize>
+    <OutputPath>bin\Debug\</OutputPath>
+    <DefineConstants>DEBUG;TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+    <DebugType>pdbonly</DebugType>
+    <Optimize>true</Optimize>
+    <OutputPath>bin\Release\</OutputPath>
+    <DefineConstants>TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+  </PropertyGroup>
+  <ItemGroup>
+    <Reference Include="Castle.Core, Version=3.3.0.0, Culture=neutral, PublicKeyToken=407dd0808d44fbdc, processorArchitecture=MSIL">
+      <HintPath>..\packages\Castle.Core.3.3.3\lib\net45\Castle.Core.dll</HintPath>
+      <Private>True</Private>
+    </Reference>
+    <Reference Include="Moq, Version=4.5.21.0, Culture=neutral, PublicKeyToken=69f491c39445e920, processorArchitecture=MSIL">
+      <HintPath>..\packages\Moq.4.5.21\lib\net45\Moq.dll</HintPath>
+      <Private>True</Private>
+    </Reference>
+    <Reference Include="nunit.framework, Version=2.6.4.14350, Culture=neutral, PublicKeyToken=96d09a1eb7f44a77, processorArchitecture=MSIL">
+      <SpecificVersion>False</SpecificVersion>
+      <HintPath>..\packages\NUnit.2.6.4\lib\nunit.framework.dll</HintPath>
+    </Reference>
+    <Reference Include="System" />
+    <Reference Include="System.Windows.Forms" />
+  </ItemGroup>
+  <ItemGroup>
+    <Compile Include="ComPort.cs" />
+    <Compile Include="I2cTest.cs" />
+    <Compile Include="MAX30003Test.cs" />
+    <Compile Include="MAX30001Test.cs" />
+    <Compile Include="MAX30101Test.cs" />
+    <Compile Include="MAX30205Test.cs" />
+    <Compile Include="Properties\AssemblyInfo.cs" />
+    <Compile Include="StreamHelper.cs" />
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="packages.config" />
+  </ItemGroup>
+  <ItemGroup>
+    <ProjectReference Include="..\GuiDLLs\RPCSupport\RPCSupport.csproj">
+      <Project>{170a27f5-0680-485d-8b90-ea736719016e}</Project>
+      <Name>RPCSupport</Name>
+    </ProjectReference>
+  </ItemGroup>
+  <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+  <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 
+       Other similar extension points exist, see Microsoft.Common.targets.
+  <Target Name="BeforeBuild">
+  </Target>
+  <Target Name="AfterBuild">
+  </Target>
+  -->
+</Project>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HspGuiSourceV301/RPCSupportTest/StreamHelper.cs	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,116 @@
+/*******************************************************************************
+* Copyright (C) 2016 Maxim Integrated Products, Inc., All rights Reserved.
+* 
+* This software is protected by copyright laws of the United States and
+* of foreign countries. This material may also be protected by patent laws
+* and technology transfer regulations of the United States and of foreign
+* countries. This software is furnished under a license agreement and/or a
+* nondisclosure agreement and may only be used or reproduced in accordance
+* with the terms of those agreements. Dissemination of this information to
+* any party or parties not specified in the license agreement and/or
+* nondisclosure agreement is expressly prohibited.
+*
+* The above copyright notice and this permission notice shall be included
+* in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+* OTHER DEALINGS IN THE SOFTWARE.
+*
+* Except as contained in this notice, the name of Maxim Integrated
+* Products, Inc. shall not be used except as stated in the Maxim Integrated
+* Products, Inc. Branding Policy.
+*
+* The mere transfer of this software does not imply any licenses
+* of trade secrets, proprietary technology, copyrights, patents,
+* trademarks, maskwork rights, or any other form of intellectual
+* property whatsoever. Maxim Integrated Products, Inc. retains all
+* ownership rights.
+*******************************************************************************
+*/
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using RPCSupport;
+using RPCSupport.Streaming;
+
+namespace RPCSupportTest
+{
+    public class StreamHelper
+    {
+        RPCClient rpcClient;
+        IPlotView view;
+
+        public StreamHelper(RPCClient rpcClient, IPlotView view)
+        {
+            this.view = view;
+            this.rpcClient = rpcClient;
+            this.rpcClient.streaming.PartialArrayIntAvailable += new EventHandler<PartialArrayIntAvailableEventArgs>(OnPartialArrayIntAvailable);
+        }
+
+        public void OnPartialArrayIntAvailable(object sender, PartialArrayIntAvailableEventArgs e)
+        {
+            if ((e.reportID & 0xF0) == PartialArrayIntAvailableEventArgs.PACKET_MAX30101)
+                view.Display(e.array1);
+        }
+
+        public void Start(byte fifo_waterlevel_mark, byte sample_avg, byte sample_rate, byte pulse_width,
+                                                                        byte red_led_current, byte accelRateParameter)
+        {
+            rpcClient.MAX30101.HRmode_init(fifo_waterlevel_mark, sample_avg, sample_rate, pulse_width, red_led_current, accelRateParameter);
+        }
+
+        public void Stop()
+        {
+            rpcClient.MAX30101.HRmode_stop();
+        }
+
+        bool started = false;
+        public void OnStartStop(object sender, EventArgs e)
+        {
+            if (!started)
+            {
+                Start(0x0f, 0, 0, 3, 0x33, (byte)(0 + 4));
+                started = true;
+            }
+            else
+            {
+                Stop();
+            }
+
+        }
+    }
+
+    public interface IPlotView
+    {
+        int Points { get; }
+        void Display(int[] array);
+        //void Display();
+    }
+
+    public class PlotView : IPlotView
+    {
+        int points;
+
+        public int Points
+        {
+            get 
+            {
+                return points;
+            }
+        }
+
+        public void Display(int[] array)
+        {
+            points += array.Length;
+        }
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HspGuiSourceV301/RPCSupportTest/packages.config	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<packages>
+  <package id="Castle.Core" version="3.3.3" targetFramework="net45" />
+  <package id="Moq" version="4.5.21" targetFramework="net45" />
+  <package id="NUnit" version="2.6.4" targetFramework="net452" />
+</packages>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HspGuiSourceV301/Script/hsp_intassignment.py	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,28 @@
+import serial
+import io
+import time
+
+ser = serial.Serial(port='com16', baudrate=9600, timeout=1)
+
+ser.isOpen()
+
+ser.write("/MAX30001/WriteReg 2 3\r\n".encode())
+print(ser.readline())
+ser.write("/MAX30001/WriteReg 3 3\r\n".encode())
+print(ser.readline())
+
+
+#time.sleep(5)
+#for x in range (0, 100):
+ser.write("/MAX30001/INT_assignment 1 0 0 2 1 0 2 2 0 1 0 0 2 1 0 3 3\r\n".encode())
+print(ser.readline())
+
+ser.write("/MAX30001/WriteReg 10 080004\r\n".encode())
+print(ser.readline())
+
+ser.write("/MAX30001/ReadReg 2\r\n".encode())
+print(ser.readline())
+ser.write("/MAX30001/ReadReg 3\r\n".encode())
+print(ser.readline())
+
+ser.close()
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HspGuiSourceV301/Script/hsp_mission.py	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,26 @@
+import serial
+import io
+
+ser = serial.Serial(port='com29', baudrate=9600, timeout=1)
+
+ser.isOpen()
+
+for x in range (0, 1):
+    ser.write("/Logging/StartMissionDefine\r\n".encode())
+    print(ser.readline())
+    ser.write("/Logging/AppendMissionCmd \"null\"\r\n".encode())
+    print(ser.readline())
+    #ser.write("/Logging/AppendMissionCmd \"/Timestamp/SetSource 0\"\r\n".encode())
+    #print(ser.readline())
+    ser.write("/Logging/AppendMissionCmd \"/MAX30001/ECG_InitStart 01 01 01 00 02 03 1F 02 00 00 01\"\r\n".encode())
+    print(ser.readline())
+    ser.write("/Logging/AppendMissionCmd \"/MAX30001/Rbias_FMSTR_Init 00 02 01 01 00\"\r\n".encode())
+    print(ser.readline())
+    ser.write("/Logging/AppendMissionCmd \"null\"\r\n".encode())
+    print(ser.readline())
+    ser.write("/Logging/EndMissionDefine\r\n".encode())
+    print(ser.readline())
+    ser.write("/Logging/WriteMission\r\n".encode())
+    print(ser.readline())
+
+ser.close()
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HspGuiSourceV301/Script/hsp_registerread.py	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,31 @@
+import serial
+import io
+import time
+
+ser = serial.Serial(port='com16', baudrate=9600, timeout=1)
+
+ser.isOpen()
+
+for x in range (0, 10000):
+    ser.write("/MAX30001/ReadReg 18\r".encode())
+    #print(ser.readline())
+    #ser.write("/MAX30001/ReadReg 18\r".encode())
+    #print(ser.readline())
+    #ser.write("/MAX30001/ReadReg 18\r".encode())
+    #print(ser.readline())
+    #ser.write("/MAX30001/ReadReg 10\r".encode())
+    #print(ser.readline())
+    #ser.write("/MAX30001/ReadReg 10\r".encode())
+    #print(ser.readline())
+    #ser.write("/MAX30001/ReadReg 10\r".encode())
+    #print(ser.readline())
+    #ser.write("/MAX30001/ReadReg 15\r".encode())
+    #print(ser.readline())
+    #ser.write("/MAX30001/ReadReg 15\r".encode())
+    #print(ser.readline())
+    #ser.write("/MAX30001/ReadReg 15\r".encode())
+#print(ser.readline())
+    time.sleep(0.1)
+    print("Count " + str(x))
+
+ser.close()
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HspGuiSourceV301/Script/hsp_streamstartstop.py	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,41 @@
+import serial
+import io
+import time
+
+ser = serial.Serial(port='com16', baudrate=9600, timeout=1)
+
+ser.isOpen()
+
+for x in range (0, 3):
+    print('-------------Test Start-------------------------------')
+    ser.write("/MAX30001/INT_assignment 1 0 0 2 2 0 2 2 0 1 0 0 2 1 0 3 3\r\n".encode())
+    print(ser.readline())
+    ser.write("/MAX30001/ECG_InitStart 01 00 00 00 00 00 0F 02 00 01 01\r\n".encode())
+    print(ser.readline())
+    ser.write("/MAX30001/PACE_InitStart 01 00 00 00 00 00 00 05 05\r\n".encode())
+    print(ser.readline())
+    ser.write("/MAX30001/BIOZ_InitStart 01 01 01 00 00 00 07 00 02 00 00 00 01 08 00 00 00\r\n".encode())
+    print(ser.readline())
+    ser.write("/MAX30001/RtoR_InitStart 01 03 0F 02 03 20 02 04 01\r\n".encode())
+    print(ser.readline())
+    ser.write("/MAX30001/Start\r\n".encode())
+
+    for i in range (0,3):
+        print(ser.read(100))
+
+    ser.write(" ".encode())
+    print(ser.read(100))
+
+    #ser.write("/MAX30001/WriteReg 10 E0004\r\n".encode())
+    #print(ser.read(100))
+    ser.write("/MAX30001/ReadReg 1D\r\n".encode())
+    print(ser.read(100))
+    ser.write("/MAX30001/WriteReg 1D 3FA300\r\n".encode())
+    print(ser.read(100))
+    ser.write("/MAX30001/WriteReg 02 03\r\n".encode())
+    print(ser.read(100))
+    ser.write("/MAX30001/WriteReg 03 03\r\n".encode())
+    print(ser.read(100))
+
+
+ser.close()
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MAX30205.lib	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,1 @@
+https://os.mbed.com/teams/MaximIntegrated/code/MAX30205/#2aeb45dd2bb9
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/e4a10ed6eb92/.gitignore	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,4 @@
+.build
+.mbed
+projectfiles
+*.py*
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/e4a10ed6eb92/.hg_archival.txt	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,5 @@
+repo: e4a10ed6eb9294b5deeba5d7f9664c900dadf17f
+node: e4a10ed6eb9294b5deeba5d7f9664c900dadf17f
+branch: default
+latesttag: null
+latesttagdistance: 1
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/e4a10ed6eb92/HSP/Devices/BMP280/BMP280/BMP280.cpp	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,294 @@
+/*******************************************************************************
+ * Copyright (C) 2016 Maxim Integrated Products, Inc., All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+ * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Except as contained in this notice, the name of Maxim Integrated
+ * Products, Inc. shall not be used except as stated in the Maxim Integrated
+ * Products, Inc. Branding Policy.
+ *
+ * The mere transfer of this software does not imply any licenses
+ * of trade secrets, proprietary technology, copyrights, patents,
+ * trademarks, maskwork rights, or any other form of intellectual
+ * property whatsoever. Maxim Integrated Products, Inc. retains all
+ * ownership rights.
+ *******************************************************************************
+ */
+
+
+#include "mbed.h"
+#include "BMP280.h"
+
+//******************************************************************************
+BMP280::BMP280(PinName sda, PinName scl, int slaveAddress) : 
+        slaveAddress(slaveAddress) {
+  i2c = new I2C(sda, scl);
+  isOwner = true;
+}
+//******************************************************************************
+BMP280::BMP280(I2C *i2c, int slaveAddress) : 
+        slaveAddress(slaveAddress) {
+  this->i2c = i2c;
+  isOwner = false;
+
+  i2c->frequency(100000);
+  loggingEnabled = 0;
+  loggingSampleRate = 5;
+}
+//******************************************************************************
+BMP280::~BMP280(void) {
+  if (isOwner == true) {
+    delete i2c;
+  }
+}
+
+//******************************************************************************
+int BMP280::init(BMP280::bmp280_osrs_P_t Osrs_p, BMP280::bmp280_osrs_T_t Osrs_t,
+                 BMP280::bmp280_FILT_t Filter, BMP280::bmp280_MODE_t Mode,
+                 BMP280::bmp280_TSB_t T_sb)
+
+{
+  char reg;
+  char raw_Tn[6];
+  char raw_Pn[20];
+
+  // Read all the temp coeffecients from the BMP280 memory. It will be used in
+  // calculation
+  reg = 0x88;
+  if (reg_read(reg, raw_Tn, 6) != 0) {
+    return -1;
+  }
+
+  dig_T1 = (((uint16_t)raw_Tn[1]) << 8) | raw_Tn[0];
+  dig_T2 = (((int16_t)raw_Tn[3]) << 8) | raw_Tn[2];
+  dig_T3 = (((int16_t)raw_Tn[5]) << 8) | raw_Tn[4];
+
+  // Read all the press coeffecients from the BMP280 memory. It will be used in
+  // calculation
+  reg = 0x8E;
+  if (reg_read(reg, raw_Pn, 20) != 0) {
+    return -1;
+  }
+
+  dig_P1 = (((uint16_t)raw_Pn[1]) << 8) | raw_Pn[0];
+  dig_P2 = (((int16_t)raw_Pn[3]) << 8) | raw_Pn[2];
+  dig_P3 = (((int16_t)raw_Pn[5]) << 8) | raw_Pn[4];
+  dig_P4 = (((int16_t)raw_Pn[7]) << 8) | raw_Pn[6];
+  dig_P5 = (((int16_t)raw_Pn[9]) << 8) | raw_Pn[8];
+  dig_P6 = (((int16_t)raw_Pn[11]) << 8) | raw_Pn[10];
+  dig_P7 = (((int16_t)raw_Pn[13]) << 8) | raw_Pn[12];
+  dig_P8 = (((int16_t)raw_Pn[15]) << 8) | raw_Pn[14];
+  dig_P9 = (((int16_t)raw_Pn[17]) << 8) | raw_Pn[16];
+
+
+  wait(1.0 / 10.0);
+
+  /****/
+  if (reg_read(BMP280_CTRL_MEAS, &bmp280_ctrl_meas.all, 1) != 0) {
+    return -1;
+  }
+
+  bmp280_ctrl_meas.bit.osrs_p = Osrs_p;
+  bmp280_ctrl_meas.bit.osrs_t = Osrs_t;
+
+  bmp280_ctrl_meas.bit.mode = Mode;
+
+  if (reg_write(BMP280_CTRL_MEAS, bmp280_ctrl_meas.all) != 0) {
+    return -1;
+  }
+
+  /****/
+
+  if (reg_read(BMP280_CONFIG, &bmp280_config.all, 1) != 0) {
+    return -1;
+  }
+
+  bmp280_config.bit.filter = Filter;
+
+  if (Mode == 0b11) {
+    bmp280_config.bit.t_sb = T_sb;
+  }
+
+  if (reg_write(BMP280_CONFIG, bmp280_config.all) != 0) {
+    return -1;
+  }
+
+  return 0;
+}
+
+//******************************************************************************
+float BMP280::ToFahrenheit(float temperature) {
+  return temperature * 9 / 5 + 32;
+}
+
+//******************************************************************************
+int BMP280::ReadCompDataRaw2(char *bmp280_rawData) {
+  int i;
+  char data[6];
+  float temp;
+  float pressure;
+  int iPressure;
+  char str[32];
+  ReadCompDataRaw(data);
+  ToFloat(data, &temp, &pressure);
+  iPressure = (int)pressure;
+  sprintf(str, "%d  ", iPressure);
+  for (i = 0; i < 6; i++) {
+    bmp280_rawData[i] = str[i];
+  }
+  return 0;
+}
+
+//******************************************************************************
+int BMP280::ReadCompDataRaw(char *bmp280_rawData) {
+  char reg;
+  char rxbytes;
+
+  reg = BMP280_PRESS_MSB;
+  rxbytes = 6;
+
+  if (reg_read(reg, bmp280_rawData, rxbytes) != 0) {
+    return -1;
+  }
+  return 0;
+}
+
+//******************************************************************************
+void BMP280::ToFloat(char *bmp280_rawData, float *Temp_degC, float *Press_Pa) {
+  bmp280_rawPress = (uint32_t)(bmp280_rawData[0] << 12) |
+                    (bmp280_rawData[1] << 4) | (bmp280_rawData[2] >> 4);
+
+  bmp280_rawTemp = (uint32_t)(bmp280_rawData[3] << 12) |
+                   (bmp280_rawData[4] << 4) | (bmp280_rawData[5] >> 4);
+
+  *Temp_degC = compensate_T_float(bmp280_rawTemp);
+  *Press_Pa = compensate_P_float(bmp280_rawPress);
+}
+
+//******************************************************************************
+int BMP280::ReadCompData(float *Temp_degC, float *Press_Pa) {
+  char bmp280_rawData[6];
+
+  if (ReadCompDataRaw(bmp280_rawData) != 0) {
+    return -1;
+  }
+  ToFloat(bmp280_rawData, Temp_degC, Press_Pa);
+  return 0;
+}
+
+//******************************************************************************
+int BMP280::reg_write(char reg, char value) {
+  int result;
+  char cmdData[2] = {(char)reg, value};
+  result = i2c->write(slaveAddress, cmdData, 2);
+  if (result != 0)
+    return -1;
+  return 0;
+}
+
+//******************************************************************************
+int BMP280::reg_read(char reg, char *value, char number) {
+  int result;
+  char cmdData[1] = {(char)reg};
+
+  result = i2c->write(slaveAddress, cmdData, 1);
+  if (result != 0)
+    return -1;
+  result = i2c->read(slaveAddress, value, number);
+  if (result != 0)
+    return -1;
+  return 0;
+}
+
+//******************************************************************************
+int BMP280::Sleep(void) {
+  // Configure the I2C interface
+
+  if (reg_read(BMP280_CTRL_MEAS, &bmp280_ctrl_meas.all, 1) != 0) {
+    return -1;
+  }
+  bmp280_ctrl_meas.bit.mode = 0b00; // put everything to sleep mode...
+
+  if (reg_write(BMP280_CTRL_MEAS, bmp280_ctrl_meas.all) != 0) {
+    return -1;
+  }
+  return 0;
+}
+
+//******************************************************************************
+void BMP280::Reset(void) {
+  reg_write(BMP280_RESET, 0xB6); // Initiate a Soft Reset
+}
+
+//******************************************************************************
+int BMP280::Detect(void) {
+  if (reg_read(BMP280_ID, &bmp280_id, 1) != 0) {
+    return -1;
+  }
+
+  if (bmp280_id == 0x58) {
+    return 1;
+  }
+  return 0;
+}
+
+//******************************************************************************
+int BMP280::ReadId(void) {
+  if (reg_read(BMP280_ID, &bmp280_id, 1) != 0) {
+    return -1;
+  }
+  return bmp280_id;
+}
+
+//******************************************************************************
+float BMP280::compensate_T_float(int32_t adc_T) {
+  float var1, var2, T;
+  var1 =
+      (((float)adc_T) / 16384.0 - ((float)dig_T1) / 1024.0) * ((float)dig_T2);
+
+  var2 = ((((float)adc_T) / 131072.0 - ((float)dig_T1) / 8192.0) *
+          (((float)adc_T) / 131072.0 - ((float)dig_T1) / 8192.0)) *
+         ((float)dig_T3);
+
+  t_fine = (int32_t)(var1 + var2);
+
+  T = (var1 + var2) / 5120.0;
+
+  return T;
+}
+
+//******************************************************************************
+float BMP280::compensate_P_float(int32_t adc_P) {
+  float var1, var2, p;
+  var1 = ((float)t_fine / 2.0) - 64000.0;
+  var2 = var1 * var1 * ((float)dig_P6) / 32768.0;
+  var2 = var2 + var1 * ((float)dig_P5) * 2.0;
+  var2 = (var2 / 4.0) + (((float)dig_P4) * 65536.0);
+  var1 = (((float)dig_P3) * var1 * var1 / 524288.0 + ((float)dig_P2) * var1) / 524288.0;
+  var1 = (1.0 + var1 / 32768.0) * ((float)dig_P1);
+  if (var1 == 0.0) {
+    return 0; // avoid exception caused by division by zero
+  }
+  p = 1048576.0 - (float)adc_P;
+  p = (p - (var2 / 4096.0)) * 6250.0 / var1;
+  var1 = ((float)dig_P9) * p * p / 2147483648.0;
+  var2 = p * ((float)dig_P8) / 32768.0;
+  p = p + (var1 + var2 + ((float)dig_P7)) / 16.0;
+  return p;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/e4a10ed6eb92/HSP/Devices/BMP280/BMP280/BMP280.h	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,418 @@
+/*******************************************************************************
+* Copyright (C) 2015 Maxim Integrated Products, Inc., All Rights Reserved.
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included
+* in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+* OTHER DEALINGS IN THE SOFTWARE.
+*
+* Except as contained in this notice, the name of Maxim Integrated
+* Products, Inc. shall not be used except as stated in the Maxim Integrated
+* Products, Inc. Branding Policy.
+*
+* The mere transfer of this software does not imply any licenses
+* of trade secrets, proprietary technology, copyrights, patents,
+* trademarks, maskwork rights, or any other form of intellectual
+* property whatsoever. Maxim Integrated Products, Inc. retains all
+* ownership rights.
+*******************************************************************************/
+/**
+ * Bosch BMP280 Digital Pressure Sensor
+ *
+ * @code
+ * #include <stdio.h>
+ * #include "mbed.h"
+ * #include "xxx.h"
+ *
+ * I2C i2c(I2C_SDA, I2C_SCL);
+ * xxx xxx(&i2c);
+ *
+ * int main(void) {
+ *	   printf("Initialized xxx\n");
+ *     while(1) {
+ *         if (xxx.init() != 0) {
+ *             printf("Error communicating with xxx\n");
+ *         } else {
+ *             printf("Initialized xxx\n");
+ *             break;
+ *         }
+ *         wait(1);
+ *     }
+ *
+ *     while(1) {
+ *         printf("");
+ *         wait(1);
+ *     }
+ * }
+ * @endcode
+ */
+
+#ifndef BMP280_H_
+#define BMP280_H_
+
+#include "mbed.h"
+
+#define BMP280_READID       (0x58)
+
+#define BMP280_TEMP_XLSB    (0xFC)
+#define BMP280_TEMP_LSB     (0xFB)
+#define BMP280_TEMP_MSB     (0xFA)
+
+#define BMP280_PRESS_XLSB   (0xF9)
+#define BMP280_PRESS_LSB    (0xF8)
+#define BMP280_PRESS_MSB    (0xF7)
+
+#define BMP280_CONFIG       (0xF5)
+#define BMP280_CTRL_MEAS    (0xF4)
+#define BMP280_STATUS       (0xF3)
+#define BMP280_RESET        (0xE0)
+#define BMP280_ID           (0xD0)
+
+// calib25-calib00: 0xA1-0x88
+#define BMP280_CALIB25      (0xA1) // Beginning address
+#define BMP280_CALIB00      (0x88) // Ending address
+
+#define BMP280_REGISTER_CHIPID    (0xD0)
+#define BMP280_REGISTER_VERSION   (0xD1)
+#define BMP280_REGISTER_SOFTRESET (0xE0)
+
+#define BMP280_REGISTER_CAL26     (0xE1) // R calibration stored in 0xE1-0xF0
+
+#define BMP280_REGISTER_CONTROL      (0xF4)
+#define BMP280_REGISTER_CONFIG       (0xF5)
+#define BMP280_REGISTER_PRESSUREDATA (0xF7)
+#define BMP280_REGISTER_TEMPDATA     (0xFA)
+
+/**
+ * @brief Bosch BMP280 Digital Pressure Sensor
+ */
+class BMP280 {
+
+public:
+  /**
+   * BMP280 constructor.
+   *
+   * @param sda mbed pin to use for SDA line of I2C interface.
+   * @param scl mbed pin to use for SCL line of I2C interface.
+   * @param slaveAddress Slave Address of the device.
+   */
+  BMP280(PinName sda, PinName scl, int slaveAddress);
+
+  /**
+   * BMP280 constructor.
+   *
+   * @param i2c I2C object to use.
+   * @param slaveAddress Slave Address of the device.
+   */
+  BMP280(I2C *i2c, int slaveAddress);
+
+  char loggingEnabled;
+  char loggingSampleRate;
+
+  /**
+  * Write a device register
+  */
+  int writeReg(char reg, char value);
+  /**
+  * Read a device register
+  */
+  int readReg(char reg, char *value);
+
+  /// @brief TEMP_XLSB (0xFC)
+  char bmp280_temp_xlsb; // Lower 4-bits are all 0's
+
+  /// @brief TEMP_LSB (0xFB)
+  char bmp280_temp_lsb;
+
+  /// @brief TEMP_MSB (0xFA)
+  char bmp280_temp_msb;
+
+  /// @brief PRESS_XLSB (0xF9)
+  char bmp280_press_xlsb; // Lower 4-bits are all 0's
+
+  /// @brief PRESS_LSB (0xF8)
+  char bmp280_press_lsb;
+
+  /// @brief PRESS_MSB (0xF7)
+  char bmp280_press_msb;
+
+  /// @brief CONFIG_REG (0xF5)
+  union bmp280_config_reg {
+    char all;
+    struct {
+      char spi3w_en : 1;
+      char reserved : 1;
+      char filter : 3;
+      char t_sb : 3;
+    } bit;
+  } bmp280_config;
+
+  /// @brief CTRL_MEAS (0xF4)
+  union bmp280_ctrl_meas {
+    char all;
+    struct {
+      char mode : 2;
+      char osrs_p : 3;
+      char osrs_t : 3;
+    } bit;
+  } bmp280_ctrl_meas;
+
+  /// @brief STATUS (0xF3)
+  union bmp280_status {
+    char all;
+    struct {
+      char im_update : 1;
+      char reserved1 : 2;
+      char measuring : 1;
+      char reserved2 : 4;
+    } bit;
+  } bmp280_status;
+
+  /// @brief  RESET (0xE0)
+  char bmp280_reset;
+
+  /// @brief  ID (0xD0)
+  char bmp280_id;
+
+  typedef enum {
+    SKIPPED_P = 0,
+    OVERSAMPLING_X1_P = 1,
+    OVERSAMPLING_X2_P = 2,
+    OVERSAMPLING_X4_P = 3,
+    OVERSAMPLING_X8_P = 4,
+    OVERSAMPLING_X16_P = 5
+  } bmp280_osrs_P_t;
+
+  typedef enum {
+    SKIPPED_T = 0,
+    OVERSAMPLING_X1_T = 1,
+    OVERSAMPLING_X2_T = 2,
+    OVERSAMPLING_X4_T = 3,
+    OVERSAMPLING_X8_T = 4,
+    OVERSAMPLING_X16_T = 5
+  } bmp280_osrs_T_t;
+
+  typedef enum {
+    FILT_OFF = 1,
+    FILT_2 = 2,
+    FILT_3 = 4,
+    FILT_4 = 8,
+    FILT_5 = 16
+  } bmp280_FILT_t;
+
+  typedef enum {
+    SLEEP_MODE = 0,
+    FORCED_MODE = 1,
+    NORMAL_MODE = 3
+  } bmp280_MODE_t;
+
+  typedef enum {
+    T_0_5 = 0,
+    T_62_5 = 1,
+    T_125 = 2,
+    T_250 = 3,
+    T_500 = 4,
+    T_1000 = 5,
+    T_2000 = 6,
+    T_4000 = 7
+  } bmp280_TSB_t;
+
+  /// @brief calib25... calib00  (0xA1...0x88)
+  char bmp280_Calib[26];
+
+  uint16_t dig_T1;
+  int16_t dig_T2;
+  int16_t dig_T3;
+
+  uint16_t dig_P1;
+  int16_t dig_P2;
+  int16_t dig_P3;
+  int16_t dig_P4;
+  int16_t dig_P5;
+  int16_t dig_P6;
+  int16_t dig_P7;
+  int16_t dig_P8;
+  int16_t dig_P9;
+
+  int32_t t_fine; // This is calculated int the temperature to be used by the
+                  // pressure
+
+  int32_t bmp280_rawPress;
+  int32_t bmp280_rawTemp;
+
+  float Temp_degC; //  Deg C.
+  float Press_Pa;  //   Pascal.
+
+  /**
+   * BMP280 constructor.
+   *
+   * @param sda mbed pin to use for SDA line of I2C interface.
+   * @param scl mbed pin to use for SCL line of I2C interface.
+   */
+  BMP280(PinName sda, PinName scl);
+
+  /**
+   * BMP280 constructor.
+   *
+   * @param i2c I2C object to use.
+   */
+  BMP280(I2C *i2c);
+
+  /**
+   * BMP280 destructor.
+   */
+  ~BMP280(void);
+
+  // Function Prototypes
+
+  /**
+  * @brief This initializes the BMP280 
+  * @brief The BMP280 has 2 modes. FORCED mode and  NORMAL mode.  FORCED Mode gives more
+  * @brief control to the processor as the processor sends out the Mode to initiate a conversion
+  * @brief and a data is sent out then. NORMAL mode is initialized once and it just runs and sends
+  * @brief out data at a programmed timed interval.  (In this example the main() will set this to Normal
+  * @brief function)
+  * @param Osrs_p- Pressure oversampling
+  * @param Osrs_t-  Temperature oversampling
+  * @param Filter-  Filter Settings
+  * @param Mode-    Power Modes
+  * @param T_sb-    Standby time (used with Normal mode)
+  * @param dig_T1, dig_T2, dig_T3-  Coeffs used for temp conversion - GLOBAL variables (output)
+  * @param dig_P1, ....  , dig_P9-  Coeffs used for press conversion - GLOBAL variables (output)
+  * @returns  0-if no error.  A non-zero value indicates an error.
+  */
+  int init(bmp280_osrs_P_t Osrs_p, bmp280_osrs_T_t Osrs_t, bmp280_FILT_t Filter,
+           bmp280_MODE_t Mode, bmp280_TSB_t T_sb);
+
+  /**
+   * @brief The BMP280 has 2 modes. FORCED mode and  NORMAL mode.  FORCED Mode
+   * gives more
+   * @brief control to the processor as the processor sends out the Mode to
+   * initiate a conversion
+   * @brief and a data is sent out then. NORMAL mode is initialized once and it
+   * just runs and sends
+   * @brief out data at a programmed timed interval.  (In this example the
+   * main() will set this to Normal
+   * @brief function)
+   * @param *Temp_degC - Pointer to temperature (result in deg C)
+   * @param *Press_Pa - Pointer to pressure (resul in Pascal)
+   * @returns 0-if no error.  A non-zero value indicates an error.
+   */
+  int ReadCompData(float *Temp_degC, float *Press_Pa);
+
+  /**
+   *  @brief This function allows writing to a register.
+   *  @param reg- Address of the register to write to
+   *  @param value- Data written to the register
+   *  @returns 0-if no error.  A non-zero value indicates an error.
+   */
+  int reg_write(char reg, char value);
+
+  /**
+   * @brief This function allows writing to a register.
+   * @params reg- Address of the register to read from (input)
+   * @params *value- Pointer to the value read from the register (output)
+   * @returns 0-if no error.  A non-zero value indicates an error.
+   */
+  int reg_read(char reg, char *value, char number);
+
+  /**
+   * @brief Performs a soft reset on the BMP280
+   * @param none
+   * @returns none
+   */
+  void Reset(void);
+
+  /**
+   * @brief Detects if the BMP280 is present
+   * @param none
+   * @returns 1 for found, 0 for not found, -1 for comm error
+   */
+  int Detect(void);
+
+  /**
+   * @brief Performs calculations on the raw temperature data to convert to
+   * @brief temperature in deg C, based on Bosch's algorithm
+   * @param Raw Temp ADC value, Global dig_T1, dig_T2, dig_T3
+   * @returns The Temperature in deg C
+   */
+  float compensate_T_float(int32_t adc_T); // returned value Deg C.
+
+  /**
+    * @brief Performs calculations on the raw pressure data to convert to
+    * @brief pressure in Pascal, based on Bosch's algorithm
+    * @param adc_P Raw Press ADC value, Global dig_P1, dig_P2,..., dig_P9
+    * @returns The Pressure in Pascals
+    */
+  float compensate_P_float(int32_t adc_P); //  returned value Pascal.
+
+  /**
+   * @brief Puts the BMP280 in low power Sleep mode
+   * @param none
+   * @returns 0 if no errors, -1 if error.
+   */
+  int Sleep(void);
+
+  /**
+   * @brief This reads the raw BMP280 data
+   * @param *bmp280_rawData- array of raw output data
+   * @returns 0-if no error.  A non-zero value indicates an error.
+   *
+   */
+  int ReadCompDataRaw(char *bmp280_rawData);
+  /**
+   * @brief This reads the raw BMP280 data uses the Bosch algorithm to get the
+   * data
+   * @brief in float, then the float gets converted to an String
+   * @param *bmp280_rawData- array of raw output data
+   * @returns 0-if no error.  A non-zero value indicates an error.
+   *
+   */
+  int ReadCompDataRaw2(char *bmp280_rawData);
+  /**
+   * @brief This converts the raw BMP280 data to couble based on Bosch's
+   * algorithm
+   * @param *bmp280_rawData- array of raw input data
+   * @param *Temp_degC- pointer to output, Temp value in deg C
+   * @param *Press_Pa- pointer to output, Press value in Pascals
+   * @returns 0-if no error.  A non-zero value indicates an error.
+   *
+   */
+  void ToFloat(char *bmp280_rawData, float *Temp_degC, float *Press_Pa);
+  /**
+   * @brief converts to Farenhite from Centigrade
+   * @param temperature in Centigrade
+   * @returns temperature value in Farenhite
+   */
+  float ToFahrenheit(float temperature);
+
+  /**
+   * @brief Reads a unique ID from the register
+   * @param none
+   * @returns The correct id value which is 0x58
+   */
+  int ReadId(void);
+
+private:
+  /// I2C pointer
+  I2C *i2c;
+  /// Is this object the owner of the I2C object
+  bool isOwner;
+  /// Device slave address
+  int slaveAddress;
+};
+
+#endif // BMP280_H_
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/e4a10ed6eb92/HSP/Devices/BMP280/BMP280_RPC.cpp	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,52 @@
+/*******************************************************************************
+ * Copyright (C) 2016 Maxim Integrated Products, Inc., All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+ * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Except as contained in this notice, the name of Maxim Integrated
+ * Products, Inc. shall not be used except as stated in the Maxim Integrated
+ * Products, Inc. Branding Policy.
+ *
+ * The mere transfer of this software does not imply any licenses
+ * of trade secrets, proprietary technology, copyrights, patents,
+ * trademarks, maskwork rights, or any other form of intellectual
+ * property whatsoever. Maxim Integrated Products, Inc. retains all
+ * ownership rights.
+ *******************************************************************************
+ */
+
+#include "BMP280_RPC.h"
+#include "BMP280.h"
+#include "StringHelper.h"
+#include "Peripherals.h"
+#include "Device_Logging.h"
+
+extern Device_Logging *bmp280_Logging;
+
+
+int BMP280_InitStart(char argStrs[32][32], char replyStrs[32][32]) {
+  uint8_t args[1];
+  uint8_t reply[1];
+
+  ProcessArgs(argStrs, args, sizeof(args));
+  bmp280_Logging->initStart(args[0]);
+  reply[0] = 0x80;
+  FormatReply(reply, sizeof(reply), replyStrs);
+  return 0;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/e4a10ed6eb92/HSP/Devices/BMP280/BMP280_RPC.h	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,47 @@
+/*******************************************************************************
+ * Copyright (C) 2016 Maxim Integrated Products, Inc., All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+ * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Except as contained in this notice, the name of Maxim Integrated
+ * Products, Inc. shall not be used except as stated in the Maxim Integrated
+ * Products, Inc. Branding Policy.
+ *
+ * The mere transfer of this software does not imply any licenses
+ * of trade secrets, proprietary technology, copyrights, patents,
+ * trademarks, maskwork rights, or any other form of intellectual
+ * property whatsoever. Maxim Integrated Products, Inc. retains all
+ * ownership rights.
+ *******************************************************************************
+ */
+#ifndef _BMP280_RPC_H_
+#define _BMP280_RPC_H_
+
+#include "mbed.h"
+
+/**
+* @brief Read the identification of the s25fs512 using quad spi
+* @param argStrs incoming rpc argument strings
+*  OUTPUT:
+*		replyStrs: strings that get returned to the rpc caller
+* @return 0 if successful, -1 if error
+*/
+int BMP280_InitStart(char argStrs[32][32], char replyStrs[32][32]);
+
+#endif /* _BMP280_RPC_H_ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/e4a10ed6eb92/HSP/Devices/HspLed/HspLed/HspLed.cpp	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,143 @@
+/*******************************************************************************
+ * Copyright (C) 2016 Maxim Integrated Products, Inc., All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+ * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Except as contained in this notice, the name of Maxim Integrated
+ * Products, Inc. shall not be used except as stated in the Maxim Integrated
+ * Products, Inc. Branding Policy.
+ *
+ * The mere transfer of this software does not imply any licenses
+ * of trade secrets, proprietary technology, copyrights, patents,
+ * trademarks, maskwork rights, or any other form of intellectual
+ * property whatsoever. Maxim Integrated Products, Inc. retains all
+ * ownership rights.
+ *******************************************************************************
+ */
+
+#include "HspLed.h"
+#include "Peripherals.h"
+
+void hspled_int_handler(void);
+
+//*******************************************************************************
+HspLed::HspLed(PinName ledPin) : 
+      redLed(LED_RED, 0), isStarted(false), timerIntervalLast(-1), timerInterval(500) {
+}
+
+
+//*******************************************************************************
+void HspLed::state(int state) { 
+  redLed.write(state); 
+}
+
+
+//*******************************************************************************
+void HspLed::toggle(void) { 
+  state(!redLed.read()); 
+}
+
+
+//*******************************************************************************
+void HspLed::setMode(eMode mode) { 
+  this->mode = mode; 
+}
+
+//*******************************************************************************
+void HspLed::blink(uint32_t mSeconds) {
+  mode = eLedPeriod;
+  this->timerInterval = (float)mSeconds / 1000.0f;
+  start();
+}
+
+//*******************************************************************************
+void HspLed::pattern(uint32_t bitPattern, uint32_t mSeconds) {
+  mode = eLedPattern;
+  this->bitPattern = bitPattern;
+  this->timerInterval = (float)mSeconds / 1000.0f;
+  start();
+}
+
+//*******************************************************************************
+void HspLed::on(void) {
+  mode = eLedOn;
+  state(HSP_LED_ON);
+  start();
+}
+
+
+//*******************************************************************************
+void HspLed::off(void) {
+  mode = eLedOff;
+  state(HSP_LED_OFF);
+  start();
+}
+
+
+//*******************************************************************************
+void HspLed::patternToLed(void) {
+  uint32_t bit;
+  bit = bitPattern & 1;
+  state(bit);
+  // rotate the pattern
+  bitPattern = bitPattern >> 1;
+  bitPattern = bitPattern | (bit << 31);
+}
+
+
+//*******************************************************************************
+void HspLed::service(void) {
+  switch (mode) {
+  case eLedOn:
+    state(HSP_LED_ON);
+    break;
+  case eLedOff:
+    state(HSP_LED_OFF);
+    break;
+  case eLedPeriod:
+    toggle();
+    break;
+  case eLedPattern:
+    patternToLed();
+    break;
+  }
+}
+
+//*******************************************************************************
+void HspLed::start(void) {
+  if (timerInterval != timerIntervalLast && isStarted == true) {
+    stop();
+  }
+  ticker.attach(&hspled_int_handler, timerInterval);
+  timerIntervalLast = timerInterval;
+
+  isStarted = true;
+}
+
+//*******************************************************************************
+void HspLed::stop(void) {
+  ticker.detach();
+  isStarted = false;
+}
+
+//*******************************************************************************
+void hspled_int_handler(void) {
+  HspLed *hspLed = Peripherals::hspLed();
+  hspLed->service();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/e4a10ed6eb92/HSP/Devices/HspLed/HspLed/HspLed.h	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,169 @@
+/*******************************************************************************
+ * Copyright (C) 2016 Maxim Integrated Products, Inc., All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+ * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Except as contained in this notice, the name of Maxim Integrated
+ * Products, Inc. shall not be used except as stated in the Maxim Integrated
+ * Products, Inc. Branding Policy.
+ *
+ * The mere transfer of this software does not imply any licenses
+ * of trade secrets, proprietary technology, copyrights, patents,
+ * trademarks, maskwork rights, or any other form of intellectual
+ * property whatsoever. Maxim Integrated Products, Inc. retains all
+ * ownership rights.
+ *******************************************************************************
+ */
+#ifndef _LED_H_
+#define _LED_H_
+
+#include "mbed.h"
+
+/**
+ * Driver for the HSP Led, supports different blink rates and patterns
+ *
+ * @code
+ * #include <stdio.h>
+ * #include "mbed.h"
+ * #include "xxx.h"
+ *
+ * I2C i2c(I2C_SDA, I2C_SCL);
+ * xxx xxx(&i2c);
+ *
+ * int main(void) {
+ *	   printf("Initialized xxx\n");
+ *     while(1) {
+ *         if (xxx.init() != 0) {
+ *             printf("Error communicating with xxx\n");
+ *         } else {
+ *             printf("Initialized xxx\n");
+ *             break;
+ *         }
+ *         wait(1);
+ *     }
+ *
+ *     while(1) {
+ *         printf("");
+ *         wait(1);
+ *     }
+ * }
+ * @endcode
+ */
+
+class HspLed {
+public:
+  static const int LED_ON = 0;
+  static const int LED_OFF = 1;
+
+  /// define all of the modes the LED can support
+  typedef enum eMode {
+    eLedOn,
+    eLedOff,
+    eLedPeriod,
+    eLedPattern
+  } eMode;
+  /// define the values that turn the LED on or off at the pin
+  #define HSP_LED_ON 0
+  #define HSP_LED_OFF 1
+
+  /*
+  * @brief Constructor where you specify the LED pin name
+  */
+  HspLed(PinName ledPin);
+  
+  /**
+  * Blink the HSP LED at a set time interval
+  * @param mSeconds Number of seconds to set the timer interval
+  */
+  void blink(uint32_t mSeconds);
+  
+  /**
+  * @brief Start rotating the LED through a 32-bit pattern at a mS rate specified
+  * @param pattern 32-bit pattern to rotate through
+  * @param mSeconds the amount of time to take per bit in the pattern
+  */ 
+  void pattern(uint32_t pattern, uint32_t mSeconds);
+  
+  /**
+  * @brief Turn the LED on
+  */
+  void on(void);
+  
+  /**
+  * @brief Turn the LED off
+  */
+  void off(void);
+
+  /**
+  * @brief Update the LED
+  */ 
+  void service(void);
+
+private:
+
+  /**
+  * Set the mode of the LED, the mode include blinking at a set rate or blinking
+  * according to a pattern
+  * @param mode Mode to set the LED to
+  */
+  void setMode(eMode state);
+  
+  /**
+  * Toggle the state of the LED
+  */
+  void toggle(void);
+
+  /**
+  * Start the LED blinking or rotating through a pattern
+  */
+  void start(void);
+
+  /**
+  * Stop blinking or rotating through a pattern
+  */
+  void stop(void);
+  
+  /**
+  * Write the LED pin to a state
+  * @param state A one or zero value to write to the LED pin
+  */  
+  void state(int state);
+
+  /*
+  * @brief Single step through the pattern and output to the LED
+  */
+  void patternToLed(void);
+
+  /// timer interval in mS
+  float timerInterval;
+  /// last timer interval set to... used to prevent resetting the timer to the same value
+  float timerIntervalLast;
+  /// local state of the pattern to rotate through
+  uint32_t bitPattern;
+  /// current mode of the LED
+  eMode mode;
+  /// the LED digital output
+  DigitalOut redLed;
+  /// Timer service used to update the LED
+  Ticker ticker;
+  /// Flag to indicate if the timer has been started
+  bool isStarted;
+};
+
+#endif /* _LED_H_ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/e4a10ed6eb92/HSP/Devices/HspLed/HspLed_RPC.cpp	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,73 @@
+/*******************************************************************************
+ * Copyright (C) 2016 Maxim Integrated Products, Inc., All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+ * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Except as contained in this notice, the name of Maxim Integrated
+ * Products, Inc. shall not be used except as stated in the Maxim Integrated
+ * Products, Inc. Branding Policy.
+ *
+ * The mere transfer of this software does not imply any licenses
+ * of trade secrets, proprietary technology, copyrights, patents,
+ * trademarks, maskwork rights, or any other form of intellectual
+ * property whatsoever. Maxim Integrated Products, Inc. retains all
+ * ownership rights.
+ *******************************************************************************
+ */
+
+#include "HspLed_RPC.h"
+#include "HspLed.h"
+#include "StringHelper.h"
+#include "Peripherals.h"
+
+int Led_On(char argStrs[32][32], char replyStrs[32][32]) {
+  uint32_t reply[1];
+  Peripherals::hspLed()->on();
+  reply[0] = 0x80;
+  FormatReply32(reply, sizeof(reply) / sizeof(uint32_t), replyStrs);
+  return 0;
+}
+
+int Led_Off(char argStrs[32][32], char replyStrs[32][32]) {
+  uint32_t reply[1];
+  Peripherals::hspLed()->off();
+  reply[0] = 0x80;
+  FormatReply32(reply, sizeof(reply) / sizeof(uint32_t), replyStrs);
+  return 0;
+}
+
+int Led_BlinkHz(char argStrs[32][32], char replyStrs[32][32]) {
+  uint32_t args[1];
+  uint32_t reply[1];
+  ProcessArgs32(argStrs, args, sizeof(args) / sizeof(uint32_t));
+  Peripherals::hspLed()->blink(args[0]);
+  reply[0] = 0x80;
+  FormatReply32(reply, sizeof(reply) / sizeof(uint32_t), replyStrs);
+  return 0;
+}
+
+int Led_BlinkPattern(char argStrs[32][32], char replyStrs[32][32]) {
+  uint32_t args[2];
+  uint32_t reply[1];
+  ProcessArgs32(argStrs, args, sizeof(args) / sizeof(uint32_t));
+  Peripherals::hspLed()->pattern(args[0], args[1]);
+  reply[0] = 0x80;
+  FormatReply32(reply, sizeof(reply) / sizeof(uint32_t), replyStrs);
+  return 0;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/e4a10ed6eb92/HSP/Devices/HspLed/HspLed_RPC.h	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,43 @@
+/*******************************************************************************
+ * Copyright (C) 2016 Maxim Integrated Products, Inc., All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+ * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Except as contained in this notice, the name of Maxim Integrated
+ * Products, Inc. shall not be used except as stated in the Maxim Integrated
+ * Products, Inc. Branding Policy.
+ *
+ * The mere transfer of this software does not imply any licenses
+ * of trade secrets, proprietary technology, copyrights, patents,
+ * trademarks, maskwork rights, or any other form of intellectual
+ * property whatsoever. Maxim Integrated Products, Inc. retains all
+ * ownership rights.
+ *******************************************************************************
+ */
+#ifndef _LED_RPC_H_
+#define _LED_RPC_H_
+
+#include "mbed.h"
+
+int Led_On(char argStrs[32][32], char replyStrs[32][32]);
+int Led_Off(char argStrs[32][32], char replyStrs[32][32]);
+int Led_BlinkHz(char argStrs[32][32], char replyStrs[32][32]);
+int Led_BlinkPattern(char argStrs[32][32], char replyStrs[32][32]);
+
+#endif /* _LED_RPC_H_ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/e4a10ed6eb92/HSP/Devices/LIS2DH/LIS2DH/LIS2DH.cpp	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,278 @@
+/*******************************************************************************
+ * Copyright (C) 2016 Maxim Integrated Products, Inc., All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+ * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Except as contained in this notice, the name of Maxim Integrated
+ * Products, Inc. shall not be used except as stated in the Maxim Integrated
+ * Products, Inc. Branding Policy.
+ *
+ * The mere transfer of this software does not imply any licenses
+ * of trade secrets, proprietary technology, copyrights, patents,
+ * trademarks, maskwork rights, or any other form of intellectual
+ * property whatsoever. Maxim Integrated Products, Inc. retains all
+ * ownership rights.
+ *******************************************************************************
+ */
+
+#include "LIS2DH.h"
+#include "Streaming.h"
+#include "Peripherals.h"
+
+void lis2dh_int_handler(void);
+/** buffer array to hold fifo contents for packetizing
+*/
+uint32_t lis2dh_buffer[LIS2DH_MAX_DATA_SIZE];
+
+static int debug_int_count = 0;
+int16_t motion_cached[3];
+LIS2DH *LIS2DH::instance = NULL;
+
+//******************************************************************************
+LIS2DH::LIS2DH(PinName sda, PinName scl, int slaveAddress) : 
+        slaveAddress(slaveAddress) {
+  i2c = new I2C(sda, scl);
+  i2c->frequency(400000);
+  isOwner = true;
+  instance = this;
+}
+
+//******************************************************************************
+LIS2DH::LIS2DH(I2C *i2c, int slaveAddress) : 
+        slaveAddress(slaveAddress) {
+  this->i2c = i2c;
+  i2c->frequency(400000);
+  isOwner = false;
+  instance = this;
+}
+
+//******************************************************************************
+LIS2DH::~LIS2DH(void) {
+  if (isOwner == true) {
+    delete i2c;
+  }
+}
+
+//******************************************************************************
+int LIS2DH::writeReg(char reg, char value) {
+  int result;
+  char cmdData[2] = {(char)reg, value};
+  result = i2c->write(slaveAddress, cmdData, 2);
+  if (result != 0)
+    return -1;
+  return 0;
+}
+
+//******************************************************************************
+int LIS2DH::readReg(char reg, char *value) {
+  int result;
+  char cmdData[1] = {(char)reg};
+
+  result = i2c->write(slaveAddress, cmdData, 1);
+  if (result != 0)
+    return -1;
+  result = i2c->read(slaveAddress, value, 1);
+  if (result != 0)
+    return -1;
+  return 0;
+}
+
+//******************************************************************************
+static void I2c_Reset(uint8_t index, int speed) {
+  mxc_i2cm_regs_t *regs = MXC_I2CM_GET_I2CM(index);
+  /* reset module */
+  regs->ctrl = MXC_F_I2CM_CTRL_MSTR_RESET_EN;
+  regs->ctrl = 0;
+  /* enable tx_fifo and rx_fifo */
+  regs->ctrl |= (MXC_F_I2CM_CTRL_TX_FIFO_EN | MXC_F_I2CM_CTRL_RX_FIFO_EN);
+}
+
+//******************************************************************************
+//  Interrupt handler, this empties the hardware fifo and packetizes it for
+//  streaming
+void LIS2DH::int_handler(void) {
+  char fifo_src;
+  int16_t valueX;
+  int16_t valueY;
+  int16_t valueZ;
+  int num;
+  int index;
+
+  I2c_Reset(2, 1);
+  num = 0;
+  index = 0;
+  fifo_src = 0;
+  while ((fifo_src & 0x20) != 0x20) {
+    get_motion_fifo(&valueX, &valueY, &valueZ);
+    lis2dh_buffer[index++] = valueX;
+    lis2dh_buffer[index++] = valueY;
+    lis2dh_buffer[index++] = valueZ;
+    readReg(LIS2DH_FIFO_SRC_REG, &fifo_src);
+    num++;
+    if (num >= 32)
+      break;
+  }
+  motion_cached[0] = valueX;
+  motion_cached[1] = valueY;
+  motion_cached[2] = valueZ;
+
+  StreamPacketUint32(PACKET_LIS2DH, lis2dh_buffer, index);
+}
+
+//******************************************************************************
+void LIS2DH::init(void) {
+  stop();
+  configure_interrupt();
+}
+
+//******************************************************************************
+void LIS2DH::configure_interrupt(void) {
+  // interrupt enabled on INT1, interrupt active low
+  lis2dh_ctrl_reg6.all = 0;
+  lis2dh_ctrl_reg6.bit.I2_INT1 = 1;      // interrupt 1 function enabled on int1 pin
+  lis2dh_ctrl_reg6.bit.H_LACTIVE = 1;    // interrupt active low
+  writeReg(LIS2DH_CTRL_REG6, lis2dh_ctrl_reg6.all);
+}
+
+//******************************************************************************
+int LIS2DH::initStart(int dataRate, int fifoThreshold) {
+  __disable_irq();
+
+  configure_interrupt();
+
+  // enable FIFO
+  lis2dh_ctrl_reg5.all = 0x0;
+  lis2dh_ctrl_reg5.bit.FIFO_EN = 0x1;
+  if (writeReg(LIS2DH_CTRL_REG5, lis2dh_ctrl_reg5.all) == -1) {
+    __enable_irq();
+    return -1;
+  }
+
+  // set FIFO to stream mode, trigger select INT1
+  lis2dh_fifo_ctrl_reg.all = 0x0;
+  lis2dh_fifo_ctrl_reg.bit.FTH = fifoThreshold;
+  lis2dh_fifo_ctrl_reg.bit.FM = LIS2DH_FIFOMODE_STREAM;
+  lis2dh_fifo_ctrl_reg.bit.TR = 0x0;
+  if (writeReg(LIS2DH_FIFO_CTRL_REG, lis2dh_fifo_ctrl_reg.all) == -1) {
+    __enable_irq();
+    return -1;
+  }
+
+  // set HR (high resolution)
+  if (writeReg(LIS2DH_CTRL_REG4, 0x8) == -1) {
+    __enable_irq();
+    return -1;
+  }
+
+  // set the data rate, enable all axis
+  dataRate = dataRate & 0xF;
+  if (dataRate > 0x9) dataRate = 0x9;
+  lis2dh_ctrl_reg1.bit.ODR = dataRate; // set the data rate
+  lis2dh_ctrl_reg1.bit.LPen = 0x0;     // disable low power mode
+  lis2dh_ctrl_reg1.bit.Zen = 0x1;      // enable z
+  lis2dh_ctrl_reg1.bit.Yen = 0x1;      // enable y
+  lis2dh_ctrl_reg1.bit.Xen = 0x1;      // enable x
+  if (writeReg(LIS2DH_CTRL_REG1, lis2dh_ctrl_reg1.all) == -1) {
+    __enable_irq();
+    return -1;
+  }
+
+  // enable watermark interrupt
+  lis2dh_ctrl_reg3.all = 0x00;
+  lis2dh_ctrl_reg3.bit.I1_WTM = 0x1;
+  if (writeReg(LIS2DH_CTRL_REG3, lis2dh_ctrl_reg3.all) == -1) {
+    __enable_irq();
+    return -1;
+  }
+  __enable_irq();
+
+  return 0;
+}
+
+//******************************************************************************
+int LIS2DH::detect(char *detected) {
+  char val;
+  *detected = 0;
+  if (readReg(LIS2DH_WHO_AM_I, &val) == -1)
+    return -1;
+  if (val == LIS2DH_ID) *detected = 1;
+  return 0;
+}
+
+//******************************************************************************
+int LIS2DH::get_motion_cached(int16_t *valueX, int16_t *valueY,
+                              int16_t *valueZ) {
+  *valueX = motion_cached[0];
+  *valueY = motion_cached[1];
+  *valueZ = motion_cached[2];
+  return 0;
+}
+
+//******************************************************************************
+int LIS2DH::get_motion_fifo(int16_t *valueX, int16_t *valueY, int16_t *valueZ) {
+  char reg = LIS2DH_OUT_X_L | 0x80;
+  char values[6];
+  int i;
+
+  reg = LIS2DH_OUT_X_L;
+  for (i = 0; i < 6; i++) {
+    if (readReg(reg, &values[i]) != 0) {
+      return -1;
+    }
+    reg++;
+  }
+
+  *valueX = ((short)values[1] << 8) + values[0];
+  *valueY = ((short)values[3] << 8) + values[2];
+  *valueZ = ((short)values[5] << 8) + values[4];
+  motion_cached[0] = *valueX;
+  motion_cached[1] = *valueY;
+  motion_cached[2] = *valueZ;
+  return 0;
+}
+
+//******************************************************************************
+// 0x33 = read ID
+char LIS2DH::readId(void) {
+  char val;
+  readReg(LIS2DH_WHO_AM_I, &val);
+  return val;
+}
+
+//******************************************************************************
+void LIS2DH::stop(void) {
+  __disable_irq();
+  writeReg(LIS2DH_CTRL_REG3, 0x00); // Disable watermark interrupt
+  writeReg(LIS2DH_CTRL_REG1, 0x00); // Data rate = 0Hz
+  writeReg(LIS2DH_FIFO_CTRL_REG,
+           0x00);                   // set to bypass mode... clears FIFO_SRC_REG
+  __enable_irq();
+}
+
+//******************************************************************************
+void LIS2DHIntHandler(void) {
+  char value;
+  // read the data rate axis enable register, if this is zero then just return,
+  // we are not ready for interrupts
+  LIS2DH::instance->readReg(LIS2DH_CTRL_REG1, &value);
+  if (value == 0x0) {
+    return;
+  }
+  LIS2DH::instance->int_handler();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/e4a10ed6eb92/HSP/Devices/LIS2DH/LIS2DH/LIS2DH.h	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,462 @@
+/*******************************************************************************
+ * Copyright (C) 2016 Maxim Integrated Products, Inc., All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+ * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Except as contained in this notice, the name of Maxim Integrated
+ * Products, Inc. shall not be used except as stated in the Maxim Integrated
+ * Products, Inc. Branding Policy.
+ *
+ * The mere transfer of this software does not imply any licenses
+ * of trade secrets, proprietary technology, copyrights, patents,
+ * trademarks, maskwork rights, or any other form of intellectual
+ * property whatsoever. Maxim Integrated Products, Inc. retains all
+ * ownership rights.
+ *******************************************************************************
+ */
+
+#ifndef LIS2DH_H_
+#define LIS2DH_H_
+
+#include "mbed.h"
+
+/**
+ * Driver for the LIS2DH on the HSP Platform
+ *
+ * @code
+ * #include <stdio.h>
+ * #include "mbed.h"
+ * #include "xxx.h"
+ *
+ * I2C i2c(I2C_SDA, I2C_SCL);
+ * xxx xxx(&i2c);
+ *
+ * int main(void) {
+ *	   printf("Initialized xxx\n");
+ *     while(1) {
+ *         if (xxx.init() != 0) {
+ *             printf("Error communicating with xxx\n");
+ *         } else {
+ *             printf("Initialized xxx\n");
+ *             break;
+ *         }
+ *         wait(1);
+ *     }
+ *
+ *     while(1) {
+ *         printf("");
+ *         wait(1);
+ *     }
+ * }
+ * @endcode
+ */
+
+void LIS2DHIntHandler(void);
+
+#define LIS2DH_READID 0x33
+
+/// @brief LIS2DH Register addresses
+#define LIS2DH_STATUS_REG_AUX  0x07
+#define LIS2DH_OUT_TEMP_L      0x0C
+#define LIS2DH_OUT_TEMP_H      0x0D
+#define LIS2DH_INT_COUNTER_REG 0x0E
+#define LIS2DH_WHO_AM_I        0x0F
+#define LIS2DH_TEMP_CFG_REG    0x1F
+#define LIS2DH_CTRL_REG1       0x20
+#define LIS2DH_CTRL_REG2       0x21
+#define LIS2DH_CTRL_REG3       0x22
+#define LIS2DH_CTRL_REG4       0x23
+#define LIS2DH_CTRL_REG5       0x24
+#define LIS2DH_CTRL_REG6       0x25
+#define LIS2DH_REFERENCE       0x26
+#define LIS2DH_STATUS_REG2     0x27
+#define LIS2DH_OUT_X_L         0x28
+#define LIS2DH_OUT_X_H         0x29
+#define LIS2DH_OUT_Y_L         0x2A
+#define LIS2DH_OUT_Y_H         0x2B
+#define LIS2DH_OUT_Z_L         0x2C
+#define LIS2DH_OUT_Z_H         0x2D
+#define LIS2DH_FIFO_CTRL_REG   0x2E
+#define LIS2DH_FIFO_SRC_REG    0x2F
+#define LIS2DH_INT1_CFG        0x30
+#define LIS2DH_INT1_SRC        0x31
+#define LIS2DH_INT1_THS        0x32
+#define LIS2DH_INT1_DURATION   0x33
+#define LIS2DH_INT2_CFG        0x34
+#define LIS2DH_INT2_SRC        0x35
+#define LIS2DH_INT2_THS        0x36
+#define LIS2DH_INT2_DURATION   0x37
+#define LIS2DH_CLICK_CFG       0x38
+#define LIS2DH_CLICK_SRC       0x39
+#define LIS2DH_CLICK_THS       0x3A
+#define LIS2DH_TIME_LIMIT      0x3B
+#define LIS2DH_TIME_LATENCY    0x3C
+#define LIS2DH_TIME_WINDOW     0x3D
+#define LIS2DH_Act_THS         0x3E
+#define LIS2DH_Act_DUR         0x3F
+
+#define LIS2DH_DATARATE_1HZ    0x1
+#define LIS2DH_DATARATE_10HZ   0x2
+#define LIS2DH_DATARATE_25HZ   0x3
+#define LIS2DH_DATARATE_50HZ   0x4
+#define LIS2DH_DATARATE_100HZ  0x5
+#define LIS2DH_DATARATE_200HZ  0x6
+#define LIS2DH_DATARATE_400HZ  0x7
+
+#define LIS2DH_FIFOMODE_BYPASS  0x00
+#define LIS2DH_FIFOMODE_FIFO    0x01
+#define LIS2DH_FIFOMODE_STREAM  0x02
+#define LIS2DH_FIFOMODE_TRIGGER 0x03
+
+#define LIS2DH_ID 0x33
+#define LIS2DH_FIFO_SIZE 32
+
+#define LISD2DH_FIFO_MODE_BYPASS  0
+#define LISD2DH_FIFO_MODE_FIFO    1
+#define LISD2DH_FIFO_MODE_STREAM  2
+#define LISD2DH_FIFO_MODE_TRIGGER 3
+
+#define LIS2DH_NUMBER_OF_AXIS  3
+#define LIS2DH_MAX_DATA_SIZE   (LIS2DH_NUMBER_OF_AXIS * LIS2DH_FIFO_SIZE)
+
+class LIS2DH {
+public:
+  /// @brief STATUS_AUX (07h)
+  union lis2dh_status_aux_reg {
+    char all;
+    struct {
+      char reserved3 : 2;
+      char TDA       : 1;
+      char reserved2 : 3;
+      char TOR       : 1;
+      char reserved1 : 1;
+    } bit;
+  } lis2dh_status_aux;
+
+  /// @brief OUT_TEMP_L (0Ch)
+  union lis2dh_out_temp_l_reg {
+    char all;
+  } lis2dh_out_temp_l;
+
+  /// @brief OUT_TEMP_H (0Dh)
+  union lis2dh_out_temp_h_reg {
+    char all;
+  } lis2dh_out_temp_h;
+
+  /// @brief INT_COUNTER (0Eh)
+  union lis2dh_int_counter_reg {
+    char all;
+  } lis2dh_int_counter;
+
+  /// @brief WHO_AM_I (0Fh)
+  union lis2dh_who_am_i_reg {
+    char all;
+  } lis2dh_who_am_i;
+
+  /// @brief TEMP_CFG_REG (1Fh)
+  union lis2dh_temp_cfg_reg {
+    char all;
+    struct {
+      char reserved1 : 6;
+      char TEMP_EN0  : 1;
+      char TEMP_EN1  : 1;
+    } bit;
+  } lis2dh_temp_cfg;
+
+  /// @brief CTRL_REG1 (20h)
+  union lis2dh_ctrl_reg1_reg {
+    char all;
+    struct {
+      char Xen  : 1;
+      char Yen  : 1;
+      char Zen  : 1;
+      char LPen : 1;
+      char ODR  : 4;
+    } bit;
+  } lis2dh_ctrl_reg1;
+
+  /// @brief CTRL_REG1 (21h)
+  union lis2dh_ctrl_reg2_reg {
+    char all;
+    struct {
+      char HPIS    : 3;
+      char HPCLICK : 1;
+      char FDS     : 1;
+      char HPCF    : 2;
+      char HPM     : 2;
+    } bit;
+  } lis2dh_ctrl_reg2;
+
+  /// @brief CTRL_REG3 (22h)
+  union lis2dh_ctrl_reg3_reg {
+    char all;
+    struct {
+      char reserved   : 1;
+      char I1_OVERRUN : 1;
+      char I1_WTM     : 1;
+      char I1_DRDY    : 2;
+      char I1_AOI     : 1;
+      char I1_CLICK   : 1;
+    } bit;
+  } lis2dh_ctrl_reg3;
+
+  /// @brief CTRL_REG4 (23h)
+  union lis2dh_ctrl_reg4_reg {
+    char all;
+    struct {
+      char SIM : 1;
+      char ST  : 2;
+      char HR  : 1;
+      char FS  : 2;
+      char BLE : 1;
+      char BDU : 1;
+    } bit;
+  } lis2dh_ctrl_reg4;
+
+  /// @brief CTRL_REG5 (24h)
+  union lis2dh_ctrl_reg5_reg {
+    char all;
+    struct {
+      char D4D_INT2 : 1;
+      char LIR_INT2 : 1;
+      char D4D_INT1 : 1;
+      char LIR_INT1 : 1;
+      char reserved : 2;
+      char FIFO_EN  : 1;
+      char BOOT     : 1;
+    } bit;
+  } lis2dh_ctrl_reg5;
+
+  /// @brief CTRL_REG6 (25h)
+  union lis2dh_ctrl_reg6_reg {
+    char all;
+    struct {
+      char reserved1 : 1;
+      char H_LACTIVE : 1;
+      char reserved2 : 1;
+      char P2_ACT    : 1;
+      char BOOT_I2   : 1;
+      char I2_INT2   : 2;
+      char I2_INT1   : 1;
+      char I2_CLICKen: 1;
+    } bit;
+  } lis2dh_ctrl_reg6;
+
+  /// @brief REFERENCE (26h)
+  union lis2dh_reference_reg {
+    char all;
+  } lis2dh_reference;
+
+  /// @brief STATUS_REG (27h)
+  union lis2dh_status_reg_ {
+    char all;
+    struct {
+      char XDA   : 1;
+      char YDA   : 1;
+      char ZDA   : 1;
+      char ZYXDA : 1;
+      char XOR   : 1;
+      char YOR   : 1;
+      char ZOR   : 1;
+      char ZYXOR : 1;
+    } bit;
+  } lis2dh_status_reg;
+
+  /// @brief OUT_X_L (28h)
+  union lis2dh_out_x_l_ {
+    char all;
+  } lis2dh_out_x_l;
+
+  /// @brief OUT_X_H (29h)
+  union lis2dh_out_x_h_ {
+    char all;
+  } lis2dh_out_x_h;
+
+  /// @brief OUT_Y_L (2Ah)
+  union lis2dh_out_y_l_ {
+    char all;
+  } lis2dh_out_y_l;
+
+  /// @brief OUT_Y_H (2Bh)
+  union lis2dh_out_y_h_ {
+    char all;
+  } lis2dh_out_y_h;
+
+  /// @brief OUT_Z_L (2Ch)
+  union lis2dh_out_z_l_ {
+    char all;
+  } lis2dh_out_z_l;
+
+  /// @brief OUT_Z_H (2Dh)
+  union lis2dh_out_z_h_ {
+    char all;
+  } lis2dh_out_z_h;
+
+  /// @brief FIFO_CTRL_REG (2Eh)
+  union lis2dh_fifo_ctrl_reg_ {
+    char all;
+    struct {
+      char FTH : 5;
+      char TR  : 1;
+      char FM  : 2;
+    } bit;
+  } lis2dh_fifo_ctrl_reg;
+
+  /// @brief FIFO_CTRL_REG (2Fh)
+  union lis2dh_fifo_src_reg_ {
+    char all;
+    struct {
+      char FSS       : 5;
+      char EMPTY     : 1;
+      char OVRN_FIFO : 1;
+      char WTM       : 1;
+    } bit;
+  } lis2dh_fifo_src_reg;
+
+  /// @brief INT1_CFG (30h)
+  union lis2dh_int1_cfg_reg_ {
+    char all;
+    struct {
+      char XLIE_XDOWNE : 1;
+      char XHIE_XUPE   : 1;
+      char YLIE_YDOWNE : 1;
+      char YHIE_YUPE   : 1;
+      char ZLIE_ZDOWNE : 1;
+      char ZHIE_ZUPE   : 1;
+      char SIXD        : 1;
+      char AOI         : 1;
+    } bit;
+  } lis2dh_int1_cfg;
+
+  /// @brief INT1_SRC (31h)
+  union lis2dh_int1_src_reg_ {
+    char all;
+    struct {
+      char XL : 1;
+      char XH : 1;
+      char YL : 1;
+      char YH : 1;
+      char ZL : 1;
+      char ZH : 1;
+      char IA : 1;
+      char reserved : 1;
+    } bit;
+  } lis2dh_int1_src;
+
+  /// @brief INT1_THS (32h)
+  union lis2dh_int1_ths_reg_ {
+    char all;
+  } lis2dh_int1_ths;
+
+  /// @brief INT1_DURATION (33h)
+  union lis2dh_int1_duration_reg_ {
+    char all;
+  } lis2dh_int1_duration;
+
+  /// @brief INT2_CFG (34h)
+  union lis2dh_int2_cfg_reg_ {
+    char all;
+    struct {
+      char XLIE : 1;
+      char XHIE : 1;
+      char YLIE : 1;
+      char YHIE : 1;
+      char ZLIE : 1;
+      char ZHIE : 1;
+      char SIX6 : 1;
+      char AOI  : 1;
+    } bit;
+  } lis2dh_int2_cfg;
+
+  /// @brief INT2_SRC (35h)
+  union lis2dh_int2_src_reg_ {
+    char all;
+    struct {
+      char XL       : 1;
+      char XH       : 1;
+      char YL       : 1;
+      char YH       : 1;
+      char ZL       : 1;
+      char ZH       : 1;
+      char IA       : 1;
+      char reserved : 1;
+    } bit;
+  } lis2dh_int2_src;
+
+  /// @brief INT2_THS (36h)
+  union lis2dh_int2_ths_reg_ {
+    char all;
+  } lis2dh_int2_ths;
+
+  /// @brief INT2_DURATION (37h)
+  union lis2dh_int2_duration_reg_ {
+    char all;
+  } lis2dh_int2_duration;
+
+  LIS2DH(PinName sda, PinName scl, int slaveAddress);
+  LIS2DH(I2C *i2c, int slaveAddress);
+  ~LIS2DH(void);
+
+  /** @brief Initialize the device
+  */
+  void init(void);
+  /** @brief Interrupt handler
+  */
+  void int_handler(void);
+  /** @brief Get motion data from the device fifo
+  */
+  int get_motion_fifo(short *valueX, short *valueY, short *valueZ);
+  /** @brief Get the last cached motion values (cached from a previous interrupt
+   * event)
+  */
+  int get_motion_cached(int16_t *valueX, int16_t *valueY, int16_t *valueZ);
+  /** @brief Star Interrupts
+  */
+  int initStart(int dataRate, int fifoThreshold);
+  /** @brief Stop interrupts
+  */
+  void stop(void);
+  /** @brief Read device register
+  */
+  int readReg(char reg, char *value);
+  /** @brief Write device regsiter
+  */
+  int writeReg(char reg, char value);
+  /** @brief Detect if device exists
+  */
+  int detect(char *detected);
+  /** @brief Read the device ID
+  */
+  char readId(void);
+
+  static LIS2DH *instance;
+
+private:
+  /** @brief
+  */
+  void configure_interrupt(void);
+  /// I2C pointer
+  I2C *i2c;
+  /// Is this object the owner of the I2C object
+  bool isOwner;
+  /// Device slave address
+  int slaveAddress;
+};
+
+#endif /* LIS2DH_H_ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/e4a10ed6eb92/HSP/Devices/LIS2DH/LIS2DH_RPC.cpp	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,89 @@
+/*******************************************************************************
+ * Copyright (C) 2016 Maxim Integrated Products, Inc., All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+ * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Except as contained in this notice, the name of Maxim Integrated
+ * Products, Inc. shall not be used except as stated in the Maxim Integrated
+ * Products, Inc. Branding Policy.
+ *
+ * The mere transfer of this software does not imply any licenses
+ * of trade secrets, proprietary technology, copyrights, patents,
+ * trademarks, maskwork rights, or any other form of intellectual
+ * property whatsoever. Maxim Integrated Products, Inc. retains all
+ * ownership rights.
+ *******************************************************************************
+ */
+
+#include "mbed.h"
+#include "LIS2DH.h"
+#include "StringInOut.h"
+#include "StringHelper.h"
+#include "Peripherals.h"
+
+#define LIS2DH_SLAVE_ADDRESS 0x32
+#define LIS2DH_REG_PART_ID   0x0F
+
+//******************************************************************************
+int LIS2DH_ReadReg(char argStrs[32][32], char replyStrs[32][32]) {
+  uint8_t args[1];
+  uint8_t reply[1];
+  ProcessArgs(argStrs, args, sizeof(args));
+  LIS2DH *lis2dh = Peripherals::lis2dh();
+  lis2dh->readReg(args[0], (char *)reply);
+  FormatReply(reply, sizeof(reply), replyStrs);
+  return 0;
+}
+
+//******************************************************************************
+int LIS2DH_WriteReg(char argStrs[32][32], char replyStrs[32][32]) {
+  uint8_t args[2];
+  uint8_t reply[1];
+  ProcessArgs(argStrs, args, sizeof(args));
+  LIS2DH *lis2dh = Peripherals::lis2dh();
+  lis2dh->writeReg(args[0], args[1]); // pass in the register address
+  reply[0] = 0x80;
+  FormatReply(reply, sizeof(reply), replyStrs);
+  return 0;
+}
+
+extern int highDataRate;
+//******************************************************************************
+int LIS2DH_InitStart(char argStrs[32][32], char replyStrs[32][32]) {
+  uint8_t args[2];
+  uint8_t reply[1];
+  ProcessArgs(argStrs, args, sizeof(args));
+  LIS2DH *lis2dh = Peripherals::lis2dh();
+  if (args[0] >= LIS2DH_DATARATE_200HZ)
+    highDataRate = 1;
+  lis2dh->initStart(args[0], args[1]);
+  reply[0] = 0x80;
+  FormatReply(reply, sizeof(reply), replyStrs);
+  return 0;
+}
+
+//******************************************************************************
+int LIS2DH_Stop(char argStrs[32][32], char replyStrs[32][32]) {
+  uint8_t reply[1];
+  LIS2DH *lis2dh = Peripherals::lis2dh();
+  lis2dh->stop();
+  reply[0] = 0x80;
+  FormatReply(reply, sizeof(reply), replyStrs);
+  return 0;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/e4a10ed6eb92/HSP/Devices/LIS2DH/LIS2DH_RPC.h	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,43 @@
+/*******************************************************************************
+ * Copyright (C) 2016 Maxim Integrated Products, Inc., All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+ * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Except as contained in this notice, the name of Maxim Integrated
+ * Products, Inc. shall not be used except as stated in the Maxim Integrated
+ * Products, Inc. Branding Policy.
+ *
+ * The mere transfer of this software does not imply any licenses
+ * of trade secrets, proprietary technology, copyrights, patents,
+ * trademarks, maskwork rights, or any other form of intellectual
+ * property whatsoever. Maxim Integrated Products, Inc. retains all
+ * ownership rights.
+ *******************************************************************************
+ */
+#ifndef _LIS2HD_H_
+#define _LIS2HD_H_
+
+#include "mbed.h"
+
+int LIS2DH_ReadReg(char argStrs[32][32], char replyStrs[32][32]);
+int LIS2DH_WriteReg(char argStrs[32][32], char replyStrs[32][32]);
+int LIS2DH_InitStart(char argStrs[32][32], char replyStrs[32][32]);
+int LIS2DH_Stop(char argStrs[32][32], char replyStrs[32][32]);
+
+#endif /* _LIS2HD_H_ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/e4a10ed6eb92/HSP/Devices/MAX30001/MAX30001/MAX30001.cpp	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,1317 @@
+
+/*******************************************************************************
+ * Copyright (C) 2016 Maxim Integrated Products, Inc., All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+ * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Except as contained in this notice, the name of Maxim Integrated
+ * Products, Inc. shall not be used except as stated in the Maxim Integrated
+ * Products, Inc. Branding Policy.
+ *
+ * The mere transfer of this software does not imply any licenses
+ * of trade secrets, proprietary technology, copyrights, patents,
+ * trademarks, maskwork rights, or any other form of intellectual
+ * property whatsoever. Maxim Integrated Products, Inc. retains all
+ * ownership rights.
+ *******************************************************************************
+ */
+
+#include "mbed.h"
+#include "MAX30001.h"
+
+MAX30001 *MAX30001::instance = NULL;
+
+//******************************************************************************
+MAX30001::MAX30001(PinName mosi, PinName miso, PinName sclk, PinName cs) {
+  spi = new SPI(mosi, miso, sclk, cs);
+  spi->frequency(3000000);
+  spi_owner = true;
+  functionpointer.attach(&spiHandler);
+  onDataAvailableCallback = NULL;
+  instance = this;
+}
+
+//******************************************************************************
+MAX30001::MAX30001(SPI *_spi) {
+  spi = _spi;
+  spi->frequency(3000000);
+  spi_owner = false;
+  functionpointer.attach(&spiHandler);
+  onDataAvailableCallback = NULL;
+  instance = this;
+}
+
+//******************************************************************************
+MAX30001::~MAX30001(void) {
+  if (spi_owner) {
+    delete spi;
+  }
+}
+
+//******************************************************************************
+int MAX30001::max30001_Rbias_FMSTR_Init(uint8_t En_rbias, uint8_t Rbiasv,
+                                        uint8_t Rbiasp, uint8_t Rbiasn,
+                                        uint8_t Fmstr) {
+  if (max30001_reg_read(CNFG_GEN, &max30001_cnfg_gen.all) == -1) {
+    return -1;
+  }
+
+  max30001_cnfg_gen.bit.en_rbias = En_rbias;
+  max30001_cnfg_gen.bit.rbiasv   = Rbiasv;
+  max30001_cnfg_gen.bit.rbiasp   = Rbiasp;
+  max30001_cnfg_gen.bit.rbiasn   = Rbiasn;
+  max30001_cnfg_gen.bit.fmstr    = Fmstr;
+
+  if (max30001_reg_write(CNFG_GEN, max30001_cnfg_gen.all) == -1) {
+    return -1;
+  }
+  return 0;
+}
+
+//******************************************************************************
+int MAX30001::max30001_CAL_InitStart(uint8_t En_Vcal, uint8_t Vmode,
+                                     uint8_t Vmag, uint8_t Fcal, uint16_t Thigh,
+                                     uint8_t Fifty) {
+  // CNFG_CAL
+  if (max30001_reg_read(CNFG_CAL, &max30001_cnfg_cal.all) == -1) {
+    return -1;
+  }
+
+  max30001_cnfg_cal.bit.vmode = Vmode;
+  max30001_cnfg_cal.bit.vmag  = Vmag;
+  max30001_cnfg_cal.bit.fcal  = Fcal;
+  max30001_cnfg_cal.bit.thigh = Thigh;
+  max30001_cnfg_cal.bit.fifty = Fifty;
+
+  if (max30001_reg_write(CNFG_CAL, max30001_cnfg_cal.all) == -1) {
+    return -1;
+  }
+
+  // RTOS uses a 32768HZ clock.  32768ticks represents 1secs.  1sec/10 =
+  // 100msecs.
+  wait(1.0 / 10.0);
+
+  if (max30001_reg_read(CNFG_CAL, &max30001_cnfg_cal.all) == -1) {
+    return -1;
+  }
+
+  max30001_cnfg_cal.bit.en_vcal = En_Vcal;
+
+  if (max30001_reg_write(CNFG_CAL, max30001_cnfg_cal.all) == -1) {
+    return -1;
+  }
+
+  // RTOS uses a 32768HZ clock.  32768ticks represents 1secs.  1sec/10 =
+  // 100msecs.
+  wait(1.0 / 10.0);
+
+  return 0;
+}
+
+//******************************************************************************
+int MAX30001::max30001_CAL_Stop(void) {
+
+  if (max30001_reg_read(CNFG_CAL, &max30001_cnfg_cal.all) == -1) {
+    return -1;
+  }
+
+  max30001_cnfg_cal.bit.en_vcal = 0; // Disable VCAL, all other settings are left unaffected
+
+  if (max30001_reg_write(CNFG_CAL, max30001_cnfg_cal.all) == -1) {
+    return -1;
+  }
+
+  return 0;
+}
+//******************************************************************************
+//******************************************************************************
+int MAX30001::max30001_INT_assignment(max30001_intrpt_Location_t en_enint_loc,     max30001_intrpt_Location_t en_eovf_loc,  max30001_intrpt_Location_t en_fstint_loc,
+		                      max30001_intrpt_Location_t en_dcloffint_loc, max30001_intrpt_Location_t en_bint_loc,  max30001_intrpt_Location_t en_bovf_loc,
+		                      max30001_intrpt_Location_t en_bover_loc,     max30001_intrpt_Location_t en_bundr_loc, max30001_intrpt_Location_t en_bcgmon_loc,
+		                      max30001_intrpt_Location_t en_pint_loc,      max30001_intrpt_Location_t en_povf_loc,  max30001_intrpt_Location_t en_pedge_loc,
+		                      max30001_intrpt_Location_t en_lonint_loc,    max30001_intrpt_Location_t en_rrint_loc, max30001_intrpt_Location_t en_samp_loc,
+		                      max30001_intrpt_type_t  intb_Type,           max30001_intrpt_type_t int2b_Type)
+
+
+{
+  // INT1
+
+  if (max30001_reg_read(EN_INT, &max30001_en_int.all) == -1) {
+    return -1;
+  }
+
+  // max30001_en_int2.bit.en_pint       = 0b1;  // Keep this off...
+
+  max30001_en_int.bit.en_eint = 0b1 & en_enint_loc;
+  max30001_en_int.bit.en_eovf = 0b1 & en_eovf_loc;
+  max30001_en_int.bit.en_fstint = 0b1 & en_fstint_loc;
+
+  max30001_en_int.bit.en_dcloffint = 0b1 & en_dcloffint_loc;
+  max30001_en_int.bit.en_bint = 0b1 & en_bint_loc;
+  max30001_en_int.bit.en_bovf = 0b1 & en_bovf_loc;
+
+  max30001_en_int.bit.en_bover = 0b1 & en_bover_loc;
+  max30001_en_int.bit.en_bundr = 0b1 & en_bundr_loc;
+  max30001_en_int.bit.en_bcgmon = 0b1 & en_bcgmon_loc;
+
+  max30001_en_int.bit.en_pint = 0b1 & en_pint_loc;
+  max30001_en_int.bit.en_povf = 0b1 & en_povf_loc;
+  max30001_en_int.bit.en_pedge = 0b1 & en_pedge_loc;
+
+  max30001_en_int.bit.en_lonint = 0b1 & en_lonint_loc;
+  max30001_en_int.bit.en_rrint = 0b1 & en_rrint_loc;
+  max30001_en_int.bit.en_samp = 0b1 & en_samp_loc;
+
+  max30001_en_int.bit.intb_type = int2b_Type;
+
+  if (max30001_reg_write(EN_INT, max30001_en_int.all) == -1) {
+    return -1;
+  }
+
+  // INT2
+
+  if (max30001_reg_read(EN_INT2, &max30001_en_int2.all) == -1) {
+    return -1;
+  }
+
+  max30001_en_int2.bit.en_eint   = 0b1 & (en_enint_loc >> 1);
+  max30001_en_int2.bit.en_eovf   = 0b1 & (en_eovf_loc >> 1);
+  max30001_en_int2.bit.en_fstint = 0b1 & (en_fstint_loc >> 1);
+
+  max30001_en_int2.bit.en_dcloffint = 0b1 & (en_dcloffint_loc >> 1);
+  max30001_en_int2.bit.en_bint      = 0b1 & (en_bint_loc >> 1);
+  max30001_en_int2.bit.en_bovf      = 0b1 & (en_bovf_loc >> 1);
+
+  max30001_en_int2.bit.en_bover  = 0b1 & (en_bover_loc >> 1);
+  max30001_en_int2.bit.en_bundr  = 0b1 & (en_bundr_loc >> 1);
+  max30001_en_int2.bit.en_bcgmon = 0b1 & (en_bcgmon_loc >> 1);
+
+  max30001_en_int2.bit.en_pint  = 0b1 & (en_pint_loc >> 1);
+  max30001_en_int2.bit.en_povf  = 0b1 & (en_povf_loc >> 1);
+  max30001_en_int2.bit.en_pedge = 0b1 & (en_pedge_loc >> 1);
+
+  max30001_en_int2.bit.en_lonint = 0b1 & (en_lonint_loc >> 1);
+  max30001_en_int2.bit.en_rrint  = 0b1 & (en_rrint_loc >> 1);
+  max30001_en_int2.bit.en_samp   = 0b1 & (en_samp_loc >> 1);
+
+  max30001_en_int2.bit.intb_type = intb_Type;
+
+  if (max30001_reg_write(EN_INT2, max30001_en_int2.all) == -1) {
+    return -1;
+  }
+
+  return 0;
+}
+
+//******************************************************************************
+int MAX30001::max30001_ECG_InitStart(uint8_t En_ecg, uint8_t Openp,
+                                     uint8_t Openn, uint8_t Pol,
+                                     uint8_t Calp_sel, uint8_t Caln_sel,
+                                     uint8_t E_fit, uint8_t Rate, uint8_t Gain,
+                                     uint8_t Dhpf, uint8_t Dlpf) {
+
+  // CNFG_EMUX
+
+  if (max30001_reg_read(CNFG_EMUX, &max30001_cnfg_emux.all) == -1) {
+    return -1;
+  }
+
+  max30001_cnfg_emux.bit.openp    = Openp;
+  max30001_cnfg_emux.bit.openn    = Openn;
+  max30001_cnfg_emux.bit.pol      = Pol;
+  max30001_cnfg_emux.bit.calp_sel = Calp_sel;
+  max30001_cnfg_emux.bit.caln_sel = Caln_sel;
+
+  if (max30001_reg_write(CNFG_EMUX, max30001_cnfg_emux.all) == -1) {
+    return -1;
+  }
+
+  /**** ENABLE CHANNELS ****/
+  // CNFG_GEN
+
+  if (max30001_reg_read(CNFG_GEN, &max30001_cnfg_gen.all) == -1) {
+    return -1;
+  }
+
+  max30001_cnfg_gen.bit.en_ecg = En_ecg; // 0b1
+
+  // fmstr is default
+
+  if (max30001_reg_write(CNFG_GEN, max30001_cnfg_gen.all) == -1) {
+    return -1;
+  }
+
+  /**** Wait for PLL Lock & References to settle down ****/
+
+  max30001_timeout = 0;
+
+  do {
+    if (max30001_reg_read(STATUS, &max30001_status.all) == -1) // Wait and spin for PLL to lock...
+    {
+      return -1;
+    }
+  } while (max30001_status.bit.pllint == 1 && max30001_timeout++ <= 1000);
+
+  // MNGR_INT
+
+  if (max30001_reg_read(MNGR_INT, &max30001_mngr_int.all) == -1) {
+    return -1;
+  }
+
+  max30001_mngr_int.bit.e_fit = E_fit; // 31
+
+  if (max30001_reg_write(MNGR_INT, max30001_mngr_int.all) == -1) {
+    return -1;
+  }
+
+  // CNFG_ECG
+
+  if (max30001_reg_read(CNFG_ECG, &max30001_cnfg_ecg.all) == -1) {
+    return -1;
+  }
+
+  max30001_cnfg_ecg.bit.rate = Rate; 
+  max30001_cnfg_ecg.bit.gain = Gain;
+  max30001_cnfg_ecg.bit.dhpf = Dhpf;
+  max30001_cnfg_ecg.bit.dlpf = Dlpf;
+
+  if (max30001_reg_write(CNFG_ECG, max30001_cnfg_ecg.all) == -1) {
+    return -1;
+  }
+
+  return 0;
+}
+
+//******************************************************************************
+int MAX30001::max30001_ECGFast_Init(uint8_t Clr_Fast, uint8_t Fast, uint8_t Fast_Th) {
+  if (max30001_reg_read(MNGR_INT, &max30001_mngr_int.all) == -1) {
+    return -1;
+  }
+
+  max30001_mngr_int.bit.clr_fast = Clr_Fast;
+
+  if (max30001_reg_write(MNGR_INT, max30001_mngr_int.all) == -1) {
+    return -1;
+  }
+
+  if (max30001_reg_read(MNGR_DYN, &max30001_mngr_dyn.all) == -1) {
+    return -1;
+  }
+
+  max30001_mngr_dyn.bit.fast = Fast;
+  max30001_mngr_dyn.bit.fast_th = Fast_Th;
+
+  if (max30001_reg_write(MNGR_INT, max30001_mngr_int.all) == -1) {
+    return -1;
+  }
+
+  return 0;
+}
+
+//******************************************************************************
+int MAX30001::max30001_Stop_ECG(void) {
+
+  if (max30001_reg_read(CNFG_GEN, &max30001_cnfg_gen.all) == -1) {
+    return -1;
+  }
+
+  max30001_cnfg_gen.bit.en_ecg = 0; // Stop ECG
+
+  // fmstr is default
+
+  if (max30001_reg_write(CNFG_GEN, max30001_cnfg_gen.all) == -1) {
+    return -1;
+  }
+
+  return 0;
+}
+
+//******************************************************************************
+int MAX30001::max30001_PACE_InitStart(uint8_t En_pace, uint8_t Clr_pedge,
+                                      uint8_t Pol, uint8_t Gn_diff_off,
+                                      uint8_t Gain, uint8_t Aout_lbw,
+                                      uint8_t Aout, uint8_t Dacp,
+                                      uint8_t Dacn) {
+
+  /**** SET MASTER FREQUENCY, ENABLE CHANNELS ****/
+
+  // CNFG_GEN
+
+  if (max30001_reg_read(CNFG_GEN, &max30001_cnfg_gen.all) == -1) {
+    return -1;
+  }
+
+  max30001_cnfg_gen.bit.en_pace = En_pace; // 0b1;
+
+  if (max30001_reg_write(CNFG_GEN, max30001_cnfg_gen.all) == -1) {
+    return -1;
+  }
+
+  /**** Wait for PLL Lock & References to settle down ****/
+  max30001_timeout = 0;
+
+  do {
+    if (max30001_reg_read(STATUS, &max30001_status.all) ==
+        -1) // Wait and spin for PLL to lock...
+    {
+      return -1;
+    }
+
+  } while (max30001_status.bit.pllint == 1 && max30001_timeout++ <= 1000);
+
+  // MNGR_INT
+
+  if (max30001_reg_read(MNGR_INT, &max30001_mngr_int.all) == -1) {
+    return -1;
+  }
+
+  max30001_mngr_int.bit.clr_pedge = Clr_pedge; // 0b0;
+
+  if (max30001_reg_write(MNGR_INT, max30001_mngr_int.all) == -1) {
+    return -1;
+  }
+
+  /* Put: CNFG_PACE */
+
+  max30001_reg_read(CNFG_PACE, &max30001_cnfg_pace.all);
+
+  max30001_cnfg_pace.bit.pol         = Pol;         
+  max30001_cnfg_pace.bit.gn_diff_off = Gn_diff_off;
+  max30001_cnfg_pace.bit.gain        = Gain;
+  max30001_cnfg_pace.bit.aout_lbw    = Aout_lbw;
+  max30001_cnfg_pace.bit.aout        = Aout;
+  max30001_cnfg_pace.bit.dacp        = Dacp;
+  max30001_cnfg_pace.bit.dacn        = Dacn;
+
+  max30001_reg_write(CNFG_PACE, max30001_cnfg_pace.all);
+
+  return 0;
+}
+//******************************************************************************
+int MAX30001::max30001_Stop_PACE(void) {
+
+  if (max30001_reg_read(CNFG_GEN, &max30001_cnfg_gen.all) == -1) {
+    return -1;
+  }
+
+  max30001_cnfg_gen.bit.en_pace = 0; // Stop PACE
+
+  if (max30001_reg_write(CNFG_GEN, max30001_cnfg_gen.all) == -1) {
+    return -1;
+  }
+
+  return 0;
+}
+
+//******************************************************************************
+int MAX30001::max30001_BIOZ_InitStart(
+    uint8_t En_bioz, uint8_t Openp, uint8_t Openn, uint8_t Calp_sel,
+    uint8_t Caln_sel, uint8_t CG_mode, uint8_t B_fit, uint8_t Rate,
+    uint8_t Ahpf, uint8_t Ext_rbias, uint8_t Gain, uint8_t Dhpf, uint8_t Dlpf,
+    uint8_t Fcgen, uint8_t Cgmon, uint8_t Cgmag, uint8_t Phoff) {
+
+  // CNFG_BMUX
+
+  if (max30001_reg_read(CNFG_BMUX, &max30001_cnfg_bmux.all) == -1) {
+    return -1;
+  }
+
+  max30001_cnfg_bmux.bit.openp    = Openp;       // 0b1;
+  max30001_cnfg_bmux.bit.openn    = Openn;       // 0b1;
+  max30001_cnfg_bmux.bit.calp_sel = Calp_sel; // 0b10;
+  max30001_cnfg_bmux.bit.caln_sel = Caln_sel; // 0b11;
+  max30001_cnfg_bmux.bit.cg_mode  = CG_mode;   // 0b00;
+
+  if (max30001_reg_write(CNFG_BMUX, max30001_cnfg_bmux.all) == -1) {
+    return -1;
+  }
+
+  /**** SET MASTER FREQUENCY, ENABLE CHANNELS ****/
+
+  // CNFG_GEN
+
+  if (max30001_reg_read(CNFG_GEN, &max30001_cnfg_gen.all) == -1) {
+    return -1;
+  }
+
+  max30001_cnfg_gen.bit.en_bioz = En_bioz;
+
+  // fmstr is default
+
+  if (max30001_reg_write(CNFG_GEN, max30001_cnfg_gen.all) == -1) {
+    return -1;
+  }
+
+  /**** Wait for PLL Lock & References to settle down ****/
+
+  max30001_timeout = 0;
+
+  do {
+    if (max30001_reg_read(STATUS, &max30001_status.all) ==
+        -1) // Wait and spin for PLL to lock...
+    {
+      return -1;
+    }
+
+  } while (max30001_status.bit.pllint == 1 && max30001_timeout++ <= 1000);
+
+  /**** Start of CNFG_BIOZ ****/
+
+  // MNGR_INT
+
+  if (max30001_reg_read(MNGR_INT, &max30001_mngr_int.all) == -1) {
+    return -1;
+  }
+
+  max30001_mngr_int.bit.b_fit = B_fit; //;
+
+  if (max30001_reg_write(MNGR_INT, max30001_mngr_int.all) == -1) {
+    return -1;
+  }
+
+  // CNFG_BIOZ
+
+  if (max30001_reg_read(CNFG_BIOZ, &max30001_cnfg_bioz.all) == -1) {
+    return -1;
+  }
+
+  max30001_cnfg_bioz.bit.rate      = Rate;
+  max30001_cnfg_bioz.bit.ahpf      = Ahpf;
+  max30001_cnfg_bioz.bit.ext_rbias = Ext_rbias;
+  max30001_cnfg_bioz.bit.gain      = Gain;
+  max30001_cnfg_bioz.bit.dhpf      = Dhpf;
+  max30001_cnfg_bioz.bit.dlpf      = Dlpf;
+  max30001_cnfg_bioz.bit.fcgen     = Fcgen;
+  max30001_cnfg_bioz.bit.cgmon     = Cgmon;
+  max30001_cnfg_bioz.bit.cgmag     = Cgmag;
+  max30001_cnfg_bioz.bit.phoff     = Phoff;
+
+  if (max30001_reg_write(CNFG_BIOZ, max30001_cnfg_bioz.all) == -1) {
+    return -1;
+  }
+
+  return 0;
+}
+
+//******************************************************************************
+int MAX30001::max30001_Stop_BIOZ(void) {
+
+  if (max30001_reg_read(CNFG_GEN, &max30001_cnfg_gen.all) == -1) {
+    return -1;
+  }
+
+  max30001_cnfg_gen.bit.en_bioz = 0; // Stop BIOZ
+
+  if (max30001_reg_write(CNFG_GEN, max30001_cnfg_gen.all) == -1) {
+    return -1;
+  }
+
+  return 0;
+}
+
+//******************************************************************************
+int MAX30001::max30001_BIOZ_InitBist(uint8_t En_bist, uint8_t Rnom,
+                                     uint8_t Rmod, uint8_t Fbist) {
+
+  // CNFG_BMUX
+
+  if (max30001_reg_read(CNFG_BMUX, &max30001_cnfg_bmux.all) == -1) {
+    return -1;
+  }
+
+  max30001_cnfg_bmux.bit.en_bist = En_bist;
+  max30001_cnfg_bmux.bit.rnom = Rnom;
+  max30001_cnfg_bmux.bit.rmod = Rmod;
+  max30001_cnfg_bmux.bit.fbist = Fbist;
+
+  if (max30001_reg_write(CNFG_BMUX, max30001_cnfg_bmux.all) == -1) {
+    return -1;
+  }
+
+  return 0;
+}
+//******************************************************************************
+int MAX30001::max30001_RtoR_InitStart(uint8_t En_rtor, uint8_t Wndw,
+                                      uint8_t Gain, uint8_t Pavg, uint8_t Ptsf,
+                                      uint8_t Hoff, uint8_t Ravg, uint8_t Rhsf,
+                                      uint8_t Clr_rrint) {
+
+  // MNGR_INT
+
+  if (max30001_reg_read(MNGR_INT, &max30001_mngr_int.all) == -1) {
+    return -1;
+  }
+
+  max30001_mngr_int.bit.clr_rrint =
+      Clr_rrint; // 0b01 & 0b00 are for interrupt mode...
+  // 0b10 is for monitoring mode... it just overwrites the data...
+
+  if (max30001_reg_write(MNGR_INT, max30001_mngr_int.all) == -1) {
+    return -1;
+  }
+
+  // RTOR1
+  if (max30001_reg_read(CNFG_RTOR1, &max30001_cnfg_rtor1.all) == -1) {
+    return -1;
+  }
+
+  max30001_cnfg_rtor1.bit.wndw = Wndw;
+  max30001_cnfg_rtor1.bit.gain = Gain;
+  max30001_cnfg_rtor1.bit.en_rtor = En_rtor;
+  max30001_cnfg_rtor1.bit.pavg = Pavg;
+  max30001_cnfg_rtor1.bit.ptsf = Ptsf;
+
+  if (max30001_reg_write(CNFG_RTOR1, max30001_cnfg_rtor1.all) == -1) {
+    return -1;
+  }
+  // RTOR2
+
+  if (max30001_reg_read(CNFG_RTOR2, &max30001_cnfg_rtor2.all) == -1) {
+    return -1;
+  }
+  max30001_cnfg_rtor2.bit.hoff = Hoff;
+  max30001_cnfg_rtor2.bit.ravg = Ravg;
+  max30001_cnfg_rtor2.bit.rhsf = Rhsf;
+
+  if (max30001_reg_write(CNFG_RTOR2, max30001_cnfg_rtor2.all) == -1) {
+    return -1;
+  }
+
+  return 0;
+}
+
+//******************************************************************************
+int MAX30001::max30001_Stop_RtoR(void) {
+
+  if (max30001_reg_read(CNFG_RTOR1, &max30001_cnfg_rtor1.all) == -1) {
+    return -1;
+  }
+
+  max30001_cnfg_rtor1.bit.en_rtor = 0; // Stop RtoR
+
+  if (max30001_reg_write(CNFG_RTOR1, max30001_cnfg_rtor1.all) == -1) {
+    return -1;
+  }
+
+  return 0;
+}
+
+//******************************************************************************
+int MAX30001::max30001_PLL_lock(void) {
+  // Spin to see PLLint become zero to indicate a lock.
+
+  max30001_timeout = 0;
+
+  do {
+    if (max30001_reg_read(STATUS, &max30001_status.all) ==
+        -1) // Wait and spin for PLL to lock...
+    {
+      return -1;
+    }
+
+  } while (max30001_status.bit.pllint == 1 && max30001_timeout++ <= 1000);
+
+  return 0;
+}
+
+//******************************************************************************
+int MAX30001::max30001_sw_rst(void) {
+  // SW reset for the MAX30001 chip
+
+  if (max30001_reg_write(SW_RST, 0x000000) == -1) {
+    return -1;
+  }
+
+  return 0;
+}
+
+//******************************************************************************
+int MAX30001::max30001_synch(void) { // For synchronization
+  if (max30001_reg_write(SYNCH, 0x000000) == -1) {
+    return -1;
+  }
+  return 0;
+}
+
+//******************************************************************************
+int MAX30001::max300001_fifo_rst(void) { // Resets the FIFO
+  if (max30001_reg_write(FIFO_RST, 0x000000) == -1) {
+    return -1;
+  }
+  return 0;
+}
+
+//******************************************************************************
+// int MAX30001::max30001_reg_write(uint8_t addr, uint32_t data)
+int MAX30001::max30001_reg_write(MAX30001_REG_map_t addr, uint32_t data) {
+
+  uint8_t result[4];
+  uint8_t data_array[4];
+  int32_t success = 0;
+
+  data_array[0] = (addr << 1) & 0xff;
+
+  data_array[3] = data & 0xff;
+  data_array[2] = (data >> 8) & 0xff;
+  data_array[1] = (data >> 16) & 0xff;
+
+  success = SPI_Transmit(&data_array[0], 4, &result[0], 4);
+
+  if (success != 0) {
+    return -1;
+  } else {
+    return 0;
+  }
+}
+
+//******************************************************************************
+// int MAX30001::max30001_reg_read(uint8_t addr, uint32_t *return_data)
+int MAX30001::max30001_reg_read(MAX30001_REG_map_t addr,
+                                uint32_t *return_data) {
+  uint8_t result[4];
+  uint8_t data_array[1];
+  int32_t success = 0;
+
+  data_array[0] = ((addr << 1) & 0xff) | 1; // For Read, Or with 1
+  success = SPI_Transmit(&data_array[0], 1, &result[0], 4);
+  *return_data = /*result[0] + */ (uint32_t)(result[1] << 16) +
+                 (result[2] << 8) + result[3];
+  if (success != 0) {
+    return -1;
+  } else {
+    return 0;
+  }
+}
+
+//******************************************************************************
+int MAX30001::max30001_Enable_DcLeadOFF_Init(int8_t En_dcloff, int8_t Ipol,
+                                             int8_t Imag, int8_t Vth) {
+  //  the leads are not touching the body
+
+  // CNFG_EMUX, Set ECGP and ECGN for external hook up...
+
+  if (max30001_reg_read(CNFG_GEN, &max30001_cnfg_gen.all) == -1) {
+    return -1;
+  }
+
+  max30001_cnfg_gen.bit.en_dcloff = En_dcloff;
+  max30001_cnfg_gen.bit.ipol = Ipol;
+  max30001_cnfg_gen.bit.imag = Imag;
+  max30001_cnfg_gen.bit.vth = Vth;
+
+  if (max30001_reg_write(CNFG_GEN, max30001_cnfg_gen.all) == -1) {
+    return -1;
+  }
+
+  return 0;
+}
+
+//******************************************************************************
+int MAX30001::max30001_Disable_DcLeadOFF(void) {
+  if (max30001_reg_read(CNFG_GEN, &max30001_cnfg_gen.all) == -1) {
+    return -1;
+  }
+
+  max30001_cnfg_gen.bit.en_dcloff = 0; // Turned off the dc lead off.
+
+  if (max30001_reg_write(CNFG_GEN, max30001_cnfg_gen.all) == -1) {
+    return -1;
+  }
+
+  return 0;
+}
+
+//******************************************************************************
+int MAX30001::max30001_BIOZ_Enable_ACLeadOFF_Init(uint8_t En_bloff,
+                                                  uint8_t Bloff_hi_it,
+                                                  uint8_t Bloff_lo_it) {
+
+  // CNFG_GEN
+  if (max30001_reg_read(CNFG_GEN, &max30001_cnfg_gen.all) == -1) {
+    return -1;
+  }
+
+  max30001_cnfg_gen.bit.en_bloff = En_bloff;
+
+  if (max30001_reg_write(CNFG_GEN, max30001_cnfg_gen.all) == -1) {
+    return -1;
+  }
+
+  // MNGR_DYN
+  if (max30001_reg_read(MNGR_DYN, &max30001_mngr_dyn.all) == -1) {
+    return -1;
+  }
+
+  max30001_mngr_dyn.bit.bloff_hi_it = Bloff_hi_it;
+  max30001_mngr_dyn.bit.bloff_lo_it = Bloff_lo_it;
+
+  if (max30001_reg_write(MNGR_DYN, max30001_mngr_dyn.all) == -1) {
+    return -1;
+  }
+
+  return 0;
+}
+
+//******************************************************************************
+int MAX30001::max30001_BIOZ_Disable_ACleadOFF(void) {
+  // CNFG_GEN
+  if (max30001_reg_read(CNFG_GEN, &max30001_cnfg_gen.all) == -1) {
+    return -1;
+  }
+
+  max30001_cnfg_gen.bit.en_bloff = 0b0; // Turns of the BIOZ AC Lead OFF feature
+
+  if (max30001_reg_write(CNFG_GEN, max30001_cnfg_gen.all) == -1) {
+    return -1;
+  }
+
+  return 0;
+}
+
+//******************************************************************************
+int MAX30001::max30001_BIOZ_Enable_BCGMON(void) {
+  // CNFG_BIOZ
+  if (max30001_reg_read(CNFG_BIOZ, &max30001_cnfg_bioz.all) == -1) {
+    return -1;
+  }
+
+  max30001_cnfg_bioz.bit.cgmon = 1;
+
+  if (max30001_reg_write(CNFG_BIOZ, max30001_cnfg_bioz.all) == -1) {
+    return -1;
+  }
+
+  max30001_reg_read(CNFG_BIOZ, &max30001_cnfg_bioz.all);
+
+  return 0;
+}
+
+#if 1
+//******************************************************************************
+int MAX30001::max30001_Enable_LeadON(int8_t Channel) // Channel: ECG = 0b01, BIOZ = 0b10, Disable = 0b00
+{
+
+  if (max30001_reg_read(CNFG_GEN, &max30001_cnfg_gen.all) == -1) {
+    return -1;
+  }
+
+  max30001_cnfg_gen.bit.en_ecg  = 0b0;
+  max30001_cnfg_gen.bit.en_bioz = 0b0;
+  max30001_cnfg_gen.bit.en_pace = 0b0;
+
+  max30001_cnfg_gen.bit.en_ulp_lon = Channel; // BIOZ ULP lead on detection...
+
+  if (max30001_reg_write(CNFG_GEN, max30001_cnfg_gen.all) == -1) {
+    return -1;
+  }
+
+  max30001_reg_read(CNFG_GEN, &max30001_cnfg_gen.all);
+
+  max30001_reg_read(STATUS, &max30001_status.all);
+
+  return 0;
+}
+//******************************************************************************
+int MAX30001::max30001_Disable_LeadON(void) {
+
+  if (max30001_reg_read(CNFG_GEN, &max30001_cnfg_gen.all) == -1) {
+    return -1;
+  }
+
+  max30001_cnfg_gen.bit.en_ulp_lon = 0b0;
+
+  if (max30001_reg_write(CNFG_GEN, max30001_cnfg_gen.all) == -1) {
+    return -1;
+  }
+
+  return 0;
+}
+#endif
+//******************************************************************************
+#define LEADOFF_SERVICE_TIME 0x2000 // 0x1000 = 1 second
+#define LEADOFF_NUMSTATES 2
+uint32_t leadoffState = 0;
+uint32_t max30001_LeadOffoldTime = 0;
+void MAX30001::max30001_ServiceLeadoff(uint32_t currentTime) {
+
+  uint32_t delta_Time;
+
+  delta_Time = currentTime - max30001_LeadOffoldTime;
+
+  if (delta_Time > LEADOFF_SERVICE_TIME) {
+    switch (leadoffState) {
+    case 0: /* switch to ECG DC Lead OFF */
+      max30001_Enable_DcLeadOFF_Init(0b01, 0b0, 0b001, 0b00);
+      break;
+
+    case 1: /* switch to BIOZ DC Lead OFF */
+      max30001_Enable_DcLeadOFF_Init(0b10, 0b0, 0b001, 0b00);
+      break;
+    }
+
+    leadoffState++;
+    leadoffState %= LEADOFF_NUMSTATES;
+
+    max30001_LeadOffoldTime = currentTime;
+  }
+}
+//******************************************************************************
+#define LEADON_SERVICE_TIME 0x2000 // 0x1000 = 1 second
+#define LEADON_NUMSTATES 2
+uint32_t leadOnState = 0;
+uint32_t max30001_LeadOnoldTime = 0;
+void MAX30001::max30001_ServiceLeadON(uint32_t currentTime) {
+
+  uint32_t delta_Time;
+
+  delta_Time = currentTime - max30001_LeadOnoldTime;
+
+  if (delta_Time > LEADON_SERVICE_TIME) {
+    switch (leadOnState) {
+    case 0: /* switch to ECG DC Lead ON */
+      max30001_Enable_LeadON(0b01);
+      break;
+
+    case 1: /* switch to BIOZ DC Lead ON */
+      max30001_Enable_LeadON(0b10);
+      break;
+    }
+
+    leadOnState++;
+    leadOnState %= LEADON_NUMSTATES;
+
+    max30001_LeadOnoldTime = currentTime;
+  }
+}
+
+//******************************************************************************
+int MAX30001::max30001_FIFO_LeadONOff_Read(void) {
+
+  uint8_t result[32 * 3]; // 32words - 3bytes each
+
+  uint8_t data_array[4];
+  int32_t success = 0;
+  int i, j;
+
+  uint32_t total_databytes;
+  uint8_t i_index;
+  uint8_t data_chunk;
+  uint8_t loop_logic;
+
+  uint8_t etag, ptag, btag;
+
+  uint8_t adr;
+
+  int8_t ReadAllPaceOnce;
+
+  static uint8_t dcloffint_OneShot = 0;
+  static uint8_t acloffint_OneShot = 0;
+  static uint8_t bcgmon_OneShot = 0;
+  static uint8_t acleadon_OneShot = 0;
+
+  int8_t ret_val;
+
+  if (max30001_status.bit.eint == 1 || max30001_status.bit.pint == 1) {
+    adr = ECG_FIFO_BURST;
+    data_array[0] = ((adr << 1) & 0xff) | 1;
+
+    // The SPI routine only sends out data of 32 bytes in size.  Therefore the
+    // data is being read in
+    // smaller chunks in this routine...
+
+    total_databytes = (max30001_mngr_int.bit.e_fit + 1) * 3;
+
+    i_index = 0;
+    loop_logic = 1;
+
+    while (loop_logic) {
+      if (total_databytes > 30) {
+        data_chunk = 30;
+        total_databytes = total_databytes - 30;
+      } else {
+        data_chunk = total_databytes;
+        loop_logic = 0;
+      }
+
+      /* The extra 1 byte is for the extra byte that comes out of the SPI */
+      success = SPI_Transmit(&data_array[0], 1, &result[i_index], (data_chunk + 1)); // Make a copy of the FIFO over here...
+
+      if (success != 0) {
+        return -1;
+      }
+
+      /* This is important, because every transaction above creates an empty
+       * redundant data at result[0] */
+      for (j = i_index; j < (data_chunk + i_index); j++) /* get rid of the 1 extra byte by moving the whole array up one */
+      {
+        result[j] = result[j + 1];
+      }
+
+      i_index = i_index + 30; /* point to the next array location to put the data in */
+    }
+
+    ReadAllPaceOnce = 0;
+
+    /* Put the content of the FIFO based on the EFIT value, We ignore the
+     * result[0] and start concatenating indexes: 1,2,3 - 4,5,6 - 7,8,9 -  */
+    for (i = 0, j = 0; i < max30001_mngr_int.bit.e_fit + 1; i++, j = j + 3) // index1=23-16 bit, index2=15-8 bit, index3=7-0 bit
+    {
+      max30001_ECG_FIFO_buffer[i] = ((uint32_t)result[j] << 16) + (result[j + 1] << 8) + result[j + 2];
+
+      etag = (0b00111000 & result[j + 2]) >> 3;
+      ptag = 0b00000111 & result[j + 2];
+
+      if (ptag != 0b111 && ReadAllPaceOnce == 0) {
+
+        ReadAllPaceOnce = 1; // This will prevent extra read of PACE, once group
+                             // 0-5 is read ONCE.
+
+        adr = PACE0_FIFO_BURST;
+
+        data_array[0] = ((adr << 1) & 0xff) | 1; // For Read Or with 1
+
+        success = SPI_Transmit(&data_array[0], 1, &result[0], 10);
+
+        max30001_PACE[0] = (uint32_t)(result[1] << 16) + (result[2] << 8) + result[3];
+        max30001_PACE[1] = (uint32_t)(result[4] << 16) + (result[5] << 8) + result[6];
+        max30001_PACE[2] = (uint32_t)(result[7] << 16) + (result[8] << 8) + result[9];
+
+        adr = PACE1_FIFO_BURST;
+
+        data_array[0] = ((adr << 1) & 0xff) | 1; // For Read Or with 1
+
+        success = SPI_Transmit(&data_array[0], 1, &result[0], 10);
+
+        max30001_PACE[3] = (uint32_t)(result[1] << 16) + (result[2] << 8) + result[3];
+        max30001_PACE[4] = (uint32_t)(result[4] << 16) + (result[5] << 8) + result[6];
+        max30001_PACE[5] = (uint32_t)(result[7] << 16) + (result[8] << 8) + result[9];
+
+        adr = PACE2_FIFO_BURST;
+
+        data_array[0] = ((adr << 1) & 0xff) | 1; // For Read Or with 1
+
+        success = SPI_Transmit(&data_array[0], 1, &result[0], 10);
+
+        max30001_PACE[6] = (uint32_t)(result[1] << 16) + (result[2] << 8) + result[3];
+        max30001_PACE[7] = (uint32_t)(result[4] << 16) + (result[5] << 8) + result[6];
+        max30001_PACE[8] = (uint32_t)(result[7] << 16) + (result[8] << 8) + result[9];
+
+        adr = PACE3_FIFO_BURST;
+
+        data_array[0] = ((adr << 1) & 0xff) | 1; // For Read Or with 1
+
+        success = SPI_Transmit(&data_array[0], 1, &result[0], 10);
+
+        max30001_PACE[9]  = (uint32_t)(result[1] << 16) + (result[2] << 8) + result[3];
+        max30001_PACE[10] = (uint32_t)(result[4] << 16) + (result[5] << 8) + result[6];
+        max30001_PACE[11] = (uint32_t)(result[7] << 16) + (result[8] << 8) + result[9];
+
+        adr = PACE4_FIFO_BURST;
+
+        data_array[0] = ((adr << 1) & 0xff) | 1; // For Read Or with 1
+
+        success = SPI_Transmit(&data_array[0], 1, &result[0], 10);
+
+        max30001_PACE[12] = (uint32_t)(result[1] << 16) + (result[2] << 8) + result[3];
+        max30001_PACE[13] = (uint32_t)(result[4] << 16) + (result[5] << 8) + result[6];
+        max30001_PACE[14] = (uint32_t)(result[7] << 16) + (result[8] << 8) + result[9];
+
+        adr = PACE5_FIFO_BURST;
+
+        data_array[0] = ((adr << 1) & 0xff) | 1; // For Read Or with 1
+
+        success = SPI_Transmit(&data_array[0], 1, &result[0], 10);
+
+        max30001_PACE[15] = (uint32_t)(result[1] << 16) + (result[2] << 8) + result[3];
+        max30001_PACE[16] = (uint32_t)(result[4] << 16) + (result[5] << 8) + result[6];
+        max30001_PACE[17] = (uint32_t)(result[7] << 16) + (result[8] << 8) + result[9];
+
+        dataAvailable(MAX30001_DATA_PACE, max30001_PACE, 18); // Send out the Pace data once only
+      }
+    }
+
+    if (etag != 0b110) {
+
+      dataAvailable(MAX30001_DATA_ECG, max30001_ECG_FIFO_buffer, (max30001_mngr_int.bit.e_fit + 1));
+    }
+
+  } /* End of ECG init */
+
+  /* RtoR */
+
+  if (max30001_status.bit.rrint == 1) {
+    if (max30001_reg_read(RTOR, &max30001_RtoR_data) == -1) {
+      return -1;
+    }
+
+    max30001_RtoR_data = (0x00FFFFFF & max30001_RtoR_data) >> 10;
+
+    hspValMax30001.R2R = (uint16_t)max30001_RtoR_data;
+    hspValMax30001.fmstr = (uint16_t)max30001_cnfg_gen.bit.fmstr;
+
+    dataAvailable(MAX30001_DATA_RTOR, &max30001_RtoR_data, 1);
+  }
+
+  // Handling BIOZ data...
+
+  if (max30001_status.bit.bint == 1) {
+    adr = 0x22;
+    data_array[0] = ((adr << 1) & 0xff) | 1;
+
+    /* [(BFIT+1)*3byte]+1extra byte due to the addr */
+
+    if (SPI_Transmit(&data_array[0], 1, &result[0],((max30001_mngr_int.bit.b_fit + 1) * 3) + 1) == -1) // Make a copy of the FIFO over here...
+
+    {
+      return -1;
+    }
+
+    btag = 0b00000111 & result[3];
+
+    /* Put the content of the FIFO based on the BFIT value, We ignore the
+     * result[0] and start concatenating indexes: 1,2,3 - 4,5,6 - 7,8,9 -  */
+    for (i = 0, j = 0; i < max30001_mngr_int.bit.b_fit + 1; i++, j = j + 3) // index1=23-16 bit, index2=15-8 bit, index3=7-0 bit
+    {
+      max30001_BIOZ_FIFO_buffer[i] = ((uint32_t)result[j + 1] << 16) + (result[j + 2] << 8) + result[j + 3];
+    }
+
+    if (btag != 0b110) {
+      dataAvailable(MAX30001_DATA_BIOZ, max30001_BIOZ_FIFO_buffer, 8);
+    }
+  }
+
+  ret_val = 0;
+
+  if (max30001_status.bit.dcloffint == 1) // ECG/BIOZ Lead Off
+  {
+    dcloffint_OneShot = 1;
+    max30001_DCLeadOff = 0;
+    max30001_DCLeadOff = max30001_DCLeadOff | (max30001_cnfg_gen.bit.en_dcloff << 8) | (max30001_status.all & 0x00000F);
+    dataAvailable(MAX30001_DATA_LEADOFF_DC, &max30001_DCLeadOff, 1);
+    // Do a FIFO Reset
+    max30001_reg_write(FIFO_RST, 0x000000);
+
+    ret_val = 0b100;
+
+  } else if (dcloffint_OneShot == 1 && max30001_status.bit.dcloffint == 0) // Just send once when it comes out of dc lead off
+  {
+    max30001_DCLeadOff = 0;
+    max30001_DCLeadOff = max30001_DCLeadOff | (max30001_cnfg_gen.bit.en_dcloff << 8) | (max30001_status.all & 0x00000F);
+    dataAvailable(MAX30001_DATA_LEADOFF_DC, &max30001_DCLeadOff, 1);
+    dcloffint_OneShot = 0;
+  }
+
+  if (max30001_status.bit.bover == 1 || max30001_status.bit.bundr == 1) // BIOZ AC Lead Off
+  {
+    acloffint_OneShot = 1;
+    max30001_ACLeadOff = 0;
+    max30001_ACLeadOff =
+        max30001_ACLeadOff | ((max30001_status.all & 0x030000) >> 16);
+    dataAvailable(MAX30001_DATA_LEADOFF_AC, &max30001_ACLeadOff, 1);
+    // Do a FIFO Reset
+    max30001_reg_write(FIFO_RST, 0x000000);
+
+    ret_val = 0b1000;
+  } else if (acloffint_OneShot == 1 && max30001_status.bit.bover == 0 && max30001_status.bit.bundr == 0) // Just send once when it comes out of ac lead off
+  {
+    max30001_ACLeadOff = 0;
+    max30001_ACLeadOff = max30001_ACLeadOff | ((max30001_status.all & 0x030000) >> 16);
+    dataAvailable(MAX30001_DATA_LEADOFF_AC, &max30001_ACLeadOff, 1);
+    acloffint_OneShot = 0;
+  }
+
+  if (max30001_status.bit.bcgmon == 1) // BIOZ BCGMON check
+  {
+    bcgmon_OneShot = 1;
+    max30001_bcgmon = 0;
+    max30001_bcgmon = max30001_bcgmon | ((max30001_status.all & 0x000030) >> 4);
+    dataAvailable(MAX30001_DATA_BCGMON, &max30001_bcgmon, 1);
+    // Do a FIFO Reset
+    max30001_reg_write(FIFO_RST, 0x000000);
+
+    ret_val = 0b10000;
+  } else if (bcgmon_OneShot == 1 && max30001_status.bit.bcgmon == 0) {
+    max30001_bcgmon = 0;
+    max30001_bcgmon = max30001_bcgmon | ((max30001_status.all & 0x000030) >> 4);
+    bcgmon_OneShot = 0;
+    dataAvailable(MAX30001_DATA_BCGMON, &max30001_bcgmon, 1);
+  }
+
+#if 0
+if(max30001_status.bit.lonint == 1)   // AC LeadON Check
+{
+	max30001_LeadOn = 0;
+	max30001_reg_read(STATUS,&max30001_status.all);        // Reading is important
+	max30001_LeadOn = max30001_LeadOn | (max30001_cnfg_gen.bit.en_ulp_lon << 8) | ((max30001_status.all & 0x000800) >> 11);  // 0b01 will mean ECG Lead On, 0b10 will mean BIOZ Lead On
+    // LEAD ON has been detected... Now take actions
+}
+#endif
+
+  if (max30001_status.bit.lonint == 1 &&
+      acleadon_OneShot == 0) // AC LeadON Check, when lead is on
+  {
+    max30001_LeadOn = 0;
+    max30001_reg_read(STATUS, &max30001_status.all); // Reading is important
+    max30001_LeadOn =
+        max30001_LeadOn | (max30001_cnfg_gen.bit.en_ulp_lon << 8) |
+        ((max30001_status.all & 0x000800) >>
+         11); // 0b01 will mean ECG Lead On, 0b10 will mean BIOZ Lead On
+
+    // LEAD ON has been detected... Now take actions
+    acleadon_OneShot = 1;
+    dataAvailable(MAX30001_DATA_ACLEADON, &max30001_LeadOn, 1); // One shot data will be sent...
+  } else if (max30001_status.bit.lonint == 0 && acleadon_OneShot == 1) {
+    max30001_LeadOn = 0;
+    max30001_reg_read(STATUS, &max30001_status.all);
+    max30001_LeadOn =
+        max30001_LeadOn | (max30001_cnfg_gen.bit.en_ulp_lon << 8) | ((max30001_status.all & 0x000800) >> 11); // 0b01 will mean ECG Lead On, 0b10 will mean BIOZ Lead On
+    dataAvailable(MAX30001_DATA_ACLEADON, &max30001_LeadOn, 1); // One shot data will be sent...
+    acleadon_OneShot = 0;
+  }
+
+  return ret_val;
+}
+
+//******************************************************************************
+
+int MAX30001::max30001_int_handler(void) {
+
+  static uint32_t InitReset = 0;
+
+  int8_t return_value;
+
+  max30001_reg_read(STATUS, &max30001_status.all);
+
+  // Inital Reset and any FIFO over flow invokes a FIFO reset
+  if (InitReset == 0 || max30001_status.bit.eovf == 1 || max30001_status.bit.bovf == 1 || max30001_status.bit.povf == 1) {
+    // Do a FIFO Reset
+    max30001_reg_write(FIFO_RST, 0x000000);
+
+    InitReset++;
+    return 2;
+  }
+
+  return_value = 0;
+
+  // The four data handling goes on over here
+  if (max30001_status.bit.eint == 1 || max30001_status.bit.pint == 1 || max30001_status.bit.bint == 1 || max30001_status.bit.rrint == 1) {
+    return_value = return_value | max30001_FIFO_LeadONOff_Read();
+  }
+
+  // ECG/BIOZ DC Lead Off test
+  if (max30001_status.bit.dcloffint == 1) {
+    return_value = return_value | max30001_FIFO_LeadONOff_Read();
+  }
+
+  // BIOZ AC Lead Off test
+  if (max30001_status.bit.bover == 1 || max30001_status.bit.bundr == 1) {
+    return_value = return_value | max30001_FIFO_LeadONOff_Read();
+  }
+
+  // BIOZ DRVP/N test using BCGMON.
+  if (max30001_status.bit.bcgmon == 1) {
+    return_value = return_value | max30001_FIFO_LeadONOff_Read();
+  }
+
+  if (max30001_status.bit.lonint == 1) // ECG Lead ON test: i.e. the leads are touching the body...
+  {
+
+    max30001_FIFO_LeadONOff_Read();
+  }
+
+  return return_value;
+}
+
+/// function pointer to the async callback
+static event_callback_t functionpointer;
+/// flag used to indicate an async xfer has taken place
+static volatile int xferFlag = 0;
+
+/**
+* @brief Callback handler for SPI async events
+* @param events description of event that occurred
+*/
+static void spiHandler(int events) { xferFlag = 1; }
+
+/**
+* @brief Transmit and recieve QUAD SPI data
+* @param tx_buf pointer to transmit byte buffer
+* @param tx_size number of bytes to transmit
+* @param rx_buf pointer to the recieve buffer
+* @param rx_size number of bytes to recieve
+*/
+int MAX30001::SPI_Transmit(const uint8_t *tx_buf, uint32_t tx_size, uint8_t *rx_buf, uint32_t rx_size) {
+  xferFlag = 0;
+  int i;
+  for (i = 0; i < sizeof(buffer); i++) {
+    if (i < tx_size)
+      buffer[i] = tx_buf[i];
+    else
+      buffer[i] = 0xFF;
+  }
+  spi->transfer<uint8_t>(buffer, (int)rx_size, rx_buf, (int)rx_size, spiHandler /* functionpointer */);
+  while (xferFlag == 0);
+  return 0;
+}
+
+//******************************************************************************
+void MAX30001::max30001_ReadHeartrateData(max30001_t *_hspValMax30001) {
+  _hspValMax30001->R2R = hspValMax30001.R2R;
+  _hspValMax30001->fmstr = hspValMax30001.fmstr;
+}
+
+//******************************************************************************
+void MAX30001::onDataAvailable(PtrFunction _onDataAvailable) {
+  onDataAvailableCallback = _onDataAvailable;
+}
+
+/**
+* @brief Used to notify an external function that interrupt data is available
+* @param id type of data available
+* @param buffer 32-bit buffer that points to the data
+* @param length length of 32-bit elements available
+*/
+void MAX30001::dataAvailable(uint32_t id, uint32_t *buffer, uint32_t length) {
+  if (onDataAvailableCallback != NULL) {
+    (*onDataAvailableCallback)(id, buffer, length);
+  }
+}
+
+/**
+* @brief Callback handler for SPI async events
+* @param events description of event that occurred
+*/
+void MAX30001::spiHandler(int events) { xferFlag = 1; }
+
+//******************************************************************************
+static int allowInterrupts = 0;
+
+void MAX30001Mid_IntB_Handler(void) {
+  if (allowInterrupts == 0) return;
+  MAX30001::instance->max30001_int_handler();
+}
+
+void MAX30001Mid_Int2B_Handler(void) {
+  if (allowInterrupts == 0) return;
+  MAX30001::instance->max30001_int_handler();
+}
+
+void MAX30001_AllowInterrupts(int state) { 
+allowInterrupts = state; 
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/e4a10ed6eb92/HSP/Devices/MAX30001/MAX30001/MAX30001.h	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,1076 @@
+/*******************************************************************************
+* Copyright (C) 2015 Maxim Integrated Products, Inc., All Rights Reserved.
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included
+* in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+* OTHER DEALINGS IN THE SOFTWARE.
+*
+* Except as contained in this notice, the name of Maxim Integrated
+* Products, Inc. shall not be used except as stated in the Maxim Integrated
+* Products, Inc. Branding Policy.
+*
+* The mere transfer of this software does not imply any licenses
+* of trade secrets, proprietary technology, copyrights, patents,
+* trademarks, maskwork rights, or any other form of intellectual
+* property whatsoever. Maxim Integrated Products, Inc. retains all
+* ownership rights.
+*******************************************************************************/
+/*
+ * max30001.h
+ *
+ *  Created on: Oct 9, 2015
+ *      Author: faisal.tariq
+ */
+
+#ifndef MAX30001_H_
+#define MAX30001_H_
+
+#include "mbed.h"
+
+#define mbed_COMPLIANT // Uncomment to Use timer for MAX30001 FCLK (for mbed)
+                       // Comment to use the RTC clock
+
+#define ASYNC_SPI_BUFFER_SIZE (32 * 3) // Maximimum buffer size for async byte transfers
+
+// Defines for data callbacks
+#define MAX30001_DATA_ECG        0x30
+#define MAX30001_DATA_PACE       0x31
+#define MAX30001_DATA_RTOR       0x32
+#define MAX30001_DATA_BIOZ       0x33
+#define MAX30001_DATA_LEADOFF_DC 0x34
+#define MAX30001_DATA_LEADOFF_AC 0x35
+#define MAX30001_DATA_BCGMON     0x36
+#define MAX30001_DATA_ACLEADON   0x37
+
+#define MAX30001_SPI_MASTER_PORT 0
+#define MAX30001_SPI_SS_INDEX    0
+
+#define MAX30001_INT_PORT_B      3
+#define MAX30001_INT_PIN_B       6
+
+#define MAX30001_INT_PORT_2B     4
+#define MAX30001_INT_PIN_2B      5
+
+#define MAX30001_INT_PORT_FCLK   1
+#define MAX30001_INT_PIN_FCLK    7
+
+#define MAX30001_FUNC_SEL_TMR    2 // 0=FW Control, 1= Pulse Train, 2=Timer
+
+#define MAX30001_INDEX    3
+#define MAX30001_POLARITY 0
+#define MAX30001_PERIOD   30518
+#define MAX30001_CYCLE    50
+
+#define MAX30001_IOMUX_IO_ENABLE 1
+
+#define MAX30001_SPI_PORT            0
+#define MAX30001_CS_PIN              0
+#define MAX30001_CS_POLARITY         0
+#define MAX30001_CS_ACTIVITY_DELAY   0
+#define MAX30001_CS_INACTIVITY_DELAY 0
+#define MAX30001_CLK_HI              1
+#define MAX30001_CLK_LOW             1
+#define MAX30001_ALT_CLK             0
+#define MAX30001_CLK_POLARITY        0
+#define MAX30001_CLK_PHASE           0
+#define MAX30001_WRITE               1
+#define MAX30001_READ                0
+
+#define MAX30001_INT_PORT_B  3
+#define MAX30001INT_PIN_B    6
+
+void MAX30001_AllowInterrupts(int state);
+
+/**
+* Maxim Integrated MAX30001 ECG/BIOZ chip
+*/
+class MAX30001 {
+
+public:
+  typedef enum { // MAX30001 Register addresses
+    STATUS     = 0x01,
+    EN_INT     = 0x02,
+    EN_INT2    = 0x03,
+    MNGR_INT   = 0x04,
+    MNGR_DYN   = 0x05,
+    SW_RST     = 0x08,
+    SYNCH      = 0x09,
+    FIFO_RST   = 0x0A,
+    INFO       = 0x0F,
+    CNFG_GEN   = 0x10,
+    CNFG_CAL   = 0x12,
+    CNFG_EMUX  = 0x14,
+    CNFG_ECG   = 0x15,
+    CNFG_BMUX  = 0x17,
+    CNFG_BIOZ  = 0x18,
+    CNFG_PACE  = 0x1A,
+    CNFG_RTOR1 = 0x1D,
+    CNFG_RTOR2 = 0x1E,
+
+    // Data locations
+    ECG_FIFO_BURST = 0x20,
+    ECG_FIFO       = 0x21,
+    FIFO_BURST     = 0x22,
+    BIOZ_FIFO      = 0x23,
+    RTOR           = 0x25,
+
+    PACE0_FIFO_BURST = 0x30,
+    PACE0_A          = 0x31,
+    PACE0_B          = 0x32,
+    PACE0_C          = 0x33,
+
+    PACE1_FIFO_BURST = 0x34,
+    PACE1_A          = 0x35,
+    PACE1_B          = 0x36,
+    PACE1_C          = 0x37,
+
+    PACE2_FIFO_BURST = 0x38,
+    PACE2_A          = 0x39,
+    PACE2_B          = 0x3A,
+    PACE2_C          = 0x3B,
+
+    PACE3_FIFO_BURST = 0x3C,
+    PACE3_A          = 0x3D,
+    PACE3_B          = 0x3E,
+    PACE3_C          = 0x3F,
+
+    PACE4_FIFO_BURST = 0x40,
+    PACE4_A          = 0x41,
+    PACE4_B          = 0x42,
+    PACE4_C          = 0x43,
+
+    PACE5_FIFO_BURST = 0x44,
+    PACE5_A          = 0x45,
+    PACE5_B          = 0x46,
+    PACE5_C          = 0x47,
+
+  } MAX30001_REG_map_t;
+
+  /**
+   * @brief STATUS (0x01) 
+   */
+  union max30001_status_reg {
+    uint32_t all;
+
+    struct {
+      uint32_t loff_nl : 1;
+      uint32_t loff_nh : 1;
+      uint32_t loff_pl : 1;
+      uint32_t loff_ph : 1;
+
+      uint32_t bcgmn     : 1;
+      uint32_t bcgmp     : 1;
+      uint32_t reserved1 : 1;
+      uint32_t reserved2 : 1;
+
+      uint32_t pllint : 1;
+      uint32_t samp   : 1;
+      uint32_t rrint  : 1;
+      uint32_t lonint : 1;
+
+      uint32_t pedge  : 1;
+      uint32_t povf   : 1;
+      uint32_t pint   : 1;
+      uint32_t bcgmon : 1;
+
+      uint32_t bundr : 1;
+      uint32_t bover : 1;
+      uint32_t bovf  : 1;
+      uint32_t bint  : 1;
+
+      uint32_t dcloffint : 1;
+      uint32_t fstint    : 1;
+      uint32_t eovf      : 1;
+      uint32_t eint      : 1;
+
+      uint32_t reserved : 8;
+
+    } bit;
+
+  } max30001_status;
+
+  
+  /**
+   * @brief EN_INT (0x02) 
+   */
+
+  union max30001_en_int_reg {
+    uint32_t all;
+
+    struct {
+      uint32_t intb_type : 2;
+      uint32_t reserved1 : 1;
+      uint32_t reserved2 : 1;
+
+      uint32_t reserved3 : 1;
+      uint32_t reserved4 : 1;
+      uint32_t reserved5 : 1;
+      uint32_t reserved6 : 1;
+
+      uint32_t en_pllint : 1;
+      uint32_t en_samp   : 1;
+      uint32_t en_rrint  : 1;
+      uint32_t en_lonint : 1;
+
+      uint32_t en_pedge  : 1;
+      uint32_t en_povf   : 1;
+      uint32_t en_pint   : 1;
+      uint32_t en_bcgmon : 1;
+
+      uint32_t en_bundr : 1;
+      uint32_t en_bover : 1;
+      uint32_t en_bovf  : 1;
+      uint32_t en_bint  : 1;
+
+      uint32_t en_dcloffint : 1;
+      uint32_t en_fstint    : 1;
+      uint32_t en_eovf      : 1;
+      uint32_t en_eint      : 1;
+
+      uint32_t reserved : 8;
+
+    } bit;
+
+  } max30001_en_int;
+
+  
+  /**
+   * @brief EN_INT2 (0x03) 
+   */  
+  union max30001_en_int2_reg {
+    uint32_t all;
+
+    struct {
+      uint32_t intb_type : 2;
+      uint32_t reserved1 : 1;
+      uint32_t reserved2 : 1;
+
+      uint32_t reserved3 : 1;
+      uint32_t reserved4 : 1;
+      uint32_t reserved5 : 1;
+      uint32_t reserved6 : 1;
+
+      uint32_t en_pllint : 1;
+      uint32_t en_samp   : 1;
+      uint32_t en_rrint  : 1;
+      uint32_t en_lonint : 1;
+
+      uint32_t en_pedge  : 1;
+      uint32_t en_povf   : 1;
+      uint32_t en_pint   : 1;
+      uint32_t en_bcgmon : 1;
+
+      uint32_t en_bundr  : 1;
+      uint32_t en_bover  : 1;
+      uint32_t en_bovf   : 1;
+      uint32_t en_bint   : 1;
+
+      uint32_t en_dcloffint : 1;
+      uint32_t en_fstint    : 1;
+      uint32_t en_eovf      : 1;
+      uint32_t en_eint      : 1;
+
+      uint32_t reserved : 8;
+
+    } bit;
+
+  } max30001_en_int2;
+
+  /**
+   * @brief MNGR_INT (0x04) 
+   */  
+  union max30001_mngr_int_reg {
+    uint32_t all;
+
+    struct {
+      uint32_t samp_it   : 2;
+      uint32_t clr_samp  : 1;
+      uint32_t clr_pedge : 1;
+      uint32_t clr_rrint : 2;
+      uint32_t clr_fast  : 1;
+      uint32_t reserved1 : 1;
+      uint32_t reserved2 : 4;
+      uint32_t reserved3 : 4;
+
+      uint32_t b_fit     : 3;
+      uint32_t e_fit     : 5;
+
+      uint32_t reserved : 8;
+
+    } bit;
+
+  } max30001_mngr_int;
+
+   /**
+   * @brief MNGR_DYN (0x05) 
+   */ 
+  union max30001_mngr_dyn_reg {
+    uint32_t all;
+
+    struct {
+      uint32_t bloff_lo_it : 8;
+      uint32_t bloff_hi_it : 8;
+      uint32_t fast_th     : 6;
+      uint32_t fast        : 2;
+      uint32_t reserved    : 8;
+    } bit;
+
+  } max30001_mngr_dyn;
+
+  // 0x08
+  // uint32_t max30001_sw_rst;
+
+  // 0x09
+  // uint32_t max30001_synch;
+
+  // 0x0A
+  // uint32_t max30001_fifo_rst;
+
+  
+   /**
+   * @brief INFO (0x0F) 
+   */
+  union max30001_info_reg {
+    uint32_t all;
+    struct {
+      uint32_t serial    : 12;
+      uint32_t part_id   : 2;
+      uint32_t sample    : 1;
+      uint32_t reserved1 : 1;
+      uint32_t rev_id    : 4;
+      uint32_t pattern   : 4;
+      uint32_t reserved  : 8;
+    } bit;
+
+  } max30001_info;
+
+   /**
+   * @brief CNFG_GEN (0x10) 
+   */
+  union max30001_cnfg_gen_reg {
+    uint32_t all;
+    struct {
+      uint32_t rbiasn     : 1;
+      uint32_t rbiasp     : 1;
+      uint32_t rbiasv     : 2;
+      uint32_t en_rbias   : 2;
+      uint32_t vth        : 2;
+      uint32_t imag       : 3;
+      uint32_t ipol       : 1;
+      uint32_t en_dcloff  : 2;
+      uint32_t en_bloff   : 2;
+      uint32_t reserved1  : 1;
+      uint32_t en_pace    : 1;
+      uint32_t en_bioz    : 1;
+      uint32_t en_ecg     : 1;
+      uint32_t fmstr      : 2;
+      uint32_t en_ulp_lon : 2;
+      uint32_t reserved : 8;
+    } bit;
+
+  } max30001_cnfg_gen;
+
+  
+   /**
+   * @brief CNFG_CAL (0x12) 
+   */  
+  union max30001_cnfg_cal_reg {
+    uint32_t all;
+    struct {
+      uint32_t thigh     : 11;
+      uint32_t fifty     : 1;
+      uint32_t fcal      : 3;
+      uint32_t reserved1 : 5;
+      uint32_t vmag      : 1;
+      uint32_t vmode     : 1;
+      uint32_t en_vcal   : 1;
+      uint32_t reserved2 : 1;
+      uint32_t reserved  : 8;
+    } bit;
+
+  } max30001_cnfg_cal;
+
+   /**
+   * @brief CNFG_EMUX  (0x14) 
+   */
+  union max30001_cnfg_emux_reg {
+    uint32_t all;
+    struct {
+      uint32_t reserved1 : 16;
+      uint32_t caln_sel  : 2;
+      uint32_t calp_sel  : 2;
+      uint32_t openn     : 1;
+      uint32_t openp     : 1;
+      uint32_t reserved2 : 1;
+      uint32_t pol       : 1;
+      uint32_t reserved : 8;
+    } bit;
+
+  } max30001_cnfg_emux;
+
+  
+   /**
+   * @brief CNFG_ECG   (0x15) 
+   */  
+  union max30001_cnfg_ecg_reg {
+    uint32_t all;
+    struct {
+      uint32_t reserved1 : 12;
+      uint32_t dlpf      : 2;
+      uint32_t dhpf      : 1;
+      uint32_t reserved2 : 1;
+      uint32_t gain      : 2;
+      uint32_t reserved3 : 4;
+      uint32_t rate      : 2;
+
+      uint32_t reserved  : 8;
+    } bit;
+
+  } max30001_cnfg_ecg;
+
+   /**
+   * @brief CNFG_BMUX   (0x17) 
+   */  
+  union max30001_cnfg_bmux_reg {
+    uint32_t all;
+    struct {
+      uint32_t fbist     : 2;
+      uint32_t reserved1 : 2;
+      uint32_t rmod      : 3;
+      uint32_t reserved2 : 1;
+      uint32_t rnom      : 3;
+      uint32_t en_bist   : 1;
+      uint32_t cg_mode   : 2;
+      uint32_t reserved3 : 2;
+      uint32_t caln_sel  : 2;
+      uint32_t calp_sel  : 2;
+      uint32_t openn     : 1;
+      uint32_t openp     : 1;
+      uint32_t reserved4 : 2;
+      uint32_t reserved : 8;
+    } bit;
+
+  } max30001_cnfg_bmux;
+
+   /**
+   * @brief CNFG_BIOZ   (0x18) 
+   */ 
+  union max30001_bioz_reg {
+    uint32_t all;
+    struct {
+      uint32_t phoff     : 4;
+      uint32_t cgmag     : 3;
+      uint32_t cgmon     : 1;
+      uint32_t fcgen     : 4;
+      uint32_t dlpf      : 2;
+      uint32_t dhpf      : 2;
+      uint32_t gain      : 2;
+      uint32_t reserved1 : 1;
+      uint32_t ext_rbias : 1;
+      uint32_t ahpf      : 3;
+      uint32_t rate      : 1;
+      uint32_t reserved : 8;
+    } bit;
+
+  } max30001_cnfg_bioz;
+
+  
+   /**
+   * @brief CNFG_PACE   (0x1A) 
+   */   
+  union max30001_cnfg_pace_reg {
+    uint32_t all;
+
+    struct {
+      uint32_t dacn        : 4;
+      uint32_t dacp        : 4;
+      uint32_t reserved1   : 4;
+      uint32_t aout        : 2;
+      uint32_t aout_lbw    : 1;
+      uint32_t reserved2   : 1;
+      uint32_t gain        : 3;
+      uint32_t gn_diff_off : 1;
+      uint32_t reserved3   : 3;
+      uint32_t pol         : 1;
+      uint32_t reserved    : 8;
+    } bit;
+
+  } max30001_cnfg_pace;
+
+   /**
+   * @brief CNFG_RTOR1   (0x1D) 
+   */   
+  union max30001_cnfg_rtor1_reg {
+    uint32_t all;
+    struct {
+      uint32_t reserved1 : 8;
+      uint32_t ptsf      : 4;
+      uint32_t pavg      : 2;
+      uint32_t reserved2 : 1;
+      uint32_t en_rtor   : 1;
+      uint32_t gain      : 4;
+      uint32_t wndw      : 4;
+      uint32_t reserved : 8;
+    } bit;
+
+  } max30001_cnfg_rtor1;
+
+   /**
+   * @brief CNFG_RTOR2 (0x1E) 
+   */   
+  union max30001_cnfg_rtor2_reg {
+    uint32_t all;
+    struct {
+      uint32_t reserved1 : 8;
+      uint32_t rhsf      : 3;
+      uint32_t reserved2 : 1;
+      uint32_t ravg      : 2;
+      uint32_t reserved3 : 2;
+      uint32_t hoff      : 6;
+      uint32_t reserved4 : 2;
+      uint32_t reserved : 8;
+    } bit;
+
+  } max30001_cnfg_rtor2;
+
+  /*********************************************************************************/
+
+  typedef enum {
+    MAX30001_NO_INT = 0, // No interrupt
+    MAX30001_INT_B  = 1,  // INTB selected for interrupt
+    MAX30001_INT_2B = 2  // INT2B selected for interrupt
+  } max30001_intrpt_Location_t;
+
+  typedef enum {
+    MAX30001_INT_DISABLED = 0b00,
+    MAX30001_INT_CMOS     = 0b01,
+    MAX30001_INT_ODN      = 0b10,
+    MAX30001_INT_ODNR     = 0b11
+  } max30001_intrpt_type_t;
+
+  typedef enum {          // Input Polarity selection
+    MAX30001_NON_INV = 0, // Non-Inverted
+    MAX30001_INV     = 1      // Inverted
+  } max30001_emux_pol;
+
+  typedef enum {              // OPENP and OPENN setting
+    MAX30001_ECG_CON_AFE = 0, // ECGx is connected to AFE channel
+    MAX30001_ECG_ISO_AFE = 1  // ECGx is isolated from AFE channel
+  } max30001_emux_openx;
+
+  typedef enum {                // EMUX_CALP_SEL & EMUX_CALN_SEL
+    MAX30001_NO_CAL_SIG = 0b00, // No calibration signal is applied
+    MAX30001_INPT_VMID  = 0b01,  // Input is connected to VMID
+    MAX30001_INPT_VCALP = 0b10, // Input is connected to VCALP
+    MAX30001_INPT_VCALN = 0b11  // Input is connected to VCALN
+  } max30001_emux_calx_sel;
+
+  typedef enum {                     // EN_ECG, EN_BIOZ, EN_PACE
+    MAX30001_CHANNEL_DISABLED = 0b0, //
+    MAX30001_CHANNEL_ENABLED = 0b1
+  } max30001_en_feature;
+
+  /*********************************************************************************/
+  // Data
+  uint32_t max30001_ECG_FIFO_buffer[32]; // (303 for internal test)
+  uint32_t max30001_BIOZ_FIFO_buffer[8]; // (303 for internal test)
+
+  uint32_t max30001_PACE[18]; // Pace Data 0-5
+
+  uint32_t max30001_RtoR_data; // This holds the RtoR data
+
+  uint32_t max30001_DCLeadOff; // This holds the LeadOff data, Last 4 bits give
+                               // the status, BIT3=LOFF_PH, BIT2=LOFF_PL,
+                               // BIT1=LOFF_NH, BIT0=LOFF_NL
+                               // 8th and 9th bits tell Lead off is due to ECG or BIOZ.  
+                               // 0b01 = ECG Lead Off and 0b10 = BIOZ Lead off
+
+  uint32_t max30001_ACLeadOff; // This gives the state of the BIOZ AC Lead Off
+                               // state.  BIT 1 = BOVER,   BIT 0 = BUNDR
+
+  uint32_t max30001_bcgmon; // This holds the BCGMON data, BIT 1 = BCGMP, BIT0 =
+                            // BCGMN
+
+  uint32_t max30001_LeadOn; // This holds the LeadOn data, BIT1 = BIOZ Lead ON,
+                            // BIT0 = ECG Lead ON, BIT8= Lead On Status Bit
+
+  uint32_t max30001_timeout; // If the PLL does not respond, timeout and get out.
+
+  typedef struct { // Creating a structure for BLE data
+    int16_t R2R;
+    int16_t fmstr;
+  } max30001_t;
+
+  max30001_t hspValMax30001; // R2R, FMSTR
+
+  /**
+  * @brief Constructor that accepts pin names for the SPI interface
+  * @param spi pointer to the mbed SPI object
+  */
+  MAX30001(SPI *spi);
+
+  /**
+  * @brief Constructor that accepts pin names for the SPI interface
+  * @param mosi master out slave in pin name
+  * @param miso master in slave out pin name
+  * @param sclk serial clock pin name
+  * @param cs chip select pin name
+  */
+  MAX30001(PinName mosi, PinName miso, PinName sclk, PinName cs);
+
+  /**
+   * MAX30001 destructor
+   */
+  ~MAX30001(void);
+
+  /**
+   * @brief This function sets up the Resistive Bias mode and also selects the master clock frequency.
+   * @brief Uses Register: CNFG_GEN-0x10
+   * @param En_rbias: Enable and Select Resitive Lead Bias Mode
+   * @param Rbiasv: Resistive Bias Mode Value Selection
+   * @param Rbiasp: Enables Resistive Bias on Positive Input
+   * @param Rbiasn: Enables Resistive Bias on Negative Input
+   * @param Fmstr: Selects Master Clock Frequency
+   * @returns 0-if no error.  A non-zero value indicates an error.
+   *
+  */
+  int max30001_Rbias_FMSTR_Init(uint8_t En_rbias, uint8_t Rbiasv,
+                                uint8_t Rbiasp, uint8_t Rbiasn, uint8_t Fmstr);
+
+  /**
+   * @brief This function uses sets up the calibration signal internally.  If it is desired to use the internal signal, then
+   * @brief this function must be called and the registers set, prior to setting the CALP_SEL and CALN_SEL in the ECG_InitStart
+   * @brief and BIOZ_InitStart functions.
+   * @brief Uses Register: CNFG_CAL-0x12
+   * @param En_Vcal: Calibration Source (VCALP and VCALN) Enable
+   * @param Vmode:   Calibration Source Mode Selection
+   * @param Vmag:    Calibration Source Magnitude Selection (VMAG)
+   * @param Fcal:    Calibration Source Frequency Selection (FCAL)
+   * @param Thigh:   Calibration Source Time High Selection
+   * @param Fifty:   Calibration Source Duty Cycle Mode Selection
+   * @returns 0-if no error.  A non-zero value indicates an error.
+   *
+   */
+  int max30001_CAL_InitStart(uint8_t En_Vcal, uint8_t Vmode, uint8_t Vmag,
+                             uint8_t Fcal, uint16_t Thigh, uint8_t Fifty);
+
+  /**
+   * @brief This function disables the VCAL signal
+   * @returns 0-if no error.  A non-zero value indicates an error.
+   */
+  int max30001_CAL_Stop(void);
+
+  /**
+   * @brief This function handles the assignment of the two interrupt pins (INTB & INT2B) with various
+   * @brief functions/behaviors  of the MAX30001.  Also, each pin can be configured for different drive capability.
+   * @brief Uses Registers: EN_INT-0x02 and EN_INT2-0x03.
+   * @param max30001_intrpt_Locatio_t  <argument>:  All the arguments with the aforementioned enumeration essentially
+   *        can be configured to generate an interrupt on either INTB or INT2B or NONE.
+   * @param max30001_intrpt_type_t  intb_Type:  INTB Port Type (EN_INT Selections).
+   * @param max30001_intrpt_type _t int2b_Type:   INT2B Port Type (EN_INT2 Selections)
+   * @returns 0-if no error.  A non-zero value indicates an error.
+   *
+   */
+     int max30001_INT_assignment(max30001_intrpt_Location_t en_enint_loc,     max30001_intrpt_Location_t en_eovf_loc,  max30001_intrpt_Location_t en_fstint_loc,
+		                 max30001_intrpt_Location_t en_dcloffint_loc, max30001_intrpt_Location_t en_bint_loc,  max30001_intrpt_Location_t en_bovf_loc,
+		                 max30001_intrpt_Location_t en_bover_loc,     max30001_intrpt_Location_t en_bundr_loc, max30001_intrpt_Location_t en_bcgmon_loc,
+		                 max30001_intrpt_Location_t en_pint_loc,      max30001_intrpt_Location_t en_povf_loc,  max30001_intrpt_Location_t en_pedge_loc,
+		                 max30001_intrpt_Location_t en_lonint_loc,    max30001_intrpt_Location_t en_rrint_loc, max30001_intrpt_Location_t en_samp_loc,
+		                 max30001_intrpt_type_t  intb_Type,           max30001_intrpt_type_t int2b_Type);
+
+
+
+  /**
+   * @brief For MAX30001/3 ONLY
+   * @brief This function sets up the MAX30001 for the ECG measurements.
+   * @brief Registers used:  CNFG_EMUX, CNFG_GEN, MNGR_INT, CNFG_ECG.
+   * @param En_ecg: ECG Channel Enable <CNFG_GEN register bits>
+   * @param Openp: Open the ECGN Input Switch (most often used for testing and calibration studies) <CNFG_EMUX register bits>
+   * @param Openn: Open the ECGN Input Switch (most often used for testing and calibration studies) <CNFG_EMUX register bits>
+   * @param Calp_sel: ECGP Calibration Selection <CNFG_EMUX register bits>
+   * @param Caln_sel: ECGN Calibration Selection <CNFG_EMUX register bits>
+   * @param E_fit: ECG FIFO Interrupt Threshold (issues EINT based on number of unread FIFO records) <CNFG_GEN register bits>
+   * @param Clr_rrint: RTOR R Detect Interrupt (RRINT) Clear Behavior <CNFG_GEN register bits>
+   * @param Rate: ECG Data Rate
+   * @param Gain: ECG Channel Gain Setting
+   * @param Dhpf: ECG Channel Digital High Pass Filter Cutoff Frequency
+   * @param Dlpf:  ECG Channel Digital Low Pass Filter Cutoff Frequency
+   * @returns 0-if no error.  A non-zero value indicates an error.
+   *
+   */
+  int max30001_ECG_InitStart(uint8_t En_ecg, uint8_t Openp, uint8_t Openn,
+                             uint8_t Pol, uint8_t Calp_sel, uint8_t Caln_sel,
+                             uint8_t E_fit, uint8_t Rate, uint8_t Gain,
+                             uint8_t Dhpf, uint8_t Dlpf);
+
+  /**
+   * @brief For MAX30001/3 ONLY
+   * @brief This function enables the Fast mode feature of the ECG.
+   * @brief Registers used: MNGR_INT-0x04, MNGR_DYN-0x05
+   * @param Clr_Fast: FAST MODE Interrupt Clear Behavior <MNGR_INT Register>
+   * @param Fast: ECG Channel Fast Recovery Mode Selection (ECG High Pass Filter Bypass) <MNGR_DYN Register>
+   * @param Fast_Th: Automatic Fast Recovery Threshold
+   * @returns 0-if no error.  A non-zero value indicates an error.
+   *
+   */
+  int max30001_ECGFast_Init(uint8_t Clr_Fast, uint8_t Fast, uint8_t Fast_Th);
+
+  /**
+  * @brief For MAX30001/3 ONLY
+  * @brief This function disables the ECG.
+  * @brief Uses Register CNFG_GEN-0x10.
+  * @returns 0-if no error.  A non-zero value indicates an error.
+  *
+  */
+  int max30001_Stop_ECG(void);
+
+  /**
+   *  @brief For MAX30001 ONLY
+   *  @brief This function sets up the MAX30001 for pace signal detection.
+   *  @brief If both PACE and BIOZ are turned ON, then make sure Fcgen is set for 80K or 40K in the
+   *  @brief max30001_BIOZ_InitStart() function.  However, if Only PACE is on but BIOZ off, then Fcgen can be set
+   *  @brief for 80K only, in the max30001_BIOZ_InitStart() function
+   *  @brief Registers used: MNGR_INT-0x04, CNFG_GEN-0x37, CNFG_PACE-0x1A.
+   *  @param En_pace : PACE Channel Enable <CNFG_GEN Register>
+   *  @param Clr_pedge : PACE Edge Detect Interrupt (PEDGE) Clear Behavior <MNGR_INT Register>
+   *  @param Pol: PACE Input Polarity Selection <CNFG_PACE Register>
+   *  @param Gn_diff_off: PACE Differentiator Mode <CNFG_PACE Register>
+   *  @param Gain: PACE Channel Gain Selection <CNFG_PACE Register>
+   *  @param Aout_lbw:  PACE Analog Output Buffer Bandwidth Mode <CNFG_PACE Register>
+   *  @param Aout: PACE Single Ended Analog Output Buffer Signal Monitoring Selection <CNFG_PACE Register>
+   *  @param Dacp (4bits): PACE Detector Positive Comparator Threshold <CNFG_PACE Register>
+   *  @param Dacn(4bits): PACE Detector Negative Comparator Threshold <CNFG_PACE Register>
+   *  @returns 0-if no error.  A non-zero value indicates an error <CNFG_PACE Register>
+   *
+   */
+  int max30001_PACE_InitStart(uint8_t En_pace, uint8_t Clr_pedge, uint8_t Pol,
+                              uint8_t Gn_diff_off, uint8_t Gain,
+                              uint8_t Aout_lbw, uint8_t Aout, uint8_t Dacp,
+                              uint8_t Dacn);
+
+  /**
+   *@brief For MAX30001 ONLY
+   *@param This function disables the PACE.  Uses Register CNFG_GEN-0x10.
+   *@returns 0-if no error.  A non-zero value indicates an error.
+   *
+   */
+  int max30001_Stop_PACE(void);
+
+  /**
+   * @brief For MAX30001/2 ONLY
+   * @brief This function sets up the MAX30001 for BIOZ measurement.
+   * @brief Registers used: MNGR_INT-0x04, CNFG_GEN-0X10, CNFG_BMUX-0x17,CNFG_BIOZ-0x18.
+   * @param En_bioz: BIOZ Channel Enable <CNFG_GEN Register>
+   * @param Openp: Open the BIP Input Switch <CNFG_BMUX Register>
+   * @param Openn: Open the BIN Input Switch <CNFG_BMUX Register>
+   * @param Calp_sel: BIP Calibration Selection <CNFG_BMUX Register>
+   * @param Caln_sel: BIN Calibration Selection <CNFG_BMUX Register>
+   * @param CG_mode:  BIOZ Current Generator Mode Selection <CNFG_BMUX Register>
+   * @param B_fit:  BIOZ FIFO Interrupt Threshold (issues BINT based on number of unread FIFO records) <MNGR_INT Register>
+   * @param Rate: BIOZ Data Rate <CNFG_BIOZ Register>
+   * @param Ahpf: BIOZ/PACE Channel Analog High Pass Filter Cutoff Frequency and Bypass <CNFG_BIOZ Register>
+   * @param Ext_rbias:  External Resistor Bias Enable <CNFG_BIOZ Register>
+   * @param Gain: BIOZ Channel Gain Setting <CNFG_BIOZ Register>
+   * @param Dhpf: BIOZ Channel Digital High Pass Filter Cutoff Frequency <CNFG_BIOZ Register>
+   * @param Dlpf:  BIOZ Channel Digital Low Pass Filter Cutoff Frequency <CNFG_BIOZ Register>
+   * @param Fcgen:  BIOZ Current Generator Modulation Frequency <CNFG_BIOZ Register>
+   * @param Cgmon:  BIOZ Current Generator Monitor <CNFG_BIOZ Register>
+   * @param Cgmag:  BIOZ Current Generator Magnitude <CNFG_BIOZ Register>
+   * @param Phoff: BIOZ Current Generator Modulation Phase Offset <CNFG_BIOZ Register>
+   * @returns 0-if no error.  A non-zero value indicates an error.
+   *
+   */
+  int max30001_BIOZ_InitStart(uint8_t En_bioz, uint8_t Openp, uint8_t Openn,
+                              uint8_t Calp_sel, uint8_t Caln_sel,
+                              uint8_t CG_mode,
+                              /* uint8_t En_bioz,*/ uint8_t B_fit, uint8_t Rate,
+                              uint8_t Ahpf, uint8_t Ext_rbias, uint8_t Gain,
+                              uint8_t Dhpf, uint8_t Dlpf, uint8_t Fcgen,
+                              uint8_t Cgmon, uint8_t Cgmag, uint8_t Phoff);
+
+  /**
+   * @brief For MAX30001/2 ONLY
+   * @brief This function disables the BIOZ.  Uses Register CNFG_GEN-0x10.
+   * @returns 0-if no error.  A non-zero value indicates an error.
+       * @returns 0-if no error.  A non-zero value indicates an error.
+   *
+   */
+  int max30001_Stop_BIOZ(void);
+
+  /**
+   * @brief For MAX30001/2 ONLY
+   * @brief BIOZ modulated Resistance Built-in-Self-Test, Registers used: CNFG_BMUX-0x17
+   * @param En_bist: Enable Modulated Resistance Built-in-Self-test <CNFG_BMUX Register>
+   * @param Rnom: BIOZ RMOD BIST Nominal Resistance Selection <CNFG_BMUX Register>
+   * @param Rmod: BIOZ RMOD BIST Modulated Resistance Selection <CNFG_BMUX Register>
+   * @param Fbist: BIOZ RMOD BIST Frequency Selection <CNFG_BMUX Register>
+   * @returns 0-if no error.  A non-zero value indicates an error.
+   *
+   */
+  int max30001_BIOZ_InitBist(uint8_t En_bist, uint8_t Rnom, uint8_t Rmod,
+                             uint8_t Fbist);
+
+  /**
+   * @brief For MAX30001/3/4 ONLY
+   * @brief Sets up the device for RtoR measurement
+   * @param EN_rtor: ECG RTOR Detection Enable <RTOR1 Register>
+   * @param Wndw: R to R Window Averaging (Window Width = RTOR_WNDW[3:0]*8mS) <RTOR1 Register>
+   * @param Gain: R to R Gain (where Gain = 2^RTOR_GAIN[3:0], plus an auto-scale option) <RTOR1 Register>
+   * @param Pavg: R to R Peak Averaging Weight Factor <RTOR1 Register>
+   * @param Ptsf: R to R Peak Threshold Scaling Factor <RTOR1 Register>
+   * @param Hoff: R to R minimum Hold Off <RTOR2 Register>
+   * @param Ravg: R to R Interval Averaging Weight Factor <RTOR2 Register>
+   * @param Rhsf: R to R Interval Hold Off Scaling Factor <RTOR2 Register>
+   * @param Clr_rrint: RTOR Detect Interrupt Clear behaviour <MNGR_INT Register>
+   * @returns 0-if no error.  A non-zero value indicates an error.
+   *
+   */
+  int max30001_RtoR_InitStart(uint8_t En_rtor, uint8_t Wndw, uint8_t Gain,
+                              uint8_t Pavg, uint8_t Ptsf, uint8_t Hoff,
+                              uint8_t Ravg, uint8_t Rhsf, uint8_t Clr_rrint);
+
+  /**
+   * @brief For MAX30001/3/4 ONLY
+   * @brief This function disables the RtoR.  Uses Register CNFG_RTOR1-0x1D
+   * @returns 0-if no error.  A non-zero value indicates an error.
+   *
+   */
+  int max30001_Stop_RtoR(void);
+
+  /**
+   * @brief This is a function that waits for the PLL to lock; once a lock is achieved it exits out. (For convenience only)
+   * @returns 0-if no error.  A non-zero value indicates an error.
+   *
+   */
+  int max30001_PLL_lock(void);
+
+  /**
+   * @brief This function causes the MAX30001 to reset.  Uses Register SW_RST-0x08
+   * @return 0-if no error.  A non-zero value indicates an error.
+   *
+   */
+  int max30001_sw_rst(void);
+
+  /**
+   * @brief This function provides a SYNCH operation.  Uses Register SYCNH-0x09. Please refer to the data sheet for
+   * @brief the details on how to use this.
+   * @returns 0-if no error.  A non-zero value indicates an error.
+   *
+   */
+  int max30001_synch(void);
+
+  /**
+   * @brief This function performs a FIFO Reset.  Uses Register FIFO_RST-0x0A. Please refer to the data sheet
+   * @brief for the details on how to use this.
+   * @returns 0-if no error.  A non-zero value indicates an error.
+   */
+  int max300001_fifo_rst(void);
+
+  /**
+   *
+   * @brief This is a callback function which collects all the data from the ECG, BIOZ, PACE and RtoR. It also handles
+   * @brief Lead On/Off.  This  function is passed through the argument of max30001_COMMinit().
+   * @returns 0-if no error.  A non-zero value indicates an error.
+   *
+   */
+  int max30001_int_handler(void);
+
+  /**
+   * @brief This is function called from the max30001_int_handler() function and processes all the ECG, BIOZ, PACE
+   * @brief and the RtoR data and sticks them in appropriate arrays and variables each unsigned 32 bits.
+   * @param ECG data will be in the array (input): max30001_ECG_FIFO_buffer[]
+   * @param Pace data will be in the array (input): max30001_PACE[]
+   * @param RtoRdata will be in the variable (input): max30001_RtoR_data
+   * @param BIOZ data will be in the array (input): max30001_BIOZ_FIFO_buffer[]
+   * @param global  max30001_ECG_FIFO_buffer[]
+   * @param global  max30001_PACE[]
+   * @param global  max30001_BIOZ_FIFO_buffer[]
+   * @param global  max30001_RtoR_data
+   * @param global  max30001_DCLeadOff
+   * @param global  max30001_ACLeadOff
+   * @param global  max30001_LeadON
+   * @returns 0-if no error.  A non-zero value indicates an error.
+   *
+   */
+  int max30001_FIFO_LeadONOff_Read(void);
+
+  /**
+   * @brief This function allows writing to a register.
+   * @param addr:  Address of the register to write to
+   * @param data:  24-bit data read from the register.
+   * @returns 0-if no error.  A non-zero value indicates an error.
+   *
+   */
+  int max30001_reg_write(MAX30001_REG_map_t addr, uint32_t data);
+
+  /**
+   * @brief This function allows reading from a register
+   * @param addr:   Address of the register to read from.
+   * @param *return_data: pointer to the value read from the register.
+   * @returns 0-if no error.  A non-zero value indicates an error.
+   *
+   */
+  int max30001_reg_read(MAX30001_REG_map_t addr, uint32_t *return_data);
+
+  /**
+   * @brief This function enables the DC Lead Off detection. Either ECG or BIOZ can be detected, one at a time.
+   * @brief Registers Used:  CNFG_GEN-0x10
+   * @param En_dcloff: BIOZ Digital Lead Off Detection Enable
+   * @param Ipol: DC Lead Off Current Polarity (if current sources are enabled/connected)
+   * @param Imag: DC Lead off current Magnitude Selection
+   * @param Vth: DC Lead Off Voltage Threshold Selection
+   * @returns 0-if no error.  A non-zero value indicates an error.
+   *
+   */
+  int max30001_Enable_DcLeadOFF_Init(int8_t En_dcloff, int8_t Ipol, int8_t Imag,
+                                     int8_t Vth);
+
+  /**
+   * @brief This function disables the DC Lead OFF feature, whichever is active.
+   * @returns 0-if no error.  A non-zero value indicates an error.
+   *
+   */
+  int max30001_Disable_DcLeadOFF(void);
+
+  /**
+   * @brief This function sets up the BIOZ for AC Lead Off test.
+   * @brief Registers Used:  CNFG_GEN-0x10, MNGR_DYN-0x05
+   * @param En_bloff: BIOZ Digital Lead Off Detection Enable <CNFG_GEN register>
+   * @param Bloff_hi_it:      DC Lead Off Current Polarity (if current sources are enabled/connected) <MNGR_DYN register>
+   * @param Bloff_lo_it:      DC Lead off current Magnitude Selection <MNGR_DYN register>
+   * @returns 0-if no error.  A non-zero value indicates an error.
+   *
+   */
+  int max30001_BIOZ_Enable_ACLeadOFF_Init(uint8_t En_bloff, uint8_t Bloff_hi_it,
+                                          uint8_t Bloff_lo_it);
+
+  /**
+   * @brief This function Turns of the BIOZ AC Lead OFF feature
+   * @brief Registers Used:  CNFG_GEN-0x10
+   * @returns 0-if no error.  A non-zero value indicates an error.
+   *
+   */
+  int max30001_BIOZ_Disable_ACleadOFF(void);
+
+  /**
+   * @brief This function enables the Current Gnerator Monitor
+   * @brief Registers Used:  CNFG_BIOZ-0x18
+   * @returns 0-if no error.  A non-zero value indicates an error.
+   *
+   */
+  int max30001_BIOZ_Enable_BCGMON(void);
+
+  /**
+   *
+   * @brief This function enables the Lead ON detection. Either ECG or BIOZ can be detected, one at a time.
+   * @brief Also, the en_bioz, en_ecg, en_pace setting is saved so that when this feature is disabled through the
+   * @brief max30001_Disable_LeadON() function (or otherwise) the enable/disable state of those features can be retrieved.
+   * @param Channel: ECG or BIOZ detection
+   * @returns 0-if everything is good.  A non-zero value indicates an error.
+   *
+   */
+  int max30001_Enable_LeadON(int8_t Channel);
+
+  /**
+   * @brief This function turns off the Lead ON feature, whichever one is active.  Also, retrieves the en_bioz,
+   * @brief en_ecg, en_pace and sets it back to as it was.
+   * @param 0-if everything is good.  A non-zero value indicates an error.
+   *
+   */
+  int max30001_Disable_LeadON(void);
+
+  /**
+   *
+   * @brief This function is toggled every 2 seconds to switch between ECG Lead ON and BIOZ Lead ON detect
+   * @brief Adjust LEADOFF_SERVICE_TIME to determine the duration between the toggles.
+   * @param CurrentTime - This gets fed the time by RTC_GetValue function
+   *
+   */
+  void max30001_ServiceLeadON(uint32_t currentTime);
+
+  /**
+   *
+   * @brief This function is toggled every 2 seconds to switch between ECG DC Lead Off and BIOZ DC Lead Off
+   * @brief Adjust LEADOFF_SERVICE_TIME to determine the duration between the toggles.
+   * @param CurrentTime - This gets fed the time by RTC_GetValue function
+   *
+   */
+  void max30001_ServiceLeadoff(uint32_t currentTime);
+
+  /**
+   *
+   * @brief This function sets current RtoR values and fmstr values in a pointer structure
+   * @param hspValMax30001 - Pointer to a structure where to store the values
+   *
+   */
+  void max30001_ReadHeartrateData(max30001_t *_hspValMax30001);
+
+  /**
+   * @brief type definition for data interrupt
+   */
+  typedef void (*PtrFunction)(uint32_t id, uint32_t *buffer, uint32_t length);
+
+  /**
+   * @brief Used to connect a callback for when interrupt data is available
+   */
+  void onDataAvailable(PtrFunction _onDataAvailable);
+
+  static MAX30001 *instance;
+
+private:
+  void dataAvailable(uint32_t id, uint32_t *buffer, uint32_t length);
+  /// interrupt handler for async spi events
+  static void spiHandler(int events);
+  /// wrapper method to transmit and recieve SPI data
+  int SPI_Transmit(const uint8_t *tx_buf, uint32_t tx_size, uint8_t *rx_buf,
+                   uint32_t rx_size);
+
+  /// pointer to mbed SPI object
+  SPI *spi;
+  /// is this object the owner of the spi object
+  bool spi_owner;
+  /// buffer to use for async transfers
+  uint8_t buffer[ASYNC_SPI_BUFFER_SIZE];
+  /// function pointer to the async callback
+  event_callback_t functionpointer;
+  /// callback function when interrupt data is available
+  PtrFunction onDataAvailableCallback;
+
+}; // End of MAX30001 Class
+
+/**
+ * @brief Preventive measure used to dismiss interrupts that fire too early during
+ * @brief initialization on INTB line
+ *
+ */
+void MAX30001Mid_IntB_Handler(void);
+
+/**
+ * @brief Preventive measure used to dismiss interrupts that fire too early during
+ * @brief initialization on INT2B line
+ *
+ */
+void MAX30001Mid_Int2B_Handler(void);
+
+/**
+ * @brief Allows Interrupts to be accepted as valid.
+ * @param state: 1-Allow interrupts, Any-Don't allow interrupts.
+ *
+ */
+void MAX30001_AllowInterrupts(int state);
+
+#endif /* MAX30001_H_ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/e4a10ed6eb92/HSP/Devices/MAX30001/MAX30001_RPC.cpp	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,477 @@
+/*******************************************************************************
+ * Copyright (C) 2016 Maxim Integrated Products, Inc., All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+ * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Except as contained in this notice, the name of Maxim Integrated
+ * Products, Inc. shall not be used except as stated in the Maxim Integrated
+ * Products, Inc. Branding Policy.
+ *
+ * The mere transfer of this software does not imply any licenses
+ * of trade secrets, proprietary technology, copyrights, patents,
+ * trademarks, maskwork rights, or any other form of intellectual
+ * property whatsoever. Maxim Integrated Products, Inc. retains all
+ * ownership rights.
+ *******************************************************************************
+ */
+
+#include <stdio.h>
+#include "StringHelper.h"
+#include "MAX30001.h"
+#include "Streaming.h"
+#include "StringInOut.h"
+#include "MAX30001_helper.h"
+#include "RpcFifo.h"
+#include "RpcServer.h"
+#include "Peripherals.h"
+#include "DataLoggingService.h"
+
+/*static int startedEcg = 0;
+static int startedBioz = 0;
+static int startedCal = 0;
+static int startedPace = 0;
+static int startedRtor = 0;
+static void StopAll();
+*/
+
+extern int highDataRate;
+
+uint32_t max30001_RegRead(MAX30001::MAX30001_REG_map_t addr) {
+  uint32_t data;
+  Peripherals::max30001()->max30001_reg_read(addr, &data);
+  return data;
+}
+
+void max30001_RegWrite(MAX30001::MAX30001_REG_map_t addr, uint32_t data) {
+  Peripherals::max30001()->max30001_reg_write(addr, data);
+}
+
+int MAX30001_WriteReg(char argStrs[32][32], char replyStrs[32][32]) {
+  uint32_t args[2];
+  uint32_t reply[1];
+  uint32_t value;
+  ProcessArgs32(argStrs, args, sizeof(args) / sizeof(uint32_t));
+
+  max30001_RegWrite((MAX30001::MAX30001_REG_map_t)args[0], args[1]);
+  reply[0] = 0x80;
+  FormatReply32(reply, sizeof(reply) / sizeof(uint32_t), replyStrs);
+  return 0;
+}
+
+int MAX30001_ReadReg(char argStrs[32][32], char replyStrs[32][32]) {
+  uint32_t args[1];
+  uint32_t reply[1];
+  uint32_t value;
+  ProcessArgs32(argStrs, args, sizeof(args) / sizeof(uint32_t));
+  value = max30001_RegRead((MAX30001::MAX30001_REG_map_t)args[0]);
+  reply[0] = value;
+  FormatReply32(reply, sizeof(reply) / sizeof(uint32_t), replyStrs);
+  return 0;
+}
+
+int MAX30001_Rbias_FMSTR_Init(char argStrs[32][32], char replyStrs[32][32]) {
+  uint32_t args[5];
+  uint32_t reply[1];
+  uint32_t value;
+  ProcessArgs32(argStrs, args, sizeof(args) / sizeof(uint32_t));
+
+  value = Peripherals::max30001()->max30001_Rbias_FMSTR_Init(args[0],  // En_rbias
+                                                             args[1],  // Rbiasv
+                                                             args[2],  // Rbiasp
+                                                             args[3],  // Rbiasn
+                                                             args[4]); // Fmstr
+
+  reply[0] = value;
+  FormatReply32(reply, sizeof(reply) / sizeof(uint32_t), replyStrs);
+  return 0;
+}
+
+int MAX30001_CAL_InitStart(char argStrs[32][32], char replyStrs[32][32]) {
+  uint32_t args[6];
+  uint32_t reply[1];
+  uint32_t value;
+  ProcessArgs32(argStrs, args, sizeof(args) / sizeof(uint32_t));
+
+  // Peripherals::serial()->printf("MAX30001_CAL_InitStart 0 ");
+  value = Peripherals::max30001()->max30001_CAL_InitStart(args[0], // En_Vcal
+                                                          args[1], // Vmag
+                                                          args[2], // Fcal
+                                                          args[3], // Thigh
+                                                          args[4], // Fifty
+                                                          args[5]); // Vmode
+
+  reply[0] = value;
+  FormatReply32(reply, sizeof(reply) / sizeof(uint32_t), replyStrs);
+  return 0;
+}
+
+int MAX30001_ECG_InitStart(char argStrs[32][32], char replyStrs[32][32]) {
+  uint32_t args[11];
+  uint32_t reply[1];
+  uint32_t value;
+  ProcessArgs32(argStrs, args, sizeof(args) / sizeof(uint32_t));
+
+  // Peripherals::serial()->printf("MAX30001_ECG_InitStart 0 ");
+  value = Peripherals::max30001()->max30001_ECG_InitStart(args[0], // En_ecg
+                                                          args[1], // Openp
+                                                          args[2], // Openn
+                                                          args[3], // Pol
+                                                          args[4], // Calp_sel
+                                                          args[5], // Caln_sel
+                                                          args[6], // E_fit
+                                                          args[7], // Rate
+                                                          args[8], // Gain
+                                                          args[9], // Dhpf
+                                                          args[10]); // Dlpf
+  // Peripherals::serial()->printf("MAX30001_ECG_InitStart 1 ");
+  MAX30001_Helper_SetStreamingFlag(eStreaming_ECG, 1);
+  reply[0] = value;
+  FormatReply32(reply, sizeof(reply) / sizeof(uint32_t), replyStrs);
+  return 0;
+}
+
+int MAX30001_ECGFast_Init(char argStrs[32][32], char replyStrs[32][32]) {
+  uint32_t args[3];
+  uint32_t reply[1];
+  uint32_t value;
+  ProcessArgs32(argStrs, args, sizeof(args) / sizeof(uint32_t));
+
+  value = Peripherals::max30001()->max30001_ECGFast_Init(args[0], // Clr_Fast
+                                                         args[1], // Fast
+                                                         args[2]); // Fast_Th
+
+  reply[0] = value;
+  FormatReply32(reply, sizeof(reply) / sizeof(uint32_t), replyStrs);
+  return 0;
+}
+
+int MAX30001_PACE_InitStart(char argStrs[32][32], char replyStrs[32][32]) {
+  uint32_t args[9];
+  uint32_t reply[1];
+  uint32_t value;
+  ProcessArgs32(argStrs, args, sizeof(args) / sizeof(uint32_t));
+
+  value =
+      Peripherals::max30001()->max30001_PACE_InitStart(args[0], // En_pace
+                                                       args[1], // Clr_pedge
+                                                       args[2], // Pol
+                                                       args[3], // Gn_diff_off
+                                                       args[4], // Gain
+                                                       args[5], // Aout_lbw
+                                                       args[6], // Aout
+                                                       args[7], // Dacp
+                                                       args[8]); // Dacn
+
+  MAX30001_Helper_SetStreamingFlag(eStreaming_PACE, 1);
+  reply[0] = value;
+  FormatReply32(reply, sizeof(reply) / sizeof(uint32_t), replyStrs);
+  return 0;
+}
+
+int MAX30001_BIOZ_InitStart(char argStrs[32][32], char replyStrs[32][32]) {
+  uint32_t args[17];
+  uint32_t reply[1];
+  uint32_t value;
+  ProcessArgs32(argStrs, args, sizeof(args) / sizeof(uint32_t));
+
+  value = Peripherals::max30001()->max30001_BIOZ_InitStart(args[0], // En_bioz
+                                                           args[1], // Openp
+                                                           args[2], // Openn
+                                                           args[3], // Calp_sel
+                                                           args[4], // Caln_sel
+                                                           args[5], // CG_mode
+                                                           args[6], // B_fit
+                                                           args[7], // Rate
+                                                           args[8], // Ahpf
+                                                           args[9], // Ext_rbias
+                                                           args[10], // Gain
+                                                           args[11], // Dhpf
+                                                           args[12], // Dlpf
+                                                           args[13], // Fcgen
+                                                           args[14], // Cgmon
+                                                           args[15], // Cgmag
+                                                           args[16]); // Phoff
+
+  MAX30001_Helper_SetStreamingFlag(eStreaming_BIOZ, 1);
+  reply[0] = value;
+  FormatReply32(reply, sizeof(reply) / sizeof(uint32_t), replyStrs);
+  return 0;
+}
+
+int MAX30001_RtoR_InitStart(char argStrs[32][32], char replyStrs[32][32]) {
+  uint32_t args[9];
+  uint32_t reply[1];
+  uint32_t value;
+  ProcessArgs32(argStrs, args, sizeof(args) / sizeof(uint32_t));
+
+  value =  Peripherals::max30001()->max30001_RtoR_InitStart(args[0], // En_rtor
+                                                            args[1], // Wndw
+                                                            args[2], // Gain
+                                                            args[3], // Pavg
+                                                            args[4], // Ptsf
+                                                            args[5], // Hoff
+                                                            args[6], // Ravg
+                                                            args[7], // Rhsf
+                                                            args[8]); // Clr_rrint
+
+  MAX30001_Helper_SetStreamingFlag(eStreaming_RtoR, 1);
+  reply[0] = value;
+  FormatReply32(reply, sizeof(reply) / sizeof(uint32_t), replyStrs);
+  return 0;
+}
+
+int MAX30001_Stop_ECG(char argStrs[32][32], char replyStrs[32][32]) {
+  uint32_t reply[1];
+  Peripherals::max30001()->max30001_Stop_ECG();
+  reply[0] = 0x80;
+  FormatReply32(reply, sizeof(reply) / sizeof(uint32_t), replyStrs);
+  return 0;
+}
+int MAX30001_Stop_PACE(char argStrs[32][32], char replyStrs[32][32]) {
+  uint32_t reply[1];
+  Peripherals::max30001()->max30001_Stop_PACE();
+  reply[0] = 0x80;
+  FormatReply32(reply, sizeof(reply) / sizeof(uint32_t), replyStrs);
+  return 0;
+}
+int MAX30001_Stop_BIOZ(char argStrs[32][32], char replyStrs[32][32]) {
+  uint32_t reply[1];
+  Peripherals::max30001()->max30001_Stop_BIOZ();
+  reply[0] = 0x80;
+  FormatReply32(reply, sizeof(reply) / sizeof(uint32_t), replyStrs);
+  return 0;
+}
+int MAX30001_Stop_RtoR(char argStrs[32][32], char replyStrs[32][32]) {
+  uint32_t reply[1];
+  Peripherals::max30001()->max30001_Stop_RtoR();
+  reply[0] = 0x80;
+  FormatReply32(reply, sizeof(reply) / sizeof(uint32_t), replyStrs);
+  return 0;
+}
+int MAX30001_Stop_Cal(char argStrs[32][32], char replyStrs[32][32]) {
+  uint32_t reply[1];
+  // max30001_Stop_Cal();
+  reply[0] = 0x80;
+  FormatReply32(reply, sizeof(reply) / sizeof(uint32_t), replyStrs);
+  return 0;
+}
+
+void max30001_ServiceStreaming() {
+  char ch;
+  uint32_t val;
+  USBSerial *usbSerial = Peripherals::usbSerial();
+
+  fifo_clear(GetStreamOutFifo());
+
+  SetStreaming(TRUE);
+  clearOutReadFifo();
+  while (IsStreaming() == TRUE) {
+
+    if (fifo_empty(GetStreamOutFifo()) == 0) {
+      fifo_get32(GetStreamOutFifo(), &val);
+
+      usbSerial->printf("%02X ", val);
+
+    }
+    if (usbSerial->available()) {
+      ch = usbSerial->_getc();
+
+      MAX30001_Helper_Stop();
+      SetStreaming(FALSE);
+      fifo_clear(GetUSBIncomingFifo()); // clear USB serial incoming fifo
+      fifo_clear(GetStreamOutFifo());
+    }
+
+  }
+}
+
+int MAX30001_Start(char argStrs[32][32], char replyStrs[32][32]) {
+  uint32_t reply[1];
+  uint32_t all;
+  fifo_clear(GetUSBIncomingFifo());
+  Peripherals::max30001()->max30001_synch();
+  //	max30001_ServiceStreaming();
+  highDataRate = 0;
+  Peripherals::max30001()->max30001_reg_read(MAX30001::STATUS, &all);
+  LoggingService_StartLoggingUsb();
+
+  reply[0] = 0x80;
+  FormatReply32(reply, sizeof(reply) / sizeof(uint32_t), replyStrs);
+  return 0;
+}
+
+int MAX30001_Stop(char argStrs[32][32], char replyStrs[32][32]) {
+  /*	uint32_t args[1];
+          uint32_t reply[1];
+          uint32_t value;
+          //ProcessArgs32(argStrs, args, sizeof(args) / sizeof(uint32_t));
+          max30001_StopTest();
+          reply[0] = 0x80;
+          FormatReply32(reply, sizeof(reply) / sizeof(uint32_t), replyStrs);*/
+  return 0;
+}
+
+int MAX30001_INT_assignment(char argStrs[32][32], char replyStrs[32][32]) {
+  uint32_t args[17];
+  uint32_t reply[1];
+  ProcessArgs32(argStrs, args, sizeof(args) / sizeof(uint32_t));
+  /*
+  printf("MAX30001_INT_assignment ");
+  printf("%d ",args[0]);
+  printf("%d ",args[1]);
+  printf("%d ",args[2]);
+  printf("%d ",args[3]);
+  printf("%d ",args[4]);
+  printf("%d ",args[5]);
+  printf("%d ",args[6]);
+  printf("%d ",args[7]);
+  printf("%d ",args[8]);
+  printf("%d ",args[9]);
+  printf("%d ",args[10]);
+  printf("%d ",args[11]);
+  printf("%d ",args[12]);
+  printf("%d ",args[13]);
+  printf("%d ",args[14]);
+  printf("%d ",args[15]);
+  printf("%d ",args[16]);
+  printf("\n");
+  fflush(stdout);
+  */
+
+  Peripherals::max30001()->max30001_INT_assignment(
+      (MAX30001::max30001_intrpt_Location_t)args[0],
+      (MAX30001::max30001_intrpt_Location_t)args[1],
+      (MAX30001::max30001_intrpt_Location_t)args[2],
+      (MAX30001::max30001_intrpt_Location_t)args[3],
+      (MAX30001::max30001_intrpt_Location_t)args[4],
+      (MAX30001::max30001_intrpt_Location_t)args[5],
+      (MAX30001::max30001_intrpt_Location_t)args[6],
+      (MAX30001::max30001_intrpt_Location_t)args[7],
+      (MAX30001::max30001_intrpt_Location_t)args[8],
+      (MAX30001::max30001_intrpt_Location_t)args[9],
+      (MAX30001::max30001_intrpt_Location_t)args[10],
+      (MAX30001::max30001_intrpt_Location_t)args[11],
+      (MAX30001::max30001_intrpt_Location_t)args[12],
+      (MAX30001::max30001_intrpt_Location_t)args[13],
+      (MAX30001::max30001_intrpt_Location_t)args[14],
+      (MAX30001::max30001_intrpt_type_t)args[15],
+      (MAX30001::max30001_intrpt_type_t)args[16]);
+  reply[0] = 0x80;
+  FormatReply32(reply, sizeof(reply) / sizeof(uint32_t), replyStrs);
+  return 0;
+}
+
+int MAX30001_StartTest(char argStrs[32][32], char replyStrs[32][32]) {
+  uint32_t reply[1];
+  // ProcessArgs32(argStrs, args, sizeof(args) / sizeof(uint32_t));
+
+  /*** Set FMSTR over here ****/
+
+  /*** Set and Start the VCAL input ***/
+  /* NOTE VCAL must be set first if VCAL is to be used */
+  Peripherals::max30001()->max30001_CAL_InitStart(0b1, 0b1, 0b1, 0b011, 0x7FF, 0b0);
+
+  /**** ECG Initialization ****/
+  Peripherals::max30001()->max30001_ECG_InitStart(0b1, 0b1, 0b1, 0b0, 0b10, 0b11, 31, 0b00, 0b00, 0b0, 0b01);
+
+  /***** PACE Initialization ***/
+  Peripherals::max30001()->max30001_PACE_InitStart(0b1, 0b0, 0b0, 0b1, 0b000, 0b0, 0b00, 0b0, 0b0);
+
+  /**** BIOZ Initialization ****/
+  Peripherals::max30001()->max30001_BIOZ_InitStart(
+      0b1, 0b1, 0b1, 0b10, 0b11, 0b00, 7, 0b0, 0b111, 0b0, 0b10, 0b00, 0b00, 0b0001, 0b0, 0b111, 0b0000);
+
+  /*** Set RtoR registers ***/
+  Peripherals::max30001()->max30001_RtoR_InitStart(
+      0b1, 0b0011, 0b1111, 0b00, 0b0011, 0b000001, 0b00, 0b000, 0b01);
+
+  /*** Set Rbias & FMSTR over here ****/
+  Peripherals::max30001()->max30001_Rbias_FMSTR_Init(0b01, 0b10, 0b1, 0b1, 0b00);
+
+  /**** Interrupt Setting  ****/
+
+  /*** Set ECG Lead ON/OFF ***/
+  //     max30001_ECG_LeadOnOff();
+
+  /*** Set BIOZ Lead ON/OFF ***/
+  //     max30001_BIOZ_LeadOnOff();  Does not work yet...
+
+  /**** Do a Synch ****/
+  Peripherals::max30001()->max30001_synch();
+
+  fifo_clear(GetUSBIncomingFifo());
+  max30001_ServiceStreaming();
+
+  reply[0] = 0x80;
+  FormatReply32(reply, sizeof(reply) / sizeof(uint32_t), replyStrs);
+  return 0;
+}
+/*
+static void StopAll() {
+        if (startedEcg == 1) {
+                max30001_Stop_ECG();
+        }
+        if (startedCal == 1) {
+        }
+        if (startedBioz == 1) {
+                max30001_Stop_BIOZ();
+        }
+        if (startedPace == 1) {
+                max30001_Stop_PACE();
+        }
+        if (startedRtor == 1) {
+                max30001_Stop_RtoR();
+        }
+        startedEcg = 0;
+        startedBioz = 0;
+        startedCal = 0;
+        startedPace = 0;
+        startedRtor = 0;
+}
+*/
+/*
+// switch to ECG DC Lead ON
+max30001_Enable_LeadON(0b01);
+// switch to BIOZ DC Lead ON
+max30001_Enable_LeadON(0b10);
+*/
+int MAX30001_Enable_ECG_LeadON(char argStrs[32][32], char replyStrs[32][32]) {
+  uint32_t reply[1];
+  // switch to ECG DC Lead ON
+  Peripherals::max30001()->max30001_Enable_LeadON(0b01);
+  reply[0] = 0x80;
+  FormatReply32(reply, sizeof(reply) / sizeof(uint32_t), replyStrs);
+  return 0;
+}
+int MAX30001_Enable_BIOZ_LeadON(char argStrs[32][32], char replyStrs[32][32]) {
+  uint32_t reply[1];
+  // switch to BIOZ DC Lead ON
+  Peripherals::max30001()->max30001_Enable_LeadON(0b10);
+  reply[0] = 0x80;
+  FormatReply32(reply, sizeof(reply) / sizeof(uint32_t), replyStrs);
+  return 0;
+}
+// uint32_t max30001_LeadOn;     // This holds the LeadOn data, BIT1 = BIOZ Lead ON,  BIT0 = ECG Lead ON
+int MAX30001_Read_LeadON(char argStrs[32][32], char replyStrs[32][32]) {
+  uint32_t reply[1];
+  // return the max30001_LeadOn var from the MAX30001 driver
+  reply[0] = Peripherals::max30001()->max30001_LeadOn;
+  FormatReply32(reply, sizeof(reply) / sizeof(uint32_t), replyStrs);
+  return 0;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/e4a10ed6eb92/HSP/Devices/MAX30001/MAX30001_RPC.h	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,59 @@
+/*******************************************************************************
+ * Copyright (C) 2016 Maxim Integrated Products, Inc., All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+ * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Except as contained in this notice, the name of Maxim Integrated
+ * Products, Inc. shall not be used except as stated in the Maxim Integrated
+ * Products, Inc. Branding Policy.
+ *
+ * The mere transfer of this software does not imply any licenses
+ * of trade secrets, proprietary technology, copyrights, patents,
+ * trademarks, maskwork rights, or any other form of intellectual
+ * property whatsoever. Maxim Integrated Products, Inc. retains all
+ * ownership rights.
+ *******************************************************************************
+ */
+#ifndef __MAX300001_RPC_H
+#define __MAX300001_RPC_H
+
+int MAX30001_WriteReg(char argStrs[32][32], char replyStrs[32][32]);
+int MAX30001_ReadReg(char argStrs[32][32], char replyStrs[32][32]);
+int MAX30001_Start(char argStrs[32][32], char replyStrs[32][32]);
+int MAX30001_Stop(char argStrs[32][32], char replyStrs[32][32]);
+int MAX30001_Rbias_FMSTR_Init(char argStrs[32][32], char replyStrs[32][32]);
+int MAX30001_CAL_InitStart(char argStrs[32][32], char replyStrs[32][32]);
+int MAX30001_ECG_InitStart(char argStrs[32][32], char replyStrs[32][32]);
+int MAX30001_ECGFast_Init(char argStrs[32][32], char replyStrs[32][32]);
+int MAX30001_PACE_InitStart(char argStrs[32][32], char replyStrs[32][32]);
+int MAX30001_BIOZ_InitStart(char argStrs[32][32], char replyStrs[32][32]);
+int MAX30001_RtoR_InitStart(char argStrs[32][32], char replyStrs[32][32]);
+int MAX30001_Stop_ECG(char argStrs[32][32], char replyStrs[32][32]);
+int MAX30001_Stop_PACE(char argStrs[32][32], char replyStrs[32][32]);
+int MAX30001_Stop_BIOZ(char argStrs[32][32], char replyStrs[32][32]);
+int MAX30001_Stop_RtoR(char argStrs[32][32], char replyStrs[32][32]);
+int MAX30001_Stop_Cal(char argStrs[32][32], char replyStrs[32][32]);
+int MAX30001_Enable_ECG_LeadON(char argStrs[32][32], char replyStrs[32][32]);
+int MAX30001_Enable_BIOZ_LeadON(char argStrs[32][32], char replyStrs[32][32]);
+int MAX30001_Read_LeadON(char argStrs[32][32], char replyStrs[32][32]);
+
+int MAX30001_StartTest(char argStrs[32][32], char replyStrs[32][32]);
+int MAX30001_INT_assignment(char argStrs[32][32], char replyStrs[32][32]);
+
+#endif /* __MAX300001_RPC_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/e4a10ed6eb92/HSP/Devices/MAX30001/MAX30001_helper.cpp	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,122 @@
+
+/*******************************************************************************
+ * Copyright (C) 2016 Maxim Integrated Products, Inc., All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+ * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Except as contained in this notice, the name of Maxim Integrated
+ * Products, Inc. shall not be used except as stated in the Maxim Integrated
+ * Products, Inc. Branding Policy.
+ *
+ * The mere transfer of this software does not imply any licenses
+ * of trade secrets, proprietary technology, copyrights, patents,
+ * trademarks, maskwork rights, or any other form of intellectual
+ * property whatsoever. Maxim Integrated Products, Inc. retains all
+ * ownership rights.
+ *******************************************************************************
+ */
+
+#include "MAX30001_helper.h"
+#include "MAX30001.h"
+#include "StringInOut.h"
+#include "Peripherals.h"
+
+static uint8_t flags[4];
+
+int MAX30001_Helper_IsStreaming(eFlags flag) { 
+ return flags[(uint32_t)flag]; 
+}
+
+void MAX30001_Helper_SetStreamingFlag(eFlags flag, uint8_t state) {
+  flags[(uint32_t)flag] = state;
+}
+
+void MAX30001_Helper_Stop(void) {
+  if (flags[(uint32_t)eStreaming_ECG] == 1) {
+    Peripherals::max30001()->max30001_Stop_ECG();
+  }
+  if (flags[(uint32_t)eStreaming_PACE] == 1) {
+    Peripherals::max30001()->max30001_Stop_PACE();
+  }
+  if (flags[(uint32_t)eStreaming_BIOZ] == 1) {
+    Peripherals::max30001()->max30001_Stop_BIOZ();
+  }
+  if (flags[(uint32_t)eStreaming_RtoR] == 1) {
+    Peripherals::max30001()->max30001_Stop_RtoR();
+  }
+  MAX30001_Helper_ClearStreamingFlags();
+}
+
+int MAX30001_AnyStreamingSet(void) {
+  uint32_t i;
+  for (i = 0; i < 4; i++) {
+    if (flags[i] == 1) return 1;
+  }
+  return 0;
+}
+
+void MAX30001_Helper_StartSync(void) {
+  if (MAX30001_AnyStreamingSet() == 1) {
+    Peripherals::max30001()->max30001_synch();
+  }
+}
+
+void MAX30001_Helper_ClearStreamingFlags(void) {
+  uint32_t i;
+  for (i = 0; i < 4; i++) {
+    flags[i] = 0;
+  }
+}
+
+void MAX30001_Helper_Debug_ShowStreamFlags(void) {
+  putStr("\r\n");
+  if (flags[(uint32_t)eStreaming_ECG] == 1) {
+    putStr("eStreaming_ECG, ");
+  }
+  if (flags[(uint32_t)eStreaming_PACE] == 1) {
+    putStr("eStreaming_PACE, ");
+  }
+  if (flags[(uint32_t)eStreaming_BIOZ] == 1) {
+    putStr("eStreaming_BIOZ, ");
+  }
+  if (flags[(uint32_t)eStreaming_RtoR] == 1) {
+    putStr("eStreaming_RtoR, ");
+  }
+  putStr("\r\n");
+}
+
+void MAX30001_Helper_SetupInterrupts() {
+	Peripherals::max30001()->max30001_INT_assignment(MAX30001::MAX30001_INT_B,    MAX30001::MAX30001_NO_INT,   MAX30001::MAX30001_NO_INT,  //  en_enint_loc,      en_eovf_loc,   en_fstint_loc,
+                                                         MAX30001::MAX30001_INT_2B,   MAX30001::MAX30001_INT_2B,   MAX30001::MAX30001_NO_INT,  //  en_dcloffint_loc,  en_bint_loc,   en_bovf_loc,
+                                                         MAX30001::MAX30001_INT_2B,   MAX30001::MAX30001_INT_2B,   MAX30001::MAX30001_NO_INT,  //  en_bover_loc,      en_bundr_loc,  en_bcgmon_loc,
+                                                         MAX30001::MAX30001_INT_B,    MAX30001::MAX30001_NO_INT,   MAX30001::MAX30001_NO_INT,  //  en_pint_loc,       en_povf_loc,   en_pedge_loc,
+                                                         MAX30001::MAX30001_INT_2B,   MAX30001::MAX30001_INT_B,    MAX30001::MAX30001_NO_INT,  //  en_lonint_loc,     en_rrint_loc,  en_samp_loc,
+                                                         MAX30001::MAX30001_INT_ODNR, MAX30001::MAX30001_INT_ODNR);                            //  intb_Type,         int2b_Type)
+}
+
+
+
+static uint8_t serialNumber[6];
+uint8_t *MAX30001_Helper_getVersion(void) {
+  // read the id
+  Peripherals::max30001()->max30001_reg_read(MAX30001::INFO, (uint32_t *)serialNumber);
+  // read id twice because it needs to be read twice
+  Peripherals::max30001()->max30001_reg_read(MAX30001::INFO, (uint32_t *)serialNumber);
+  return serialNumber;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/e4a10ed6eb92/HSP/Devices/MAX30001/MAX30001_helper.h	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,55 @@
+/*******************************************************************************
+ * Copyright (C) 2016 Maxim Integrated Products, Inc., All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+ * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Except as contained in this notice, the name of Maxim Integrated
+ * Products, Inc. shall not be used except as stated in the Maxim Integrated
+ * Products, Inc. Branding Policy.
+ *
+ * The mere transfer of this software does not imply any licenses
+ * of trade secrets, proprietary technology, copyrights, patents,
+ * trademarks, maskwork rights, or any other form of intellectual
+ * property whatsoever. Maxim Integrated Products, Inc. retains all
+ * ownership rights.
+ *******************************************************************************
+ */
+#ifndef MAX30001_HELPER_H_
+#define MAX30001_HELPER_H_
+
+#include "mbed.h"
+
+typedef enum eFlags {
+  eStreaming_ECG,
+  eStreaming_PACE,
+  eStreaming_BIOZ,
+  eStreaming_RtoR
+} eFlags;
+
+int MAX30001_Helper_IsStreaming(eFlags flag);
+void MAX30001_Helper_SetStreamingFlag(eFlags flag, uint8_t state);
+void MAX30001_Helper_Stop(void);
+void MAX30001_Helper_ClearStreamingFlags(void);
+int MAX30001_AnyStreamingSet(void);
+void MAX30001_Helper_Debug_ShowStreamFlags(void);
+void MAX30001_Helper_StartSync(void);
+void MAX30001_Helper_SetupInterrupts(void);
+uint8_t *MAX30001_Helper_getVersion(void);
+
+#endif /* MAX30001_HELPER_H_ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/e4a10ed6eb92/HSP/Devices/MAX30101/MAX30101/MAX30101.cpp	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,703 @@
+
+/*******************************************************************************
+ * Copyright (C) 2016 Maxim Integrated Products, Inc., All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+ * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Except as contained in this notice, the name of Maxim Integrated
+ * Products, Inc. shall not be used except as stated in the Maxim Integrated
+ * Products, Inc. Branding Policy.
+ *
+ * The mere transfer of this software does not imply any licenses
+ * of trade secrets, proprietary technology, copyrights, patents,
+ * trademarks, maskwork rights, or any other form of intellectual
+ * property whatsoever. Maxim Integrated Products, Inc. retains all
+ * ownership rights.
+ *******************************************************************************
+ */
+
+#include "mbed.h"
+#include "MAX30101.h"
+
+MAX30101 *MAX30101::instance = NULL;
+
+//******************************************************************************
+MAX30101::MAX30101(PinName sda, PinName scl, int slaveAddress): 
+          slaveAddress(slaveAddress) {
+  i2c = new I2C(sda, scl);
+  i2c_owner = true;
+  i2c->frequency(400000);
+  onInterruptCallback = NULL;
+  onDataAvailableCallback = NULL;
+  instance = this;
+}
+
+//******************************************************************************
+MAX30101::MAX30101(I2C *_i2c, int slaveAddress) : 
+          slaveAddress(slaveAddress) {
+  i2c = _i2c;
+  i2c_owner = false;
+  i2c->frequency(400000);
+  onInterruptCallback = NULL;
+  onDataAvailableCallback = NULL;
+  instance = this;
+}
+
+//******************************************************************************
+MAX30101::~MAX30101(void) {
+  if (i2c_owner) {
+    delete i2c;
+  }
+}
+
+//******************************************************************************
+int MAX30101::int_handler(void) {
+  uint16_t index, i;
+  uint16_t rx_bytes, second_rx_bytes;
+  char temp_int;
+  char temp_frac;
+  uint16_t num_active_led;
+  uint32_t sample;
+  int loop = 1;
+  static uint8_t cntr_int = 0;
+
+
+  cntr_int++;
+
+  while (loop) {
+    if (i2c_reg_read(REG_INT_STAT_1, &max30101_Interrupt_Status_1.all) != 0) // Read Interrupt flag bits
+    {
+      return -1;
+    }
+
+    if (i2c_reg_read(REG_INT_STAT_2, &max30101_Interrupt_Status_2.all) != 0) // Read Interrupt flag bits
+    {
+      return -1;
+    }
+
+    if (max30101_Interrupt_Status_1.bit.a_full) {
+      /* Read the sample(s) */
+      char reg = REG_FIFO_DATA;
+
+      num_active_led = 0;
+
+      if (max30101_mode_configuration.bit.mode == 0x02) // Heart Rate mode, i.e. 1 led
+      {
+        num_active_led = 1;
+      } else if (max30101_mode_configuration.bit.mode == 0x03) // SpO2 mode, i.e. 2 led
+      {
+        num_active_led = 2;
+      } else if (max30101_mode_configuration.bit.mode == 0x07) // Multi-LED mode, i.e. 1-4 led
+      {
+        if (max30101_multiLED_mode_ctrl_1.bit.slot1 != 0) {
+          num_active_led++;
+        }
+
+        if (max30101_multiLED_mode_ctrl_1.bit.slot2 != 0) {
+          num_active_led++;
+        }
+
+        if (max30101_multiLED_mode_ctrl_2.bit.slot3 != 0) {
+          num_active_led++;
+        }
+
+        if (max30101_multiLED_mode_ctrl_2.bit.slot4 != 0) {
+          num_active_led++;
+        }
+      }
+               // 3bytes/LED x Number of Active LED x FIFO level selected
+        rx_bytes =  3 * num_active_led * (32-max30101_fifo_configuration.bit.fifo_a_full);   
+
+      second_rx_bytes = rx_bytes;
+
+      /*  The FIFO Size is determined by the Sample size.  The number of bytes
+       * in a Sample is dictated by number of LED's
+       *
+       *   #LED Selected     Bytes in "1" sample
+       *        1                  3
+       *        2                  6
+       *        3                  9
+       *        4                  12
+       *
+       *  The I2C API function limits the number of bytes to read to 256 (i.e.
+       * char).  Therefore, when set for
+       *  Multiple LED's and the FIFO size is set to 32.  It would mean there is
+       * more than 256 bytes.
+       *  In that case two I2C reads have to be made.  However It is important
+       * to not that each "Sample"
+       *  must be read completely and reading only partial number of bytes from
+       * a sample will result in erroneous data.
+       *
+       *  For example:
+       *  Num of LED selected = 3 and FIFO size is set to 32 (i.e. 0 value in
+       * register), then the number of bytes
+       *  will be 3bytes/Led * 3led's * 32 = 288 bytes in all.  Since there are
+       * 3 LED's each sample will contain (3 * 3)
+       *  9bytes.  Therefore Sample 1 = 9bytes, Sample 2 = 18,... Sample 28 =
+       * 252.  Therefore the first
+       *  I2C read should be 252 bytes and the second read should be 288-252 =
+       * 36.
+       *
+       *  It turns out that this size issue comes up only when number of LED
+       * selected is 3 or 4 and choosing 252bytes
+       *  for the first I2C read would work for both Number of LED selection.
+       */
+
+      if (rx_bytes <= CHUNK_SIZE) {
+        I2CM_Read(slaveAddress, &reg, 1, &max30101_rawData[0],
+                  (char)rx_bytes /*total_databytes_1*/);
+      } else {
+        I2CM_Read(slaveAddress, &reg, 1, &max30101_rawData[0], CHUNK_SIZE);
+
+        second_rx_bytes = second_rx_bytes - CHUNK_SIZE;
+        I2CM_Read(slaveAddress, &reg, 1, &max30101_rawData[CHUNK_SIZE],
+                  (char)second_rx_bytes);
+      }
+
+      index = 0;
+
+      for (i = 0; i < rx_bytes; i += 3) {
+        sample = ((uint32_t)(max30101_rawData[i] & 0x03) << 16) | (max30101_rawData[i + 1] << 8) | max30101_rawData[i + 2];
+
+        // Right shift the data based on the LED_PW setting
+        sample = sample >>
+                 (3 -
+                  max30101_spo2_configuration.bit.led_pw); // 0=shift 3, 1=shift 2, 2=shift 1, 3=no shift
+
+        max30101_buffer[index++] = sample;
+      }
+
+      onDataAvailableCallback(MAX30101_OXIMETER_DATA + num_active_led, max30101_buffer, index);
+    }
+
+// This interrupt handles the proximity interrupt, for future enhancements
+#if 0
+   if(max30101_Interrupt_Status_1.bit.prox_int)
+     {
+     max30101_mode_configuration.full=0;
+     max30101_mode_configuration.bit.mode=0x03;     // SpO2 mode
+     i2c_reg_write(REG_MODE_CFG, max30101_mode_configuration.full);
+
+     }
+#endif
+
+    // This interrupt handles the temperature interrupt
+    if (max30101_Interrupt_Status_2.bit.die_temp_rdy) {
+      char reg;
+
+      reg = REG_TINT;
+      if (I2CM_Read(slaveAddress, &reg, 1, &temp_int, 1) != 0) {
+        return -1;
+      }
+
+      reg = REG_TFRAC;
+      if (I2CM_Read(slaveAddress, &reg, 1, &temp_frac, 1) != 0) {
+        return -1;
+      }
+
+      max30101_final_temp = (int8_t)temp_int + 0.0625 * temp_frac;
+
+      if (i2c_reg_write(REG_TEMP_EN, 0x00) != 0) // Die Temperature Config, Temp disable... after one read...
+      {
+        return -1;
+      }
+    }
+
+    if (i2c_reg_read(REG_INT_STAT_1, &max30101_Interrupt_Status_1.all) != 0) // Read Interrupt flag bits
+    {
+      return -1;
+    }
+    if (max30101_Interrupt_Status_1.bit.a_full != 1) {
+      loop = 0;
+    }
+  }
+
+  interruptPostCallback();
+
+
+  return 0;
+}
+
+//******************************************************************************
+int MAX30101::SpO2mode_init(uint8_t fifo_waterlevel_mark, uint8_t sample_avg,
+                            uint8_t sample_rate, uint8_t pulse_width,
+                            uint8_t red_led_current, uint8_t ir_led_current) {
+
+  char status;
+
+  max30101_mode_configuration.all = 0;
+  max30101_mode_configuration.bit.reset = 1;
+  if (i2c_reg_write(REG_MODE_CFG, max30101_mode_configuration.all) != 0) // Reset the device, Mode = don't use...
+  {
+    return -1;
+  }
+
+  /* Give it some settle time (100ms) */
+  wait(1.0 / 10.0); // Let things settle down a bit
+
+  max30101_fifo_configuration.all = 0;
+  max30101_fifo_configuration.bit.smp_ave = sample_avg; // Sample averaging;
+  max30101_fifo_configuration.bit.fifo_roll_over_en = 1; // FIFO Roll over enabled
+  max30101_fifo_configuration.bit.fifo_a_full = fifo_waterlevel_mark; // Interrupt when certain level is filled
+  if (i2c_reg_write(REG_FIFO_CFG, max30101_fifo_configuration.all) != 0) {
+    return -1;
+  }
+
+  max30101_spo2_configuration.bit.spo2_adc_rge = 0x2; // ADC Range 8192 fullscale
+  max30101_spo2_configuration.bit.spo2_sr = sample_rate; // 100 Samp/sec.
+  max30101_spo2_configuration.bit.led_pw = pulse_width; // Pulse Width=411us and ADC Resolution=18
+  if (i2c_reg_write(REG_SPO2_CFG, max30101_spo2_configuration.all) != 0) {
+    return -1;
+  }
+
+  max30101_led1_pa = red_led_current; // RED LED current
+  if (i2c_reg_write(REG_LED1_PA, max30101_led1_pa) != 0) {
+    return -1;
+  }
+
+  max30101_led2_pa = ir_led_current; // IR LED current
+  if (i2c_reg_write(REG_LED2_PA, max30101_led2_pa) != 0) {
+    return -1;
+  }
+
+  /************/
+
+  if (i2c_reg_read(REG_INT_STAT_1, &status) != 0) //  Clear INT1 by reading the status
+  {
+    return -1;
+  }
+
+  if (i2c_reg_read(REG_INT_STAT_2, &status) != 0) //  Clear INT2 by reading the status
+  {
+    return -1;
+  }
+
+  if (i2c_reg_write(REG_FIFO_W_PTR, 0x00) != 0) //  Clear FIFO ptr
+  {
+    return -1;
+  }
+
+  if (i2c_reg_write(REG_FIFO_OVF_CNT, 0x00) != 0) //  Clear FIFO ptr
+  {
+    return -1;
+  }
+
+  if (i2c_reg_write(REG_FIFO_R_PTR, 0x00) != 0) //  Clear FIFO ptr
+  {
+    return -1;
+  }
+
+  max30101_Interrupt_Enable_1.all = 0;
+  max30101_Interrupt_Enable_1.bit.a_full_en = 1; //  Enable FIFO almost full interrupt
+  if (i2c_reg_write(REG_INT_EN_1, max30101_Interrupt_Enable_1.all) != 0) {
+    return -1;
+  }
+
+  max30101_mode_configuration.all = 0;
+  max30101_mode_configuration.bit.mode = 0x03; // SpO2 mode
+  if (i2c_reg_write(REG_MODE_CFG, max30101_mode_configuration.all) != 0) {
+    return -1;
+  }
+
+  return 0;
+}
+
+//******************************************************************************
+int MAX30101::SpO2mode_stop(void) {
+
+  max30101_Interrupt_Enable_1.all = 0;
+  max30101_Interrupt_Enable_1.bit.a_full_en = 0; //  Disable FIFO almost full interrupt
+  if (i2c_reg_write(REG_INT_EN_1, max30101_Interrupt_Enable_1.all) != 0) {
+    return -1;
+  }
+
+  max30101_mode_configuration.all = 0;
+  max30101_mode_configuration.bit.mode = 0x00; // SpO2 mode off
+  if (i2c_reg_write(REG_MODE_CFG, max30101_mode_configuration.all) != 0) {
+    return -1;
+  }
+
+  max30101_led1_pa = 0; // RED LED current, 0.0
+  if (i2c_reg_write(REG_LED1_PA, max30101_led1_pa) != 0) {
+    return -1;
+  }
+
+  max30101_led2_pa = 0; // IR LED current, 0.0
+  if (i2c_reg_write(REG_LED2_PA, max30101_led2_pa) != 0) {
+    return -1;
+  }
+
+  return 0;
+}
+
+//******************************************************************************
+int MAX30101::HRmode_init(uint8_t fifo_waterlevel_mark, uint8_t sample_avg,
+                          uint8_t sample_rate, uint8_t pulse_width,
+                          uint8_t red_led_current) {
+
+  /*uint8_t*/ char status;
+
+  max30101_mode_configuration.all = 0;
+  max30101_mode_configuration.bit.reset = 1;
+  if (i2c_reg_write(REG_MODE_CFG, max30101_mode_configuration.all) != 0) // Reset the device, Mode = don't use...
+  {
+    return -1;
+  }
+
+  /* Give it some settle time (100ms) */
+  wait(1.0 / 10.0); // Let things settle down a bit
+
+  max30101_fifo_configuration.all = 0;
+  max30101_fifo_configuration.bit.smp_ave = sample_avg; // Sample averaging;
+  max30101_fifo_configuration.bit.fifo_roll_over_en = 1; // FIFO Roll over enabled
+  max30101_fifo_configuration.bit.fifo_a_full = fifo_waterlevel_mark; // Interrupt when certain level is filled
+  if (i2c_reg_write(REG_FIFO_CFG, max30101_fifo_configuration.all) != 0) {
+    return -1;
+  }
+
+  max30101_spo2_configuration.bit.spo2_adc_rge = 0x2; // ADC Range 8192 fullscale
+  max30101_spo2_configuration.bit.spo2_sr = sample_rate; // 100 Samp/sec.
+  max30101_spo2_configuration.bit.led_pw = pulse_width; // Pulse Width=411us and ADC Resolution=18
+  if (i2c_reg_write(REG_SPO2_CFG, max30101_spo2_configuration.all) != 0) {
+    return -1;
+  }
+
+  max30101_led1_pa = red_led_current; // RED LED current, 0.0
+  if (i2c_reg_write(REG_LED1_PA, max30101_led1_pa) != 0) {
+    return -1;
+  }
+
+  /************/
+
+  if (i2c_reg_read(REG_INT_STAT_1, &status) != 0) //  Clear INT1 by reading the status
+  {
+    return -1;
+  }
+
+  if (i2c_reg_read(REG_INT_STAT_2, &status) != 0) //  Clear INT2 by reading the status
+  {
+    return -1;
+  }
+
+  if (i2c_reg_write(REG_FIFO_W_PTR, 0x00) != 0) //  Clear FIFO ptr
+  {
+    return -1;
+  }
+
+  if (i2c_reg_write(REG_FIFO_OVF_CNT, 0x00) != 0) //  Clear FIFO ptr
+  {
+    return -1;
+  }
+
+  if (i2c_reg_write(REG_FIFO_R_PTR, 0x00) != 0) //  Clear FIFO ptr
+  {
+    return -1;
+  }
+
+  max30101_Interrupt_Enable_1.all = 0;
+  max30101_Interrupt_Enable_1.bit.a_full_en = 1;
+  // max30101_Interrupt_Enable_1.bit.prox_int_en=0;   //  Enable Proximity
+  // Interrupt
+  if (i2c_reg_write(REG_INT_EN_1, max30101_Interrupt_Enable_1.all) != 0) {
+    return -1;
+  }
+
+  max30101_mode_configuration.all = 0;
+  max30101_mode_configuration.bit.mode = 0x02; // HR mode
+  if (i2c_reg_write(REG_MODE_CFG, max30101_mode_configuration.all) != 0) {
+    return -1;
+  }
+
+  return 0;
+}
+
+//******************************************************************************
+int MAX30101::HRmode_stop(void) {
+
+  max30101_Interrupt_Enable_1.all = 0;
+  max30101_Interrupt_Enable_1.bit.a_full_en = 0; //  Disable FIFO almost full interrupt
+  if (i2c_reg_write(REG_INT_EN_1, max30101_Interrupt_Enable_1.all) != 0) {
+    return -1;
+  }
+
+  max30101_mode_configuration.all = 0;
+  max30101_mode_configuration.bit.mode = 0x00; // HR mode off
+  if (i2c_reg_write(REG_MODE_CFG, max30101_mode_configuration.all) != 0) {
+    return -1;
+  }
+
+  max30101_led1_pa = 0; // RED LED current, 0.0
+  if (i2c_reg_write(REG_LED1_PA, max30101_led1_pa) != 0) {
+    return -1;
+  }
+
+  return 0;
+}
+
+//******************************************************************************
+int MAX30101::Multimode_init(uint8_t fifo_waterlevel_mark, uint8_t sample_avg,
+                             uint8_t sample_rate, uint8_t pulse_width,
+                             uint8_t red_led_current, uint8_t ir_led_current,
+                             uint8_t green_led_current, uint8_t slot_1,
+                             uint8_t slot_2, uint8_t slot_3, uint8_t slot_4) {
+  char status;
+  max30101_mode_configuration.all = 0;
+  max30101_mode_configuration.bit.reset = 1;
+  if (i2c_reg_write(REG_MODE_CFG, max30101_mode_configuration.all) != 0) // Reset the device, Mode = don't use...
+  {
+    return -1;
+  }
+
+  /* Give it some settle time (100ms) */ // Let things settle down a bit
+  wait(1.0 / 10.0);
+
+  max30101_fifo_configuration.all = 0;
+  max30101_fifo_configuration.bit.smp_ave = sample_avg; // Sample averaging;
+  max30101_fifo_configuration.bit.fifo_roll_over_en = 1; // FIFO Roll over enabled
+  max30101_fifo_configuration.bit.fifo_a_full =
+      fifo_waterlevel_mark; // Interrupt when certain level is filled
+  if (i2c_reg_write(REG_FIFO_CFG, max30101_fifo_configuration.all) != 0) {
+    return -1;
+  }
+
+  max30101_spo2_configuration.bit.spo2_adc_rge = 0x2; // ADC Range 8192 fullscale
+  max30101_spo2_configuration.bit.spo2_sr = sample_rate; // 100 Samp/sec.
+  max30101_spo2_configuration.bit.led_pw = pulse_width; // Pulse Width=411us and ADC Resolution=18
+  if (i2c_reg_write(REG_SPO2_CFG, max30101_spo2_configuration.all) != 0) {
+    return -1;
+  }
+
+  max30101_led1_pa = red_led_current; // RED LED current
+  if (i2c_reg_write(REG_LED1_PA, max30101_led1_pa) != 0) {
+    return -1;
+  }
+
+  max30101_led2_pa = ir_led_current; // IR LED current
+  if (i2c_reg_write(REG_LED2_PA, max30101_led2_pa) != 0) {
+    return -1;
+  }
+
+  max30101_led3_pa = green_led_current; // Green LED current
+  if (i2c_reg_write(REG_LED3_PA, max30101_led3_pa) != 0) {
+    return -1;
+  }
+
+  // 0x01=Red(LED1), 0x02=IR(LED2), 0x03=Green(LED3) : Use LEDn_PA to adjust the intensity
+  // 0x05=Red      , 0x06=IR      , 0x07=Green       : Use PILOT_PA to adjust the intensity DO NOT USE THIS ROW...
+
+  max30101_multiLED_mode_ctrl_1.bit.slot1 = slot_1;
+  max30101_multiLED_mode_ctrl_1.bit.slot2 = slot_2;
+  if (i2c_reg_write(REG_SLT2_SLT1, max30101_multiLED_mode_ctrl_1.all)) {
+    return -1;
+  }
+
+  max30101_multiLED_mode_ctrl_2.all = 0;
+  max30101_multiLED_mode_ctrl_2.bit.slot3 = slot_3;
+  max30101_multiLED_mode_ctrl_2.bit.slot4 = slot_4;
+  if (i2c_reg_write(REG_SLT4_SLT3, max30101_multiLED_mode_ctrl_2.all)) {
+    return -1;
+  }
+
+  /************/
+
+  if (i2c_reg_read(REG_INT_STAT_1, &status) != 0) //  Clear INT1 by reading the status
+  {
+    return -1;
+  }
+
+  if (i2c_reg_read(REG_INT_STAT_2, &status) != 0) //  Clear INT2 by reading the status
+  {
+    return -1;
+  }
+
+  if (i2c_reg_write(REG_FIFO_W_PTR, 0x00) != 0) //  Clear FIFO ptr
+  {
+    return -1;
+  }
+
+  if (i2c_reg_write(REG_FIFO_OVF_CNT, 0x00) != 0) //  Clear FIFO ptr
+  {
+    return -1;
+  }
+
+  if (i2c_reg_write(REG_FIFO_R_PTR, 0x00) != 0) //  Clear FIFO ptr
+  {
+    return -1;
+  }
+
+  max30101_Interrupt_Enable_1.all = 0;
+  max30101_Interrupt_Enable_1.bit.a_full_en = 1; //  Enable FIFO almost full interrupt
+  if (i2c_reg_write(REG_INT_EN_1, max30101_Interrupt_Enable_1.all) != 0) {
+    return -1;
+  }
+
+  max30101_mode_configuration.all = 0;
+  max30101_mode_configuration.bit.mode = 0x07; // Multi-LED mode
+  if (i2c_reg_write(REG_MODE_CFG, max30101_mode_configuration.all) != 0) {
+    return -1;
+  }
+
+  return 0;
+}
+
+//******************************************************************************
+int MAX30101::Multimode_stop(void) {
+
+  max30101_Interrupt_Enable_1.all = 0;
+  max30101_Interrupt_Enable_1.bit.a_full_en = 0; //  Disable FIFO almost full interrupt
+  if (i2c_reg_write(REG_INT_EN_1, max30101_Interrupt_Enable_1.all) != 0) {
+    return -1;
+  }
+
+  max30101_mode_configuration.all = 0;
+  max30101_mode_configuration.bit.mode = 0x00; // Multi-LED mode off
+  if (i2c_reg_write(REG_MODE_CFG, max30101_mode_configuration.all) != 0) {
+    return -1;
+  }
+
+  max30101_led1_pa = 0; // RED LED current, 0.0
+  if (i2c_reg_write(REG_LED1_PA, max30101_led1_pa) != 0) {
+    return -1;
+  }
+
+  max30101_led2_pa = 0; // IR LED current, 0.0
+  if (i2c_reg_write(REG_LED2_PA, max30101_led2_pa) != 0) {
+    return -1;
+  }
+
+  max30101_led3_pa = 0; // Green LED current, 0.0
+  if (i2c_reg_write(REG_LED3_PA, max30101_led3_pa) != 0) {
+    return -1;
+  }
+  return 0;
+}
+
+//******************************************************************************
+int MAX30101::tempread(void) {
+  max30101_Interrupt_Enable_2.all = 0;
+  max30101_Interrupt_Enable_2.bit.die_temp_rdy_en = 1; // Enable the Temp Rdy;
+  if (i2c_reg_write(REG_INT_EN_2, 0x02) != 0) // Interrupt Enable 2, Temperature Interrupt
+  {
+    return -1;
+  }
+
+  if (i2c_reg_write(REG_TEMP_EN, 0x01) != 0) // Die Temperature Config, Temp enable...
+  {
+    return -1;
+  }
+  return 0;
+}
+
+//******************************************************************************
+int MAX30101::i2c_reg_write(MAX30101_REG_map_t reg, char value) {
+  char cmdData[2] = {reg, value};
+
+  if (I2CM_Write(slaveAddress, NULL, 0, cmdData, 2) != 0 /*2*/) {
+    return -1;
+  }
+
+  return 0;
+}
+
+//******************************************************************************
+int MAX30101::i2c_reg_read(MAX30101_REG_map_t reg, char *value) {
+  if (I2CM_Read(slaveAddress, (char *)&reg, 1, value, 1) != 0 /*1*/) {
+    return -1;
+  }
+
+  return 0;
+}
+
+/**
+* @brief Read from an I2C device
+* @param slaveAddress slave address to use with transaction
+* @param writeData pointer of data to write
+* @param writeCount number of data to write
+* @param readData pointer to buffer to read to
+* @param readCount number of bytes to read
+*/
+int MAX30101::I2CM_Read(int slaveAddress, char *writeData, char writeCount,
+                        char *readData, char readCount) {
+  if (writeData != NULL && writeCount != 0) {
+    i2c->write(slaveAddress, writeData, writeCount, true);
+  }
+  if (readData != NULL && readCount != 0) {
+    i2c->read(slaveAddress, readData, readCount);
+  }
+  return 0;
+}
+
+/**
+* @brief Write to an I2C device
+* @param slaveAddress slave address to use with transaction
+* @param writeData pointer of data to write
+* @param writeCount1 number of data to write
+* @param writeData2 pointer to buffer to read to
+* @param writeCount2 number of bytes to read
+*/
+int MAX30101::I2CM_Write(int slaveAddress, char *writeData1, char writeCount1,
+                         char *writeData2, char writeCount2) {
+  if (writeData1 != NULL && writeCount1 != 0) {
+    i2c->write(slaveAddress, writeData1, writeCount1);
+  }
+  if (writeData2 != NULL && writeCount2 != 0) {
+    i2c->write(slaveAddress, writeData2, writeCount2);
+  }
+  return 0;
+}
+
+//******************************************************************************
+void MAX30101::onDataAvailable(DataCallbackFunction _onDataAvailable) {
+  onDataAvailableCallback = _onDataAvailable;
+}
+
+/**
+* @brief Used to notify an external function that interrupt data is available
+* @param id type of data available
+* @param buffer 32-bit buffer that points to the data
+* @param length length of 32-bit elements available
+*/
+void MAX30101::dataAvailable(uint32_t id, uint32_t *buffer, uint32_t length) {
+  if (onDataAvailableCallback != NULL) {
+    (*onDataAvailableCallback)(id, buffer, length);
+  }
+}
+
+//******************************************************************************
+void MAX30101::onInterrupt(InterruptFunction _onInterrupt) {
+  onInterruptCallback = _onInterrupt;
+}
+
+/**
+* @brief Executed on interrupt
+* @param id type of data available
+* @param buffer 32-bit buffer that points to the data
+* @param length length of 32-bit elements available
+*/
+void MAX30101::interruptPostCallback(void) {
+  if (onInterruptCallback != NULL) {
+    (*onInterruptCallback)();
+  }
+}
+
+int max30101_enableInterrupts = 0;
+/**************************************************************************************************************/
+void MAX30101MidIntHandler(void) { 
+  MAX30101::instance->int_handler(); 
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/e4a10ed6eb92/HSP/Devices/MAX30101/MAX30101/MAX30101.h	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,454 @@
+/*******************************************************************************
+/ * Copyright (C) 2015 Maxim Integrated Products, Inc., All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+ * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Except as contained in this notice, the name of Maxim Integrated
+ * Products, Inc. shall not be used except as stated in the Maxim Integrated
+ * Products, Inc. Branding Policy.
+ *
+ * The mere transfer of this software does not imply any licenses
+ * of trade secrets, proprietary technology, copyrights, patents,
+ * trademarks, maskwork rights, or any other form of intellectual
+ * property whatsoever. Maxim Integrated Products, Inc. retains all
+ * ownership rights.
+ *******************************************************************************/
+/*
+ * max30101.h
+ *
+ *  Created on: Aug 26, 2015
+ *      Author: faisal.tariq
+ */
+
+#ifndef _MAX30101_H_
+#define _MAX30101_H_
+
+#include "mbed.h"
+
+#define MAX30101_RAW_DATA_SIZE 3 * 4 * 32
+#define MAX30101_PROC_DATA_SIZE 4 * 32
+
+#define MAX30101_OXIMETER_DATA 0x10
+
+#define CHUNK_SIZE 252
+
+// MAX30101 Register addresses
+
+#define MAX30101_INT_PORT 4
+#define MAX30101_INT_PIN 0
+#define MAX30101_MASTER_NUM 2
+
+/**
+* Maxim Integrated MAX30101 Oximeter chip
+*/
+class MAX30101 {
+public:
+  float max30101_final_temp;                         // Global declaration
+  uint32_t max30101_buffer[MAX30101_PROC_DATA_SIZE]; // final Processed data
+  char max30101_rawData[MAX30101_RAW_DATA_SIZE];     //  raw data from the chip
+
+  typedef enum { // MAX30101 Register addresses
+
+    /*Status */
+    REG_INT_STAT_1 = 0x00,
+    REG_INT_STAT_2 = 0x01,
+    REG_INT_EN_1   = 0x02,
+    REG_INT_EN_2   = 0x03,
+
+    REG_FIFO_W_PTR   = 0x04,
+    REG_FIFO_OVF_CNT = 0x05,
+    REG_FIFO_R_PTR   = 0x06,
+    REG_FIFO_DATA    = 0x07,
+    /* Configuration */
+    REG_FIFO_CFG  = 0x08,
+    REG_MODE_CFG  = 0x09,
+    REG_SPO2_CFG  = 0x0A,
+    REG_LED1_PA   = 0x0C,
+    REG_LED2_PA   = 0x0D,
+    REG_LED3_PA   = 0x0E,
+    REG_PILOT_PA  = 0x10,
+    REG_SLT2_SLT1 = 0x11,
+    REG_SLT4_SLT3 = 0x12,
+    /* Die Temp    */
+    REG_TINT    = 0x1F,
+    REG_TFRAC   = 0x20,
+    REG_TEMP_EN = 0x21,
+    /* Proximity Func */
+    REG_PROX_INT_THR = 0x30,
+    /* Part ID        */
+    REG_REV_ID = 0xFE,
+    REG_ID     = 0xFF,
+  } MAX30101_REG_map_t;
+
+  /**********/
+  /* STATUS */
+  /**********/
+  /// @brief STATUS1 (0x00)
+  union max30101_Interrupt_Status_1_reg {
+    char all;
+    struct {
+      char pwr_rdy  : 1;
+      char reserved : 3;
+      char prox_int : 1;
+      char alc_ovf  : 1;
+      char ppg_rdy  : 1;
+      char a_full   : 1;
+    } bit;
+  } max30101_Interrupt_Status_1;
+
+  /// @brief STATUS2 (0x01)
+  union max30101_Interrupt_Status_2_reg {
+    char all;
+    struct {
+      char reserved1    : 1;
+      char die_temp_rdy : 1;
+      char reserved2    : 6;
+    } bit;
+  } max30101_Interrupt_Status_2;
+
+  /// @brief INTERRUPT_ENABLE1 (0x02)
+  volatile union max30101_Interrupt_Enable_1_reg {
+    uint8_t all;
+    struct {
+      uint8_t reserved1   : 4;
+      uint8_t prox_int_en : 1;
+      uint8_t alc_ovf_en  : 1;
+      uint8_t ppg_rdy_en  : 1;
+      uint8_t a_full_en   : 1;
+    } bit;
+  } max30101_Interrupt_Enable_1;
+
+  /// @brief INTERRUPT_ENABLE2 (0x03)
+  volatile union max30101_Interrupt_Enable_2_reg {
+    uint8_t all;
+    struct {
+      uint8_t reserved1       : 1;
+      uint8_t die_temp_rdy_en : 1;
+      uint8_t reserved2       : 6;
+    } bit;
+  } max30101_Interrupt_Enable_2;
+
+  /*********/
+  /* FIFO  */
+  /*********/
+  // 0x04
+  /// @brief FIFO_WR_PTR (0x04)
+  volatile union max30101_fifo_wr_ptr_reg {
+    uint8_t all;
+    struct {
+      uint8_t fifo_wr_ptr : 5;
+      uint8_t reserved1   : 3;
+    } bit;
+  } max30101_fifo_wr_ptr;
+
+  /// @brief OVF_COUNTER (0x05)
+  volatile union max30101_ovf_counter_reg {
+    uint8_t all;
+    struct {
+      uint8_t fifo_ovf_counter : 5;
+      uint8_t reserved1        : 3;
+    } bit;
+  } max30101_ovf_counter_reg;
+
+  /// @brief FIFO_READ_PTR (0x06)
+  volatile union max30101_fifo_rd_ptr_reg {
+    uint8_t all;
+    struct {
+      uint8_t fifo_rd_ptr : 5;
+      uint8_t reserved1   : 3;
+    } bit;
+  } max30101_fifo_rd_ptr;
+
+  // 0x07
+  uint8_t max30101_fifo_data;
+
+  /********************/
+  /* Configuration    */
+  /********************/
+  // 0x08
+  /// @brief FIFO_CONFIGURATION (0x08)
+  volatile union max30101_fifo_configuration_reg {
+    uint8_t all;
+    struct {
+      uint8_t fifo_a_full       : 4;
+      uint8_t fifo_roll_over_en : 1;
+      uint8_t smp_ave           : 3;
+    } bit;
+  } max30101_fifo_configuration;
+
+  /// @brief MODE_CONFIGURATION (0x09)
+  volatile union max30101_mode_configuration_reg {
+    uint8_t all;
+    struct {
+      uint8_t mode      : 3;
+      uint8_t reserved1 : 3;
+      uint8_t reset     : 1;
+      uint8_t shdn      : 1;
+    } bit;
+  } max30101_mode_configuration;
+
+  /// @brief SPO2_CONGIGURATION (0x0A)
+  volatile union max30101_spo2_configuration_reg {
+    uint8_t all;
+    struct {
+      uint8_t led_pw       : 2;
+      uint8_t spo2_sr      : 3;
+      uint8_t spo2_adc_rge : 2;
+      uint8_t reserved1    : 1;
+    } bit;
+  } max30101_spo2_configuration;
+
+  /// @brief LED1_PA (0x0C)
+  uint8_t max30101_led1_pa;
+
+  /// @brief LED2_PA (0x0D)
+  uint8_t max30101_led2_pa;
+
+  /// @brief LED3_PA (0x0E)
+  uint8_t max30101_led3_pa;
+
+  /// @brief PILOT_PA (0x10)
+  uint8_t max30101_pilot_pa;
+
+  volatile union max30101_multiLED_mode_ctrl_1_reg {
+    uint8_t all;
+    struct {
+      uint8_t slot1     : 3;
+      uint8_t reserved  : 1;
+      uint8_t slot2     : 3;
+      uint8_t reserved1 : 1;
+    } bit;
+  } max30101_multiLED_mode_ctrl_1;
+
+  volatile union max30101_multiLED_mode_ctrl_2_reg {
+    uint8_t all;
+    struct {
+      uint8_t slot3     : 3;
+      uint8_t reserved  : 1;
+      uint8_t slot4     : 3;
+      uint8_t reserved1 : 1;
+    } bit;
+  } max30101_multiLED_mode_ctrl_2;
+
+  /********************/
+  /* Die Temperature  */
+  /********************/
+
+  uint8_t max30101_tinit;
+
+  uint8_t max30101_tfrac;
+
+  volatile union max30101_die_temp_config {
+    uint8_t all;
+    struct {
+      uint8_t temp_en  : 1;
+      uint8_t reserved : 7;
+    } bit;
+  } max30101_die_temp_config;
+  /*******************************/
+  /***** Function Prototypes *****/
+  /*******************************/
+
+  uint8_t max30101_prox_int_thresh;
+
+  /**
+  * MAX30101 constructor.
+  *
+  * @param sda mbed pin to use for SDA line of I2C interface.
+  * @param scl mbed pin to use for SCL line of I2C interface.
+  */
+  MAX30101(PinName sda, PinName scl, int slaveAddress);
+
+  /**
+  *  MAX30101 constructor.
+  *
+  * @param i2c I2C object to use.
+  */
+  MAX30101(I2C *i2c, int slaveAddress);
+
+  /**
+  * MAX30101 destructor.
+  */
+  ~MAX30101(void);
+
+  /**
+       * @brief Allows reading from MAX30101 register
+   * @param reg: is the register address, to read from (look at max30101.h and the
+   *             data sheet for details)
+   * @param value: is the pointer to the value read from the register
+   * @returns  0-if no error.  A non-zero value indicates an error.
+   */
+  int i2c_reg_read(MAX30101_REG_map_t reg, char *value);
+
+  /**
+   * @brief Allows writing to MAX30101 register
+   * @param reg: is the register address, to read from (look at max30101.h and
+   * the
+   *        data sheet for details)
+   * @param value: is the value to write to the register
+   * @returns  0-if if no error.  A non-zero value indicates an error.
+   */
+  int i2c_reg_write(MAX30101_REG_map_t reg, char value);
+
+  /**
+   * @brief This function sets up for the SpO2 mode.  The data is returned in
+   * the callback function
+   * @brief max30101_int_handler in global array: buffer[].  SP mode handles two LED (Red,IR) data.  Hence it
+   * @brief can fill up the FIFO up to a maximum of 3bytes/sample x 32 x 2 = 192bytes.
+   * @param fifo_waterlevel_mark: corresponds to FIFO_A_FULL, In FIFO Configuration Register (0x08)
+   * @param sample_avg: corresponds to SMP_AVE, in FIFO Configuration Register (0x08)
+   * @param sample_rate: corresponds to SPO2_SR, IN SpO2 Configuration Register (0x0A)
+   * @param pulse_width: corresponds to LED_PW in SpO2 Configuration register(0x0A)
+   * @param red_led_current: corresponds to LED1_PA register (0x0C).  Please see data sheet for values
+   * @param ir_led_current: corresponds to LED2_PA register (0x0D).  Please see data sheet for values
+   * @returns 0-if everything is good.  A non-zero value indicates an error.
+   */
+  int SpO2mode_init(uint8_t fifo_waterlevel_mark, uint8_t sample_avg,
+                    uint8_t sample_rate, uint8_t pulse_width,
+                    uint8_t red_led_current, uint8_t ir_led_current);
+
+  /**
+   * @brief This function will stop the SpO2 mode and turn off all operating LEDâs.
+   * @return  0-if if no error.  A non-zero value indicates an error.
+   */
+  int SpO2mode_stop(void);
+
+  /**
+   * @brief This function sets up for the HR mode.  The data is returned in thecallback function
+   * @brief max30101_int_handler in global array: buffer[].HR mode handles one LED (Red) data.  Hence it can fill
+   * @brief up the FIFO up to a maximum of 3bytes/sample x 32 = 96bytes.
+   * @brief fifo_waterlevel_mark: corresponds to FIFO_A_FULL, In FIFO Configuration Register (0x08)
+   * @param sample_avg: corresponds to SMP_AVE, in FIFO Configuration Register (0x08)
+   * @param sample_rate:corresponds to SPO2_SR, IN SpO2 Configuration Register (0x0A)
+   * @param pulse_width: corresponds to LED_PW in SpO2 Configuration Register(0x0A)
+   * @param red_led_current: corresponds to LED1_PA register (0x0C).  Please see data sheet for values
+   * @returns  0-if if no error.  A non-zero value indicates an error.
+   */
+  int HRmode_init(uint8_t fifo_waterlevel_mark, uint8_t sample_avg,
+                  uint8_t sample_rate, uint8_t pulse_width,
+                  uint8_t red_led_current);
+
+  /**
+   * @brief This function will stop the HR mode and turn off all operating
+   * LED’s.
+   * @return  0-if if no error.  A non-zero value indicates an error.
+   */
+  int HRmode_stop(void);
+
+  /**
+   *@brief This function sets up for the Multi-mode.  The data is returned in the callback function max30101_int_handler in global array:
+   *@brief buffer[].  Multi-LED mode can handle 1 to 4 LED combinations.  Hence it can fill up the FIFO up to a maximum of
+   *@brief 3bytes/sample x 32 x 4 = 384bytes.
+   *@param fifo_waterlevel_mark: corresponds to FIFO_A_FULL, In FIFO Configuration Register (0x08)
+   *@param sample_avg: corresponds to SMP_AVE, in FIFO Configuration Register (0x08)
+   *@param sample_rate:corresponds to SPO2_SR, IN SpO2 Configuration Register (0x0A)
+   *@param pulse_width: corresponds to LED_PW in SpO2 Configuration register(0x0A)
+   *@param red_led_current: corresponds to LED1_PA register (0x0C).  Please see data sheet for values
+   *@param ir_led_current: corresponds to LED2_PA register (0x0D).  Please see data sheet for values
+   *@param green_led_current: corresponds to LED3_PA register (0x0E).  Please see data sheet for values
+   *@param slot_1,…,slot_4: corresponds to Multi-LED Mode control Registers (0x11-0x12).
+   *@returns  0-if if no error.  A non-zero value indicates an error.
+   */
+  int Multimode_init(uint8_t fifo_waterlevel_mark, uint8_t sample_avg,
+                     uint8_t sample_rate, uint8_t pulse_width,
+                     uint8_t red_led_current, uint8_t ir_led_current,
+                     uint8_t green_led_current, uint8_t slot_1, uint8_t slot_2,
+                     uint8_t slot_3, uint8_t slot_4);
+
+  /**
+   * @brief This function will stop the Multi-mode and turn off all operating LED’s.
+   * @returns  0-if if no error.  A non-zero value indicates an error.
+   */
+  int Multimode_stop(void);
+
+  /**
+   * @brief This is a function that sets up for temperature read and should be called after one of the mode
+   * @brief has been setup.  The data is returned in the callback function max30101_int_handler.  This
+   * @brief function needs to be called every time temperature reading is required.
+   * @brief Call the temp function after one of the MODES have been started
+   * @brief Note that the temp is disabled after one read... also, it is not necessary
+   * @brief to read the temp frequently...
+   * @returns  0-if if no error.  A non-zero value indicates an error.
+   */
+  int tempread(void);
+
+  /**
+   *@brief This is a callback function which collects the data from the FIFO of the MAX30101 in a 32-bit
+   *@brief unsigned global array called max30101_buffer[].  Upon every interrupt from the MAX30101, this
+   *@brief function is called to service the FIFO of the MAX30101.  This callback function also services the
+   *@brief interrupt for the temp data.  The temp data is collected in a floating point global variable
+   *@brief final_temp.
+   *@param max30101_buffer[], global uint32_t
+   *@returns  0-if everything is good.  A non-zero value indicates an error.
+   */
+  int int_handler(void);
+  /**
+  * @brief type definition for data interrupt
+  */
+  typedef void (*DataCallbackFunction)(uint32_t id, uint32_t *buffer,
+                                       uint32_t length);
+  /**
+  * @brief type definition for general interrupt
+  */
+  typedef void (*InterruptFunction)();
+
+  /**
+  * @brief Used to connect a callback for when interrupt data is available
+  */
+  void onInterrupt(InterruptFunction _onInterrupt);
+
+  /**
+  * @brief Used to connect a callback for when interrupt data is available
+  */
+  void onDataAvailable(DataCallbackFunction _onDataAvailable);
+
+  static MAX30101 *instance;
+
+private:
+  /// called when interrupt data is available
+  void dataAvailable(uint32_t id, uint32_t *buffer, uint32_t length);
+  /// callback function at the end of the interrupt
+  void interruptPostCallback(void);
+  /// callback function when interrupt data is available
+  DataCallbackFunction onDataAvailableCallback;
+  /// callback function when interrupt data is available
+  InterruptFunction onInterruptCallback;
+  /// Read I2c wrapper method
+  int I2CM_Read(int slaveAddress, char *writeData, char writeCount, char *readData, char readCount);
+  /// Write I2c wrapper method
+  int I2CM_Write(int slaveAddress, char *writeData1, char writeCount1, char *writeData2, char writeCount2);
+  /// pointer to I2C object
+  I2C *i2c;
+  /// flag to track if this object is the owner (created) the I2C object
+  bool i2c_owner;
+  /// Device slave address
+  int slaveAddress;
+};
+
+/**
+*  @brief Resets the I2C block, when needed
+*/
+extern void I2CM_Init_Reset(uint8_t index, int speed);
+
+ /**
+  * @brief Used for debugging, if needed
+  */
+void MAX30101MidIntHandler(void);
+
+#endif /* _MAX30101_H_ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/e4a10ed6eb92/HSP/Devices/MAX30101/MAX30101_RPC.cpp	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,272 @@
+/*******************************************************************************
+ * Copyright (C) 2016 Maxim Integrated Products, Inc., All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+ * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Except as contained in this notice, the name of Maxim Integrated
+ * Products, Inc. shall not be used except as stated in the Maxim Integrated
+ * Products, Inc. Branding Policy.
+ *
+ * The mere transfer of this software does not imply any licenses
+ * of trade secrets, proprietary technology, copyrights, patents,
+ * trademarks, maskwork rights, or any other form of intellectual
+ * property whatsoever. Maxim Integrated Products, Inc. retains all
+ * ownership rights.
+ *******************************************************************************
+ */
+#include "MAX30101_RPC.h"
+#include "StringHelper.h"
+#include "MAX30101.h"
+#include "Streaming.h"
+#include "RpcFifo.h"
+#include "RpcServer.h"
+#include "StringInOut.h"
+#include "MAX30101_helper.h"
+#include "LIS2DH.h"
+#include "Peripherals.h"
+#include "DataLoggingService.h"
+
+//******************************************************************************
+int MAX30101_WriteReg(char argStrs[32][32], char replyStrs[32][32]) {
+	uint8_t args[2];
+	uint8_t reply[1];
+	ProcessArgs(argStrs, args, sizeof(args));
+//	Peripherals::max30101()->writeReg(args[0] , args[1]);	// pass in the register address and the data
+	reply[0] = 0x80;
+	FormatReply(reply, sizeof(reply), replyStrs);
+	return 0;
+}
+
+//******************************************************************************
+int MAX30101_ReadReg(char argStrs[32][32], char replyStrs[32][32]) {
+	uint8_t args[1];
+	uint8_t reply[1];
+	char value;
+	ProcessArgs(argStrs, args, sizeof(args));
+//	Peripherals::max30101()->readReg(args[0] , &value, 1);
+	reply[0] = (uint8_t)value;
+	FormatReply(reply, sizeof(reply), replyStrs);
+	return 0;
+}
+
+//******************************************************************************
+int MAX30101_COMMinit(char argStrs[32][32], char replyStrs[32][32])
+{
+	uint8_t args[4];
+	uint8_t return_value;
+	ProcessArgs(argStrs,args,sizeof(args));
+
+	//return_value = max30101_COMMinit(args[0], args[1], args[2], args[3]);
+
+	strcpy(replyStrs[0],"80");
+	return return_value;
+}
+
+//******************************************************************************
+int MAX30101_SpO2mode_stop(char argStrs[32][32], char replyStrs[32][32])
+{
+	uint8_t args[4];
+	uint8_t return_value;
+	ProcessArgs(argStrs,args,sizeof(args));
+
+	//lis2dh_Stop();
+	//max30101_SpO2mode_stop();
+	Peripherals::max30101()->SpO2mode_stop();
+
+	strcpy(replyStrs[0],"80");
+	return return_value;
+}
+
+//******************************************************************************
+int MAX30101_HRmode_stop(char argStrs[32][32], char replyStrs[32][32])
+{
+	uint8_t args[4];
+	ProcessArgs(argStrs,args,sizeof(args));
+
+	//lis2dh_Stop();
+	Peripherals::max30101()->HRmode_stop();
+
+	strcpy(replyStrs[0],"80");
+	return 0;
+}
+
+//******************************************************************************
+int MAX30101_Multimode_stop(char argStrs[32][32], char replyStrs[32][32])
+{
+	uint8_t args[4];
+	ProcessArgs(argStrs,args,sizeof(args));
+
+	//lis2dh_Stop();
+	Peripherals::max30101()->Multimode_stop();
+
+	strcpy(replyStrs[0],"80");
+	return 0;
+}
+
+//******************************************************************************
+void ClearInOutFifos() {
+	fifo_clear(GetStreamOutFifo());		// clear stream out fifo
+	fifo_clear(GetUSBIncomingFifo());				// clear USB serial incoming fifo
+}
+
+int highDataRate = 0;
+#define MAX30101_200HZ	2
+#define MAX30101_400HZ	3
+
+/**
+* Adjust the threshold of the Accel based on the data rate
+* @lis2dhDataRate Data rate of the accel to determine what would be a good threshold value
+*/
+static int adjustAccelThreshold(int lis2dhDataRate) {
+	int lis2dhFifoThreshold;
+	lis2dhFifoThreshold = 31;
+	if (lis2dhDataRate <= LIS2DH_DATARATE_50HZ) lis2dhFifoThreshold = 4; 
+	if (lis2dhDataRate == LIS2DH_DATARATE_100HZ) lis2dhFifoThreshold = 8; 
+	return lis2dhFifoThreshold;
+}
+
+/**
+* Evaluate the data rate of the Accel to see if we should stream using a high data rate mode
+* @lis2dhDataRate Data rate of the accel to determine if this is a high data rate
+*/
+static void adjustHighDataRate(int lis2dhDataRate) {
+	highDataRate = 0;
+	if (lis2dhDataRate >= LIS2DH_DATARATE_200HZ) highDataRate = 1;
+}
+
+//******************************************************************************
+int MAX30101_SpO2mode_init(char argStrs[32][32], char replyStrs[32][32])
+{
+	uint8_t args[7];
+	uint8_t lis2dhDataRate;
+	uint8_t lis2dhFifoThreshold;
+	ProcessArgs(argStrs, args, sizeof(args));
+
+	ClearInOutFifos();
+	MAX30101_Helper_SetStreamingFlag(eStreaming_SPO2,1);
+	Peripherals::max30101()->SpO2mode_init(args[0], args[1], args[2], args[3], args[4], args[5]);
+
+	lis2dhDataRate = args[6];
+	lis2dhFifoThreshold = adjustAccelThreshold(lis2dhDataRate);
+	adjustHighDataRate(lis2dhDataRate);
+
+	Peripherals::lis2dh()->initStart(lis2dhDataRate,lis2dhFifoThreshold);
+	LoggingService_StartLoggingUsb();
+
+	strcpy(replyStrs[0],"80");
+	return 0;
+}
+
+//******************************************************************************
+int MAX30101_SpO2mode_InitStart(char argStrs[32][32], char replyStrs[32][32])
+{
+	uint8_t args[6];   // Size
+	ProcessArgs(argStrs, args, sizeof(args));
+
+	ClearInOutFifos();
+	MAX30101_Helper_SetStreamingFlag(eStreaming_SPO2,1);
+	if (args[2] >= MAX30101_200HZ) highDataRate = 1;
+	Peripherals::max30101()->SpO2mode_init(args[0], args[1], args[2], args[3], args[4], args[5]);
+
+	strcpy(replyStrs[0],"80");
+	return 0;
+}
+
+//******************************************************************************
+int MAX30101_HRmode_init(char argStrs[32][32], char replyStrs[32][32])
+{
+	uint8_t args[6];
+	uint8_t lis2dhDataRate;
+	uint8_t lis2dhFifoThreshold;
+	ProcessArgs(argStrs, args, sizeof(args));
+
+	ClearInOutFifos();
+	MAX30101_Helper_SetStreamingFlag(eStreaming_HR,1);
+	Peripherals::max30101()->HRmode_init(args[0], args[1], args[2], args[3], args[4]);
+
+	lis2dhDataRate = args[5];
+	lis2dhFifoThreshold = adjustAccelThreshold(lis2dhDataRate);
+	adjustHighDataRate(lis2dhDataRate);
+	
+	Peripherals::lis2dh()->initStart(lis2dhDataRate,lis2dhFifoThreshold);
+	LoggingService_StartLoggingUsb();
+	strcpy(replyStrs[0],"80");
+	return 0;
+}
+
+//******************************************************************************
+int MAX30101_HRmode_InitStart(char argStrs[32][32], char replyStrs[32][32])
+{
+	uint8_t args[5];
+	ProcessArgs(argStrs, args, sizeof(args));
+
+	ClearInOutFifos();
+	MAX30101_Helper_SetStreamingFlag(eStreaming_HR,1);
+	if (args[2] >= MAX30101_200HZ) highDataRate = 1;
+	Peripherals::max30101()->HRmode_init(args[0], args[1], args[2], args[3], args[4]);
+	strcpy(replyStrs[0],"80");
+	return 0;
+}
+
+//******************************************************************************
+int MAX30101_Multimode_init(char argStrs[32][32], char replyStrs[32][32])
+{
+	uint8_t args[12];
+	uint8_t lis2dhDataRate;
+	uint8_t lis2dhFifoThreshold;
+	ProcessArgs(argStrs, args, sizeof(args));
+
+	ClearInOutFifos();
+
+	lis2dhDataRate = args[11];
+	lis2dhFifoThreshold = adjustAccelThreshold(lis2dhDataRate);
+	adjustHighDataRate(lis2dhDataRate);
+	
+	Peripherals::lis2dh()->initStart(lis2dhDataRate,lis2dhFifoThreshold);
+
+	wait(0.1f);
+	MAX30101_Helper_SetStreamingFlag(eStreaming_MULTI, 1);
+	Peripherals::max30101()->Multimode_init(args[0], args[1], args[2],
+											args[3], args[4], args[5], args[6],
+											args[7], args[8], args[9], args[10]);
+	LoggingService_StartLoggingUsb();
+
+	strcpy(replyStrs[0],"80");
+	return 0;
+}
+
+//******************************************************************************
+int MAX30101_Multimode_InitStart(char argStrs[32][32], char replyStrs[32][32])
+{
+	uint8_t args[11];
+	ProcessArgs(argStrs, args, sizeof(args));
+
+	ClearInOutFifos();
+	MAX30101_Helper_SetStreamingFlag(eStreaming_MULTI, 1);
+	if (args[2] >= MAX30101_200HZ) highDataRate = 1;
+	Peripherals::max30101()->Multimode_init(args[0], args[1], args[2],
+											args[3], args[4], args[5], args[6],
+											args[7], args[8], args[9], args[10]);
+
+	strcpy(replyStrs[0],"80");
+	return 0;
+}
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/e4a10ed6eb92/HSP/Devices/MAX30101/MAX30101_RPC.h	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,51 @@
+/*******************************************************************************
+ * Copyright (C) 2016 Maxim Integrated Products, Inc., All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+ * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Except as contained in this notice, the name of Maxim Integrated
+ * Products, Inc. shall not be used except as stated in the Maxim Integrated
+ * Products, Inc. Branding Policy.
+ *
+ * The mere transfer of this software does not imply any licenses
+ * of trade secrets, proprietary technology, copyrights, patents,
+ * trademarks, maskwork rights, or any other form of intellectual
+ * property whatsoever. Maxim Integrated Products, Inc. retains all
+ * ownership rights.
+ *******************************************************************************
+ */
+#ifndef _MAX30101_RPC_H_
+#define _MAX30101_RPC_H_
+
+int MAX30101_WriteReg(char argStrs[32][32], char replyStrs[32][32]);
+int MAX30101_ReadReg(char argStrs[32][32], char replyStrs[32][32]);
+int MAX30101_StreamTest(char argStrs[32][32], char replyStrs[32][32]);
+int MAX30101_COMMinit(char argStrs[32][32], char replyStrs[32][32]);
+int MAX30101_SpO2mode_init(char argStrs[32][32], char replyStrs[32][32]);
+int MAX30101_SpO2mode_InitStart(char argStrs[32][32], char replyStrs[32][32]);
+int MAX30101_HRmode_init(char argStrs[32][32], char replyStrs[32][32]);
+int MAX30101_HRmode_InitStart(char argStrs[32][32], char replyStrs[32][32]);
+int MAX30101_Multimode_init(char argStrs[32][32], char replyStrs[32][32]);
+int MAX30101_Multimode_InitStart(char argStrs[32][32], char replyStrs[32][32]);
+
+int MAX30101_SpO2mode_stop(char argStrs[32][32], char replyStrs[32][32]);
+int MAX30101_HRmode_stop(char argStrs[32][32], char replyStrs[32][32]);
+int MAX30101_Multimode_stop(char argStrs[32][32], char replyStrs[32][32]);
+
+#endif /* _MAX30101_RPC_H_ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/e4a10ed6eb92/HSP/Devices/MAX30101/MAX30101_helper.cpp	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,74 @@
+
+/*******************************************************************************
+ * Copyright (C) 2016 Maxim Integrated Products, Inc., All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+ * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Except as contained in this notice, the name of Maxim Integrated
+ * Products, Inc. shall not be used except as stated in the Maxim Integrated
+ * Products, Inc. Branding Policy.
+ *
+ * The mere transfer of this software does not imply any licenses
+ * of trade secrets, proprietary technology, copyrights, patents,
+ * trademarks, maskwork rights, or any other form of intellectual
+ * property whatsoever. Maxim Integrated Products, Inc. retains all
+ * ownership rights.
+ *******************************************************************************
+ */
+
+#include <stdint.h>
+#include "MAX30101_helper.h"
+#include "MAX30101.h"
+#include "Peripherals.h"
+
+// int8_t max30101_SpO2mode_stop(void);
+// int8_t max30101_HRmode_stop(void);
+// int8_t max30101_Multimode_stop(void);
+
+static uint8_t flags[3];
+
+uint8_t MAX30101_Helper_IsStreaming(eMAX30101Flags flag) {
+  return flags[(uint32_t)flag];
+}
+
+void MAX30101_Helper_SetStreamingFlag(eMAX30101Flags flag, uint8_t state) {
+  flags[(uint32_t)flag] = state;
+}
+
+void MAX30101_Helper_Stop(void) {
+  if (flags[(uint32_t)eStreaming_HR] == 1) {
+    Peripherals::max30101()->HRmode_stop();
+  }
+  if (flags[(uint32_t)eStreaming_SPO2] == 1) {
+    Peripherals::max30101()->SpO2mode_stop();
+  }
+  if (flags[(uint32_t)eStreaming_MULTI] == 1) {
+    Peripherals::max30101()->Multimode_stop();
+  }
+  MAX30101_Helper_ClearStreamingFlags();
+}
+
+void MAX30101_Helper_ClearStreamingFlags(void) {
+  uint32_t i;
+  for (i = 0; i < 3; i++) {
+    flags[i] = 0;
+  }
+}
+
+void MAX30101_OnInterrupt(void) { I2CM_Init_Reset(2, 1); }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/e4a10ed6eb92/HSP/Devices/MAX30101/MAX30101_helper.h	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,48 @@
+/*******************************************************************************
+ * Copyright (C) 2016 Maxim Integrated Products, Inc., All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+ * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Except as contained in this notice, the name of Maxim Integrated
+ * Products, Inc. shall not be used except as stated in the Maxim Integrated
+ * Products, Inc. Branding Policy.
+ *
+ * The mere transfer of this software does not imply any licenses
+ * of trade secrets, proprietary technology, copyrights, patents,
+ * trademarks, maskwork rights, or any other form of intellectual
+ * property whatsoever. Maxim Integrated Products, Inc. retains all
+ * ownership rights.
+ *******************************************************************************
+ */
+#ifndef MAX30101_HELPER_H_
+#define MAX30101_HELPER_H_
+
+typedef enum eMAX30101Flags {
+  eStreaming_HR,
+  eStreaming_SPO2,
+  eStreaming_MULTI
+} eMAX30101Flags;
+
+uint8_t MAX30101_Helper_IsStreaming(eMAX30101Flags flag);
+void MAX30101_Helper_SetStreamingFlag(eMAX30101Flags flag, uint8_t state);
+void MAX30101_Helper_Stop(void);
+void MAX30101_Helper_ClearStreamingFlags(void);
+void MAX30101_OnInterrupt(void);
+
+#endif /* MAX30101_HELPER_H_ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/e4a10ed6eb92/HSP/Devices/PushButton/PushButton.cpp	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,68 @@
+/*******************************************************************************
+ * Copyright (C) 2016 Maxim Integrated Products, Inc., All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+ * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Except as contained in this notice, the name of Maxim Integrated
+ * Products, Inc. shall not be used except as stated in the Maxim Integrated
+ * Products, Inc. Branding Policy.
+ *
+ * The mere transfer of this software does not imply any licenses
+ * of trade secrets, proprietary technology, copyrights, patents,
+ * trademarks, maskwork rights, or any other form of intellectual
+ * property whatsoever. Maxim Integrated Products, Inc. retains all
+ * ownership rights.
+ *******************************************************************************
+ */
+
+#include "PushButton.h"
+#include "Peripherals.h"
+
+void pb_hit_interrupt_fall(void);
+
+PushButton::PushButton(PinName pin) : interruptButton(pin) {
+  this->pin = pin;
+
+  interruptButton.mode(PullUp);
+  // Delay for initial pullup to take effect
+  wait(0.01f);
+  // Attach the address of the interrupt handler routine for pushbutton
+  interruptButton.fall(&pb_hit_interrupt_fall);
+}
+
+bool PushButton::GetButtonFallState(void) { 
+ return buttonFallState; 
+}
+
+void PushButton::SetButtonFallState(bool state) { 
+ buttonFallState = state; 
+}
+
+void PushButton::clearButtonFallState(void) { 
+ buttonFallState = false; 
+}
+
+int PushButton::Read(void) { 
+ return interruptButton.read(); 
+}
+
+void pb_hit_interrupt_fall(void) {
+  if (Peripherals::pushButton() != NULL)
+    Peripherals::pushButton()->SetButtonFallState(true);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/e4a10ed6eb92/HSP/Devices/PushButton/PushButton.h	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,69 @@
+/*******************************************************************************
+ * Copyright (C) 2016 Maxim Integrated Products, Inc., All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+ * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Except as contained in this notice, the name of Maxim Integrated
+ * Products, Inc. shall not be used except as stated in the Maxim Integrated
+ * Products, Inc. Branding Policy.
+ *
+ * The mere transfer of this software does not imply any licenses
+ * of trade secrets, proprietary technology, copyrights, patents,
+ * trademarks, maskwork rights, or any other form of intellectual
+ * property whatsoever. Maxim Integrated Products, Inc. retains all
+ * ownership rights.
+ *******************************************************************************
+ */
+#ifndef _PUSHBUTTON_H
+#define _PUSHBUTTON_H
+
+#include "mbed.h"
+
+class PushButton {
+public:
+  /**
+  * @brief Constructor with a PinName
+  */
+  PushButton(PinName pin);
+  /**
+  * @brief Get the pushed state of the button
+  */
+  bool GetButtonFallState(void);
+  /**
+  * @brief Clear the pushed state of the button
+  */
+  void clearButtonFallState(void);
+  /**
+  * @brief Read the button input
+  * @return Represented as 0 or 1 (int)
+  */
+  int Read(void);
+  /**
+  * @brief Set the state
+  * @param state Set the button state to this value
+  */
+  void SetButtonFallState(bool state);
+
+private:
+  InterruptIn interruptButton;
+  bool buttonFallState;
+  PinName pin;
+};
+
+#endif /* _PUSHBUTTON_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/e4a10ed6eb92/HSP/Devices/S25FS256/S25FS512.cpp	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,472 @@
+/*******************************************************************************
+ * Copyright (C) 2016 Maxim Integrated Products, Inc., All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+ * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Except as contained in this notice, the name of Maxim Integrated
+ * Products, Inc. shall not be used except as stated in the Maxim Integrated
+ * Products, Inc. Branding Policy.
+ *
+ * The mere transfer of this software does not imply any licenses
+ * of trade secrets, proprietary technology, copyrights, patents,
+ * trademarks, maskwork rights, or any other form of intellectual
+ * property whatsoever. Maxim Integrated Products, Inc. retains all
+ * ownership rights.
+ *******************************************************************************
+ */
+
+//
+// Flash Non-Volatile Memory
+// U27 S25FS512
+// Nimitz SPIM1
+//
+
+#include "mbed.h"
+#include "S25FS512.h"
+#include "QuadSpiInterface.h"
+
+#define IOMUX_IO_ENABLE              1
+
+#define S25FS512_SPI_PORT            1
+#define S25FS512_CS_PIN              0
+#define S25FS512_CS_POLARITY         0
+#define S25FS512_CS_ACTIVITY_DELAY   0
+#define S25FS512_CS_INACTIVITY_DELAY 0
+#define S25FS512_CLK_HI              4
+#define S25FS512_CLK_LOW             4
+#define S25FS512_ALT_CLK             0
+#define S25FS512_CLK_POLARITY        0
+#define S25FS512_CLK_PHASE           0
+#define S25FS512_WRITE               1
+#define S25FS512_READ                0
+
+#define INT_PORT_B 3
+#define INT_PIN_B 6
+
+uint8_t flashBuffer[257 + 10];
+
+//******************************************************************************
+S25FS512::S25FS512(QuadSpiInterface *_quadSpiInterface) {
+  this->quadSpiInterface = _quadSpiInterface;
+}
+
+//******************************************************************************
+S25FS512::~S25FS512(void) {
+}
+
+//******************************************************************************
+int S25FS512::init(void) {
+  setQuadMode();
+  return 0;
+}
+
+//******************************************************************************
+int S25FS512::wren4Wire(void) {
+  uint8_t cmdArray[8];
+  // Send WREN
+  cmdArray[0] = 0x06;
+  wait_1mS();
+  return reg_write_read_multiple_4Wire(cmdArray, 1, flashBuffer, 1);
+}
+
+//******************************************************************************
+uint8_t S25FS512::wren(void) {
+  uint8_t cmdArray[8];
+  // Send WREN
+  cmdArray[0] = 0x06;
+  wait_1mS();
+  return reg_write_read_multiple_quad(cmdArray, 1, flashBuffer, 0);
+}
+
+//******************************************************************************
+int8_t S25FS512::reg_write_read_multiple_quad_last(uint8_t *bufferOut,
+                                                   uint8_t numberOut,
+                                                   uint8_t *bufferIn,
+                                                   uint8_t numberIn,
+                                                   uint8_t last) {
+  int32_t success = 0;
+
+  success = quadSpiInterface->SPI_Transmit( 
+                       bufferOut, numberOut, 
+                       bufferIn, numberIn, (int)last);
+
+  if (success != 0) return -1;
+  return 0;
+}
+
+//******************************************************************************
+int8_t S25FS512::reg_write_read_multiple_4Wire(uint8_t *bufferOut,
+                                               uint8_t numberOut,
+                                               uint8_t *bufferIn,
+                                               uint8_t numberIn) {
+  int32_t success = 0;
+  success = quadSpiInterface->SPI_Transmit4Wire(bufferOut, numberOut, bufferIn,
+                                                numberIn, (int)1);
+
+  if (success != 0) return -1;
+  return 0;
+}
+
+//******************************************************************************
+int8_t S25FS512::reg_write_read_multiple_quad(uint8_t *bufferOut,
+                                              uint8_t numberOut,
+                                              uint8_t *bufferIn,
+                                              uint8_t numberIn) {
+  int8_t ret;
+  ret = reg_write_read_multiple_quad_last(bufferOut, numberOut, bufferIn,
+                                          numberIn, 1);
+  return ret;
+}
+
+//******************************************************************************
+void S25FS512::readID(uint8_t *id) {
+  uint8_t cmd = 0x9F;
+  reg_write_read_multiple_quad(&cmd, 1, id, 4);
+}
+
+//******************************************************************************
+int8_t S25FS512::writeAnyRegister(uint32_t address, uint8_t data) {
+  uint8_t cmdArray[5];
+  cmdArray[0] = 0x71;
+  cmdArray[1] = (address >> 16) & 0xFF;
+  cmdArray[2] = (address >> 8) & 0xFF;
+  cmdArray[3] = (address >> 0) & 0xFF;
+  cmdArray[4] = data;
+  return reg_write_read_multiple_quad(cmdArray, 5, flashBuffer, 0);
+}
+
+int8_t S25FS512::writeAnyRegister4Wire(uint32_t address, uint8_t data) {
+  uint8_t cmdArray[5];
+  cmdArray[0] = 0x71;
+  cmdArray[1] = (address >> 16) & 0xFF;
+  cmdArray[2] = (address >> 8) & 0xFF;
+  cmdArray[3] = (address >> 0) & 0xFF;
+  cmdArray[4] = data;
+  return reg_write_read_multiple_4Wire(cmdArray, 5, flashBuffer, 5);
+}
+
+//******************************************************************************
+int8_t S25FS512::writeRegisters(void) {
+  uint8_t cmdArray[3];
+  wait_1mS();
+  cmdArray[0] = 0x01;
+  cmdArray[1] = 0x00;
+  cmdArray[2] = 0x02; // set Quad to 1
+  reg_write_read_multiple_quad(cmdArray, 3, flashBuffer, 0);
+  return 0;
+}
+
+//******************************************************************************
+int8_t S25FS512::readAnyRegister(uint32_t address, uint8_t *data,
+                                 uint32_t length) {
+  uint8_t cmdArray[4];
+  cmdArray[0] = 0x65;
+  cmdArray[1] = (address >> 16) & 0xFF;
+  cmdArray[2] = (address >> 8) & 0xFF;
+  cmdArray[3] = (address >> 0) & 0xFF;
+  return reg_write_read_multiple_quad(cmdArray, 4, data, length);
+}
+
+//******************************************************************************
+int8_t S25FS512::bulkErase(void) {
+  uint8_t cmdArray[1];
+  cmdArray[0] = 0x60;
+  return reg_write_read_multiple_quad(cmdArray, 1, flashBuffer, 0);
+}
+
+//******************************************************************************
+int8_t S25FS512::pageProgram(uint32_t address, uint8_t *buffer) {
+  uint32_t i;
+  uint8_t cmdArray[5 + 256];
+  uint8_t *ptr;
+
+  // for (i = 0; i < 256; i++) {
+  //	dataArray[i] = i;
+  //}
+  cmdArray[0] = 0x02; // 0x71;
+  //	cmdArray[1] = (address >> 24) & 0xFF;
+  cmdArray[1] = (address >> 16) & 0xFF;
+  cmdArray[2] = (address >> 8) & 0xFF;
+  cmdArray[3] = (address >> 0) & 0xFF;
+  for (i = 0; i < 256; i++) {
+    cmdArray[4 + i] = buffer[i];
+  }
+  //	reg_write_read_multiple_quad(cmdArray,256 + 4,flashBuffer,256 + 4);
+
+  ptr = cmdArray;
+  reg_write_read_multiple_quad_last(ptr, 4 + 64, flashBuffer, 0, 0);
+  wait_1mS();
+  ptr += (4 + 64);
+  reg_write_read_multiple_quad_last(ptr, 64, flashBuffer, 0, 0);
+  wait_1mS();
+  ptr += 64;
+  reg_write_read_multiple_quad_last(ptr, 64, flashBuffer, 0, 0);
+  wait_1mS();
+  ptr += 64;
+  reg_write_read_multiple_quad_last(ptr, 64, flashBuffer, 0, 1);
+  wait_1mS();
+  return 0;
+}
+
+//******************************************************************************
+int8_t S25FS512::quadIoRead_Pages(uint32_t address, uint8_t *buffer,
+                                  uint32_t numberOfPages) {
+  uint8_t cmdArray[5];
+  uint8_t *ptr;
+  uint8_t last;
+  uint32_t i;
+
+  cmdArray[0] = 0xEB;
+  cmdArray[1] = (address >> 16) & 0xFF;
+  cmdArray[2] = (address >> 8) & 0xFF;
+  cmdArray[3] = (address >> 0) & 0xFF;
+  ptr = buffer;
+  last = 0;
+  // only send the command
+  reg_write_read_multiple_quad_last(cmdArray, 4, ptr, 0, 0);
+  wait_1mS();
+  reg_write_read_multiple_quad_last(cmdArray, 0, ptr, 5, 0);
+  wait_1mS();
+  for (i = 0; i < numberOfPages; i++) {
+    reg_write_read_multiple_quad_last(cmdArray, 0, ptr, 64, 0);
+    wait_1mS();
+    ptr += 64;
+    reg_write_read_multiple_quad_last(cmdArray, 0, ptr, 64, 0);
+    wait_1mS();
+    ptr += 64;
+    reg_write_read_multiple_quad_last(cmdArray, 0, ptr, 64, 0);
+    wait_1mS();
+    ptr += 64;
+    // check if this is the last page
+    if ((i + 1) == numberOfPages) {
+      last = 1;
+    }
+    reg_write_read_multiple_quad_last(cmdArray, 0, ptr, 64, last);
+    wait_1mS();
+    ptr += 64;
+  }
+  return 0;
+}
+
+//******************************************************************************
+int8_t S25FS512::checkBusy(void) {
+  uint8_t cmdArray[5];
+  cmdArray[0] = 0x05;
+  reg_write_read_multiple_quad(cmdArray, 1, flashBuffer, 2);
+  return flashBuffer[1] & 0x1;
+}
+
+//******************************************************************************
+void S25FS512::waitTillNotBusy(void) {
+  while (checkBusy() == 1) {
+  }
+}
+
+//******************************************************************************
+int8_t S25FS512::sectorErase(uint32_t address) {
+  uint8_t cmdArray[5];
+  cmdArray[0] = 0xD8;
+  cmdArray[1] = (address >> 16) & 0xFF;
+  cmdArray[2] = (address >> 8) & 0xFF;
+  cmdArray[3] = (address >> 0) & 0xFF;
+  return reg_write_read_multiple_quad(cmdArray, 4, flashBuffer, 0);
+}
+
+//******************************************************************************
+int8_t S25FS512::parameterSectorErase(uint32_t address) {
+  uint8_t cmdArray[5];
+  cmdArray[0] = 0x20;
+  cmdArray[1] = (address >> 16) & 0xFF;
+  cmdArray[2] = (address >> 8) & 0xFF;
+  cmdArray[3] = (address >> 0) & 0xFF;
+  reg_write_read_multiple_quad(cmdArray, 4, flashBuffer, 0);
+  return 0;
+}
+
+#define ONE_MS (32768 / 500)
+#define ONEHUNDRED_US (32768 / 1000)
+#define TEM_MS (32768 / 50)
+
+//******************************************************************************
+void S25FS512::wait_1mS(void) { 
+ wait_ms(1); 
+}
+
+//******************************************************************************
+void S25FS512::wait_100uS(void) { 
+wait_us(100); 
+}
+
+//******************************************************************************
+void S25FS512::wait_10mS(void) { 
+wait_ms(10); 
+}
+
+//******************************************************************************
+int8_t S25FS512::readIdentification(uint8_t *dataArray, uint8_t length) {
+  // 4QIOR = 0x9F
+  uint8_t cmdArray[1];
+  cmdArray[0] = 0x9F; // read ID command
+  return reg_write_read_multiple_quad(cmdArray, 1, dataArray, length);
+}
+
+//******************************************************************************
+uint8_t S25FS512::reset(void) {
+  uint8_t cmdArray[8];
+  wait_1mS();
+  cmdArray[0] = 0x66;
+  reg_write_read_multiple_quad(cmdArray, 1, flashBuffer, 0);
+  wait_1mS();
+  cmdArray[0] = 0x99;
+  reg_write_read_multiple_quad(cmdArray, 1, flashBuffer, 0);
+  return 0;
+}
+
+//******************************************************************************
+uint8_t S25FS512::enableHWReset(void) {
+  uint8_t data[8];
+  wait_1mS();
+  // CR2V Configuration Register-2 Volatile
+  // bit 5
+  readAnyRegister(0x00800003, data, 8);
+  writeAnyRegister(0x00800003, 0x64);
+  return 0;
+}
+
+//******************************************************************************
+uint8_t S25FS512::detect(void) {
+  uint8_t array[8];
+  uint8_t array2[8];
+
+  // Send WREN
+  wren();
+  // Send WREN
+  wren();
+  // delay
+  wait_1mS();
+  // Send WREN
+  wren();
+  // delay
+  wait_1mS();
+
+  // Send write any register cmd
+  writeAnyRegister(0x0003, 0x48);
+  // delay
+  wait_1mS();
+  array[0] = 0x9F; // read ID command
+  reg_write_read_multiple_quad(array, 1, array2, 7);
+  return 0;
+}
+
+//******************************************************************************
+int S25FS512::setQuadMode(void) {
+  wait_1mS();
+  wren4Wire();
+  wait_1mS();
+  writeAnyRegister4Wire(0x800002, 0x02); // set Quad = 1
+  wait_1mS();
+  wren4Wire();
+  wait_1mS();
+  writeAnyRegister4Wire(0x800003, 0x48); // set 8 latency, set QPI 4-4-4
+}
+
+//******************************************************************************
+uint32_t S25FS512::isPageEmpty(uint8_t *ptr) {
+  int i;
+  for (i = 0; i < 256; i++) {
+    if (ptr[i] != 0xFF)
+      return 0;
+  }
+  return 1;
+}
+
+//******************************************************************************
+int8_t S25FS512::parameterSectorErase_Helper(uint32_t address) {
+  waitTillNotBusy();
+  wait_100uS();
+  wren();
+  wait_100uS();
+  parameterSectorErase(address);
+  wait_100uS();
+  waitTillNotBusy();
+  wait_100uS();
+  return 0;
+}
+
+//******************************************************************************
+int8_t S25FS512::sectorErase_Helper(uint32_t address) {
+  waitTillNotBusy();
+  wait_100uS();
+  wren();
+  wait_100uS();
+  if (address < 0x8000) {
+    parameterSectorErase(address);
+  } else {
+    sectorErase(address);
+  }
+  wait_100uS();
+  waitTillNotBusy();
+  wait_100uS();
+  return 0;
+}
+
+//******************************************************************************
+int8_t S25FS512::bulkErase_Helper(void) {
+  waitTillNotBusy();
+  wait_100uS();
+  wren();
+  wait_100uS();
+  bulkErase();
+  wait_100uS();
+  waitTillNotBusy();
+  wait_100uS();
+  return 0;
+}
+
+//******************************************************************************
+// write a page worth of data (256 bytes) from buffer, offset defined where in
+// the buffer to begin write
+int8_t S25FS512::writePage_Helper(uint32_t pageNumber, uint8_t *buffer,
+                                  uint32_t offset) {
+  uint8_t *ptr;
+  waitTillNotBusy();
+  wait_1mS();
+  wren();
+  ptr = &buffer[offset];
+  wait_1mS();
+  pageProgram(pageNumber << 8, ptr);
+  wait_1mS();
+  return 0;
+}
+
+//******************************************************************************
+// read pages from flash into buffer, offset defined where in the buffer use
+int8_t S25FS512::readPages_Helper(uint32_t startPageNumber,
+                                  uint32_t endPageNumber, uint8_t *buffer,
+                                  uint32_t offset) {
+  uint8_t *ptr;
+  uint32_t page;
+  ptr = &buffer[offset];
+  for (page = startPageNumber; page <= endPageNumber; page++) {
+    wait_100uS();
+    quadIoRead_Pages((uint32_t)(page << 8), (uint8_t *)ptr, 1);
+    ptr += 0x100;
+  }
+  return 0;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/e4a10ed6eb92/HSP/Devices/S25FS256/S25FS512.h	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,127 @@
+/*******************************************************************************
+ * Copyright (C) 2016 Maxim Integrated Products, Inc., All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+ * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Except as contained in this notice, the name of Maxim Integrated
+ * Products, Inc. shall not be used except as stated in the Maxim Integrated
+ * Products, Inc. Branding Policy.
+ *
+ * The mere transfer of this software does not imply any licenses
+ * of trade secrets, proprietary technology, copyrights, patents,
+ * trademarks, maskwork rights, or any other form of intellectual
+ * property whatsoever. Maxim Integrated Products, Inc. retains all
+ * ownership rights.
+ *******************************************************************************
+ */
+#ifndef S25FS512_H_
+#define S25FS512_H_
+
+#include "mbed.h"
+#include "QuadSpiInterface.h"
+
+class S25FS512 {
+public:
+  S25FS512(QuadSpiInterface *_quadSpiInterface);
+  ~S25FS512(void);
+
+  QuadSpiInterface *quadSpiInterface;
+
+  /** Initialize the driver
+  */
+  int init(void);
+
+  /** Detect the presence of the flash device
+  */
+  uint8_t detect(void);
+
+  /** Read the identification of the flash
+  */
+  int8_t readIdentification(uint8_t *dataArray, uint8_t length);
+
+  /** Bulk erase the flash device
+  */
+  int8_t bulkErase_Helper(void);
+
+  /** Erase Parameter Sectors
+  */
+  int8_t parameterSectorErase_Helper(uint32_t address);
+
+  /** Write a Page
+  */
+  int8_t writePage_Helper(uint32_t pageNumber, uint8_t *buffer,
+                          uint32_t offset);
+
+  /** Read a Page
+  * @param
+  */
+  int8_t readPages_Helper(uint32_t startPageNumber, uint32_t endPageNumber,
+                          uint8_t *buffer, uint32_t offset);
+
+  /** Erase a Sector
+  @param address Address of sector to erase
+  */
+
+  int8_t sectorErase_Helper(uint32_t address);
+  /** Scans through byte pointer for a page worth of data to see if the page is all FFs
+  @param ptr Byte pointer to buffer to scan
+  @return Returns a 1 if the page is empty, 0 if it is not all FFs
+  */
+  uint32_t isPageEmpty(uint8_t *ptr);
+  
+  /** Issue a software reset to the flash device
+  */
+
+  uint8_t reset(void);
+  /** Enable a hardware reset
+  */
+
+  uint8_t enableHWReset(void);
+  /** Read the id byte of this device
+  */
+
+  void readID(uint8_t *id);
+
+private:
+  int8_t reg_write_read_multiple_quad_last(uint8_t *dataIn, uint8_t numberIn, uint8_t *dataOut, uint8_t numberOut, uint8_t last);
+  int8_t reg_write_read_multiple_quad(uint8_t *dataIn, uint8_t numberIn, uint8_t *dataOut, uint8_t numberOut);
+  int8_t reg_write_read_multiple_4Wire(uint8_t *bufferOut, uint8_t numberOut, uint8_t *bufferIn, uint8_t numberIn);
+  uint8_t spiWriteRead (uint8_t writeNumber,uint8_t *writeData, uint8_t readNumber, uint8_t *readData);
+  uint8_t spiWriteRead4Wire(uint8_t writeNumber,uint8_t *writeData, uint8_t readNumber, uint8_t *readData);
+
+  int8_t writeAnyRegister(uint32_t address, uint8_t data);
+  int8_t writeAnyRegister4Wire(uint32_t address, uint8_t data);
+  int8_t writeRegisters(void);
+  uint8_t wren(void);
+  int setQuadMode(void);
+  int wren4Wire(void);
+  // int8_t setQuadMode();
+  int8_t readAnyRegister(uint32_t address, uint8_t *data, uint32_t length);
+  int8_t bulkErase(void);
+  int8_t pageProgram(uint32_t address, uint8_t *buffer);
+  int8_t quadIoRead_Pages(uint32_t address, uint8_t *buffer, uint32_t numberOfPages);
+  int8_t checkBusy(void);
+  void waitTillNotBusy(void);
+  int8_t sectorErase(uint32_t address);
+  int8_t parameterSectorErase(uint32_t address);
+  void wait_1mS(void);
+  void wait_100uS(void);
+  void wait_10mS(void);
+};
+#endif /* S25FS512_H_ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/e4a10ed6eb92/HSP/Devices/S25FS256/S25FS512_RPC.cpp	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,122 @@
+/*******************************************************************************
+ * Copyright (C) 2016 Maxim Integrated Products, Inc., All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+ * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Except as contained in this notice, the name of Maxim Integrated
+ * Products, Inc. shall not be used except as stated in the Maxim Integrated
+ * Products, Inc. Branding Policy.
+ *
+ * The mere transfer of this software does not imply any licenses
+ * of trade secrets, proprietary technology, copyrights, patents,
+ * trademarks, maskwork rights, or any other form of intellectual
+ * property whatsoever. Maxim Integrated Products, Inc. retains all
+ * ownership rights.
+ *******************************************************************************
+ */
+
+#include "S25FS512_RPC.h"
+#include "S25FS512.h"
+#include "StringInOut.h"
+#include "StringHelper.h"
+#include "Peripherals.h"
+
+int S25FS512_Reset(char argStrs[32][32], char replyStrs[32][32]) {
+  uint32_t reply[1];
+  Peripherals::s25FS512()->reset();
+  reply[0] = 0x80;
+  FormatReply32(reply, sizeof(reply) / sizeof(uint32_t), replyStrs);
+  return 0;
+}
+
+int S25FS512_EnableHWReset(char argStrs[32][32], char replyStrs[32][32]) {
+  uint32_t reply[1];
+  Peripherals::s25FS512()->enableHWReset();
+  reply[0] = 0x80;
+  FormatReply32(reply, sizeof(reply) / sizeof(uint32_t), replyStrs);
+  return 0;
+}
+
+int S25FS512_SpiWriteRead(char argStrs[32][32], char replyStrs[32][32]) {
+  uint8_t args[16];
+  uint8_t reply[16];
+  uint8_t writeNumber;
+  uint8_t readNumber;
+  // get the number of bytes to write
+  ProcessArgs(argStrs, args, 1);
+  writeNumber = args[0];
+  ProcessArgs(argStrs, args, writeNumber + 2);
+  readNumber = args[writeNumber + 1];
+  FormatReply(reply, readNumber, replyStrs);
+  return 0;
+}
+
+int S25FS512_SpiWriteRead4Wire(char argStrs[32][32], char replyStrs[32][32]) {
+  uint8_t args[16];
+  uint8_t reply[16];
+  uint8_t writeNumber;
+  uint8_t readNumber;
+  // get the number of bytes to write
+  ProcessArgs(argStrs, args, 1);
+  writeNumber = args[0];
+  ProcessArgs(argStrs, args, writeNumber + 2);
+  readNumber = args[writeNumber + 1];
+  FormatReply(reply, readNumber, replyStrs);
+  return 0;
+}
+
+int S25FS512_ReadPage(char argStrs[32][32], char replyStrs[32][32]) {
+  uint32_t args[2];
+  uint32_t reply[1];
+  ProcessArgs32(argStrs, args, sizeof(args) / sizeof(uint32_t));
+  reply[0] = 0x80;
+  FormatReply32(reply, sizeof(reply) / sizeof(uint32_t), replyStrs);
+  return 0;
+}
+
+int S25FS512_ReadPagesBinary(char argStrs[32][32], char replyStrs[32][32]) {
+  uint32_t args[2];
+  uint32_t reply[1];
+  uint8_t pageData[256];
+
+  uint32_t startPage;
+  uint32_t endPage;
+  uint32_t page;
+
+  ProcessArgs32(argStrs, args, sizeof(args) / sizeof(uint32_t));
+  startPage = args[0];
+  endPage = args[1];
+  for (page = startPage; page <= endPage; page++) {
+    Peripherals::s25FS512()->readPages_Helper(page, page, pageData, 0);
+    putBytes256Block(pageData, 1);
+  }
+  reply[0] = 0x80;
+  FormatReply32(reply, sizeof(reply) / sizeof(uint32_t), replyStrs);
+  return 0;
+}
+
+int S25FS512_ReadId(char argStrs[32][32], char replyStrs[32][32]) {
+  char str[32];
+  uint8_t data[128];
+  Peripherals::s25FS512()->readIdentification(data, sizeof(data));
+  Peripherals::s25FS512()->readIdentification(data, sizeof(data));
+  sprintf(str, "%02X%02X%02X%02X", data[0], data[1], data[2], data[3]);
+  strcpy(replyStrs[0], str);
+  return 0;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/e4a10ed6eb92/HSP/Devices/S25FS256/S25FS512_RPC.h	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,47 @@
+/*******************************************************************************
+ * Copyright (C) 2016 Maxim Integrated Products, Inc., All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+ * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Except as contained in this notice, the name of Maxim Integrated
+ * Products, Inc. shall not be used except as stated in the Maxim Integrated
+ * Products, Inc. Branding Policy.
+ *
+ * The mere transfer of this software does not imply any licenses
+ * of trade secrets, proprietary technology, copyrights, patents,
+ * trademarks, maskwork rights, or any other form of intellectual
+ * property whatsoever. Maxim Integrated Products, Inc. retains all
+ * ownership rights.
+ *******************************************************************************
+ */
+#ifndef _S25FS512_RPC_H_
+#define _S25FS512_RPC_H_
+
+#include "mbed.h"
+
+int S25FS512_ReadPagesBinary(char argStrs[32][32], char replyStrs[32][32]);
+int S25FS512_ReadPage(char argStrs[32][32], char replyStrs[32][32]);
+int S25FS512_ReadPagesBinary(char argStrs[32][32], char replyStrs[32][32]);
+int S25FS512_ReadId(char argStrs[32][32], char replyStrs[32][32]);
+int S25FS512_Reset(char argStrs[32][32], char replyStrs[32][32]);
+int S25FS512_EnableHWReset(char argStrs[32][32], char replyStrs[32][32]);
+int S25FS512_SpiWriteRead(char argStrs[32][32], char replyStrs[32][32]);
+int S25FS512_SpiWriteRead4Wire(char argStrs[32][32], char replyStrs[32][32]);
+
+#endif /* _S25FS512_RPC_H_ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/e4a10ed6eb92/HSP/Hsp_BLE/BluetoothLE/BluetoothLE.cpp	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,172 @@
+/*******************************************************************************
+ * Copyright (C) 2016 Maxim Integrated Products, Inc., All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+ * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Except as contained in this notice, the name of Maxim Integrated
+ * Products, Inc. shall not be used except as stated in the Maxim Integrated
+ * Products, Inc. Branding Policy.
+ *
+ * The mere transfer of this software does not imply any licenses
+ * of trade secrets, proprietary technology, copyrights, patents,
+ * trademarks, maskwork rights, or any other form of intellectual
+ * property whatsoever. Maxim Integrated Products, Inc. retains all
+ * ownership rights.
+ *******************************************************************************
+ */
+#include "BluetoothLE.h"
+#include "Characteristic.h"
+
+/**
+ * @brief Constructor for class
+ */
+BluetoothLE::BluetoothLE(BLE *ble, int numberOfCharacteristics)
+    : ble(ble), runningIndex(0),
+      numberOfCharacteristics(numberOfCharacteristics) {
+  characteristics = new Characteristic *[numberOfCharacteristics];
+  gattCharacteristics = new GattCharacteristic *[numberOfCharacteristics];
+}
+
+/**
+ * @brief Destructor for class
+ */
+BluetoothLE::~BluetoothLE(void) {
+  for (int i = 0; i < numberOfCharacteristics; i++) delete characteristics[i];
+  delete[] gattCharacteristics;
+  delete[] characteristics;
+}
+
+/**
+ * @brief Initialize the advertising, characteristics, service for this platform
+ */
+void BluetoothLE::addCharacteristic(Characteristic *characteristic) {
+  characteristic->setBLE(ble);
+  characteristic->setIndex(runningIndex);
+  characteristics[runningIndex] = characteristic;
+  gattCharacteristics[runningIndex] = characteristic->getGattCharacteristic();
+  runningIndex++;
+}
+
+/**
+ * @brief Initialize the advertising, characteristics, service for this platform
+ */
+void BluetoothLE::initService(uint8_t *serialNumber, uint8_t *deviceName,
+                              int nameSize, uint8_t *serviceUUID) {
+  ble->init();
+  ble->onDisconnection(this, &BluetoothLE::disconnectionCallback);
+
+  ble->gap().setAddress((BLEProtocol::AddressType_t)0, serialNumber);
+
+  // Setup Advertising
+  ble->accumulateAdvertisingPayload(
+      GapAdvertisingData::BREDR_NOT_SUPPORTED |
+      GapAdvertisingData::LE_GENERAL_DISCOVERABLE);
+  ble->accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LOCAL_NAME,
+                                    (uint8_t *)deviceName, nameSize);
+  ble->setAdvertisingType(GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED);
+  ble->setAdvertisingInterval(1600); // 1000ms; in multiples of 0.625ms.
+  GattService envService(serviceUUID, gattCharacteristics,
+                         numberOfCharacteristics);
+  ble->gattServer().addService(envService);
+  ble->onDataWritten(this, &BluetoothLE::onDataWritten);
+  // Start Advertising
+  ble->startAdvertising();
+}
+
+static const Gap::ConnectionParams_t paramsLowPower = {
+    400,    /**< Minimum Connection Interval in 1.25 ms units, see @ref BLE_GAP_CP_LIMITS.*/
+    400,    /**< Maximum Connection Interval in 1.25 ms units, see @ref BLE_GAP_CP_LIMITS.*/
+    60,     /**< Slave Latency in number of connection events, see @ref BLE_GAP_CP_LIMITS.*/
+    3100    /**< Connection Supervision Timeout in 10 ms units, see @ref BLE_GAP_CP_LIMITS.*/
+};
+
+static Gap::Handle_t connHandle = 0;
+
+/**
+ * @brief Called on BLE connection
+ */
+void BluetoothLE::connectionCallback(
+    const Gap::ConnectionCallbackParams_t *params) {
+  connHandle = params->handle;
+}
+
+/**
+ * @brief Start advertising on a disconnect
+ */
+void BluetoothLE::disconnectionCallback(
+    const Gap::DisconnectionCallbackParams_t *params) {
+  _isConnected = false;
+  ble->startAdvertising();
+}
+
+/**
+ * @brief Called when the client writes to a writable characteristic
+ * @param params Pointer to a structure that contains details on what was
+ * written
+ */
+void BluetoothLE::onDataWritten(const GattWriteCallbackParams *params) {
+  int i;
+  int index = 0;
+  // match the characteristic handle
+  printf("BluetoothLE::onDataWritten ");
+  for (i = 0; i < numberOfCharacteristics; i++) {
+    if (params->handle == gattCharacteristics[i]->getValueHandle()) {
+      characteristics[i]->copyDataWritten(params);
+      index = i;
+      break;
+    }
+  }
+  (*_onDataWritten)(index);
+}
+
+/**
+* @brief Update the characteristic notification
+* @param index Index of the characteristic
+* @param data Pointer to the byte data to update the charateristic payload
+*/
+void BluetoothLE::notifyCharacteristic(int index, uint8_t *data) {
+  for (int i = 0; i < characteristics[index]->getPayloadLength(); i++) {
+    characteristics[index]->getPayloadBytes()[i] = data[i];
+  }
+  characteristics[index]->update();
+}
+
+/**
+* @brief Update the characteristic notification
+* @param index Index of the characteristic
+* @param data Pointer to the byte data to update the charateristic payload
+*/
+void BluetoothLE::notifyCharacteristicTest(int index) {
+  for (int i = 0; i < characteristics[index]->getPayloadLength(); i++) {
+    characteristics[index]->getPayloadBytes()[i]++;
+  }
+  characteristics[index]->update();
+}
+
+uint8_t *BluetoothLE::getDataWritten(int index, int *length) {
+  return characteristics[index]->getDataWritten(length);
+}
+
+/**
+* @brief Function to query if a BLE connection is active
+* @return true if BLE connected, false if BLE is not connected
+*/
+bool BluetoothLE::isConnected(void) {
+  return (ble->getGapState().connected == 1 ? true : false);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/e4a10ed6eb92/HSP/Hsp_BLE/BluetoothLE/BluetoothLE.h	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,137 @@
+/*******************************************************************************
+ * Copyright (C) 2016 Maxim Integrated Products, Inc., All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+ * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Except as contained in this notice, the name of Maxim Integrated
+ * Products, Inc. shall not be used except as stated in the Maxim Integrated
+ * Products, Inc. Branding Policy.
+ *
+ * The mere transfer of this software does not imply any licenses
+ * of trade secrets, proprietary technology, copyrights, patents,
+ * trademarks, maskwork rights, or any other form of intellectual
+ * property whatsoever. Maxim Integrated Products, Inc. retains all
+ * ownership rights.
+ *******************************************************************************
+ */
+#ifndef _BLUETOOTHLE_H_
+#define _BLUETOOTHLE_H_
+
+#include "mbed.h"
+#include "BLE.h"
+#include "Characteristic.h"
+
+class BluetoothLE {
+public:
+    BluetoothLE(BLE *ble, int numberOfCharacteristics);
+    ~BluetoothLE(void);
+    void addCharacteristic(Characteristic *characteristic);
+    void initService(uint8_t *serialNumber, uint8_t *deviceName, int nameSize, uint8_t *serviceUUID);
+    void notifyCharacteristic(int index, uint8_t *data);
+
+
+ 	/**
+	* @brief Return a characteristic based on incoming index
+    * @param index index into an array of characteristics
+	*/
+   Characteristic *getCharacteristic(int index) {
+        return characteristics[index];
+    }
+
+	/**
+	* @brief Get the payload for this characteristic
+	*/
+    uint8_t *getCharacteristicPayload(int index) {
+    	return characteristics[index]->getPayloadPtr();
+    }
+    typedef void (*PtrFunction)(int index);
+    
+	/**
+	* @brief Used to connect a connection callback
+	*/
+    template<typename T>
+    void onConnect(T *object, void (T::*member)(void)) {
+        _onConnect.attach( object, member ); 
+    }
+	/**
+	* @brief Used to connect a disconnection callback
+	*/
+    template<typename T>
+    void onDisconnect(T *object, void (T::*member)(void)) {
+        _onDisconnect.attach( object, member );
+    }
+	/**
+	* @brief Used to connect a characteristic written callback
+	*/
+    void onDataWritten(PtrFunction _onDataWritten) {
+        this->_onDataWritten = _onDataWritten;
+    }
+    /**
+	* @brief Get the connection state of the BLE
+	* @return true if connection BLE connection is present, false if no connection
+	*/
+    bool isConnected(void);
+    
+    /**
+	* @brief Perform a notification test
+	* @param index Index into an array of characteristic objects
+	*/
+    void notifyCharacteristicTest(int index);
+    
+    /**
+	* @brief Get the data that was written to the indexed characteristic
+	* @return true if connection BLE connection is present, false if no connection
+	*/
+	uint8_t *getDataWritten(int index, int *length);
+    
+private:
+	/**
+	* @brief Disconnection callback
+	*/
+    void disconnectionCallback(const Gap::DisconnectionCallbackParams_t *params);
+	/**
+	* @brief Connection callback
+	*/
+    void connectionCallback(const Gap::ConnectionCallbackParams_t *params);
+	/**
+	* @brief Characteristic written callback
+	*/
+    void onDataWritten(const GattWriteCallbackParams *params);
+
+	/// array of characteristic class pointers
+    Characteristic **characteristics;
+	/// array of gatt characteristic pointers
+    GattCharacteristic **gattCharacteristics;
+	/// pointer to mbed BLE layer
+    BLE *ble;
+	/// total number of characteristics
+    int numberOfCharacteristics;    
+	/// flag to keep track of BLE connection state
+    bool _isConnected;    
+	/// running index for building characteristic array
+    int runningIndex;
+	/// callback function for when a connection is made
+    FunctionPointer _onConnect;
+	/// callback function for when a connection is disconnected
+    FunctionPointer _onDisconnect; 
+	/// callback function for when characteristic data is written
+    PtrFunction _onDataWritten;
+};
+
+#endif // _BLUETOOTHLE_H_
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/e4a10ed6eb92/HSP/Hsp_BLE/BluetoothLE/Characteristic.cpp	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,61 @@
+/*******************************************************************************
+* Copyright (C) 2016 Maxim Integrated Products, Inc., All Rights Reserved.
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included
+* in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+* OTHER DEALINGS IN THE SOFTWARE.
+*
+* Except as contained in this notice, the name of Maxim Integrated
+* Products, Inc. shall not be used except as stated in the Maxim Integrated
+* Products, Inc. Branding Policy.
+*
+* The mere transfer of this software does not imply any licenses
+* of trade secrets, proprietary technology, copyrights, patents,
+* trademarks, maskwork rights, or any other form of intellectual
+* property whatsoever. Maxim Integrated Products, Inc. retains all
+* ownership rights.
+*******************************************************************************
+*/
+#include "Characteristic.h"
+
+Characteristic::Characteristic(uint16_t length, const UUID &uuid,
+                               uint8_t additionalProperties,
+                               GattAttribute *descriptors[],
+                               unsigned numDescriptors)
+    : gattCharacteristic(
+          uuid, reinterpret_cast<uint8_t *>(payload.getPointer()), length,
+          length, additionalProperties, descriptors, numDescriptors) {
+  payloadLength = length;
+  dataWrittenLength = -1;
+}
+
+void Characteristic::update(void) {
+  if (ble->getGapState().connected) {
+    ble->gattServer().write(gattCharacteristic.getValueHandle(),
+                            payload.getPointer(), payloadLength);
+  }
+}
+
+int Characteristic::getPayloadLength(void) { return payloadLength; }
+
+GattAttribute::Handle_t Characteristic::getValueHandle(void) {
+  return gattCharacteristic.getValueHandle();
+}
+
+GattCharacteristic *Characteristic::getGattCharacteristic(void) {
+  return &gattCharacteristic;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/e4a10ed6eb92/HSP/Hsp_BLE/BluetoothLE/Characteristic.h	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,112 @@
+/*******************************************************************************
+* Copyright (C) 2016 Maxim Integrated Products, Inc., All Rights Reserved.
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included
+* in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+* OTHER DEALINGS IN THE SOFTWARE.
+*
+* Except as contained in this notice, the name of Maxim Integrated
+* Products, Inc. shall not be used except as stated in the Maxim Integrated
+* Products, Inc. Branding Policy.
+*
+* The mere transfer of this software does not imply any licenses
+* of trade secrets, proprietary technology, copyrights, patents,
+* trademarks, maskwork rights, or any other form of intellectual
+* property whatsoever. Maxim Integrated Products, Inc. retains all
+* ownership rights.
+*******************************************************************************
+*/
+#ifndef _CHARACTERISTIC_H_
+#define _CHARACTERISTIC_H_
+
+#include "mbed.h"
+#include "BLE.h"
+#include "GattCharacteristic.h"
+
+class Characteristic {
+public:
+  /**
+   * @brief ticker handler static method
+   */
+  Characteristic(uint16_t length, const UUID &uuid,
+                 uint8_t additionalProperties =
+                     GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NONE,
+                 GattAttribute *descriptors[] = NULL,
+                 unsigned numDescriptors = 0);
+
+  void setIndex(int index) { this->index = index; }
+  /**
+  * @brief Set a pointer reference to the mbed BLE framework
+  */
+  void setBLE(BLE *ble) { this->ble = ble; }
+  /**
+  * @brief Get the pointer to the byte payload
+  */
+  uint8_t *getPayloadPtr(void) { return payload.getPointer(); }
+  /**
+   * @brief Get the handle of the characteristic
+   */
+  GattAttribute::Handle_t getValueHandle();
+  /**
+   * @brief Update the characteristic
+   */
+  void update(void);
+  /**
+   * @brief Get the GattCharacteristic
+   */
+  GattCharacteristic *getGattCharacteristic();
+  /**
+  * @brief Get the length of the payload
+  */
+  int getPayloadLength(void);
+
+  uint8_t *getPayloadBytes(void) { return payload.bytes; }
+
+  void copyDataWritten(const GattWriteCallbackParams *params) {
+    int i = 0;
+    while (i < params->len && i < sizeof(dataWritten)) {
+      dataWritten[i] = params->data[i];
+      i++;
+    }
+    dataWrittenLength = params->len;
+  }
+
+  uint8_t *getDataWritten(int *length) {
+    *length = dataWrittenLength;
+    return dataWritten;
+  }
+
+private:
+  int payloadLength;
+  struct PayloadStruct {
+    uint8_t bytes[32];
+    uint8_t *getPointer(void) { return bytes; }
+  };
+  /// local copy of data written to this characteristic
+  uint8_t dataWritten[64];
+  int dataWrittenLength;
+  /// payload structure for this characteristic
+  PayloadStruct payload;
+  /// gatt characteristic
+  GattCharacteristic gattCharacteristic;
+  /// mbed BLE framework pointer
+  BLE *ble;
+  /// index of this characteristic
+  int index;
+};
+
+#endif /* _CHARACTERISTIC_H_ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/e4a10ed6eb92/HSP/Hsp_BLE/HspBLE.cpp	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,197 @@
+/*******************************************************************************
+ * Copyright (C) 2016 Maxim Integrated Products, Inc., All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+ * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Except as contained in this notice, the name of Maxim Integrated
+ * Products, Inc. shall not be used except as stated in the Maxim Integrated
+ * Products, Inc. Branding Policy.
+ *
+ * The mere transfer of this software does not imply any licenses
+ * of trade secrets, proprietary technology, copyrights, patents,
+ * trademarks, maskwork rights, or any other form of intellectual
+ * property whatsoever. Maxim Integrated Products, Inc. retains all
+ * ownership rights.
+ *******************************************************************************
+ */
+#include "HspBLE.h"
+#include "Peripherals.h"
+#include "MAX30001_helper.h"
+
+#define LOW_BYTE(x) ((uint8_t)((x)&0xFF))
+#define HIGH_BYTE(x) ((uint8_t)(((x) >> 8) & 0xFF))
+
+/// define all of the characteristic UUIDs
+uint8_t HspBLE::temperatureTopCharUUID[] = {0x35,0x44,0x53,0x1b,0x00,0xc3,0x43,0x42,0x97,0x55,0xb5,0x6a,0xbe,0x8e,0x6c,0x67};
+uint8_t HspBLE::temperatureBottomCharUUID[] = {0x35,0x44,0x53,0x1b,0x00,0xc3,0x43,0x42,0x97,0x55,0xb5,0x6a,0xbe,0x8e,0x6a,0x66};
+uint8_t HspBLE::accelerometerCharUUID[] = {0xe6,0xc9,0xda,0x1a,0x80,0x96,0x48,0xbc,0x83,0xa4,0x3f,0xca,0x38,0x37,0x05,0xaf};
+uint8_t HspBLE::heartrateCharUUID[] = {0x62,0x1a,0x00,0xe3,0xb0,0x93,0x46,0xbf,0xaa,0xdc,0xab,0xe4,0xc6,0x48,0xc5,0x69};
+uint8_t HspBLE::pressureCharUUID[] = {0x1d,0x8a,0x19,0x32,0xda,0x49,0x49,0xad,0x91,0xd8,0x80,0x08,0x32,0xe7,0xe9,0x40};
+uint8_t HspBLE::dataCharUUID[] = {0xaa,0x8a,0x19,0x32,0xda,0x49,0x49,0xad,0x91,0xd8,0x80,0x08,0x32,0xe7,0xe9,0x40};
+uint8_t HspBLE::commandCharUUID[] = {0x36,0xe5,0x5e,0x37,0x6b,0x5b,0x42,0x0b,0x91,0x07,0x0d,0x34,0xa0,0xe8,0x67,0x5a};
+
+
+/// define the BLE device name
+uint8_t HspBLE::deviceName[] = "MAXREFDES100";
+/// define the BLE serial number
+uint8_t HspBLE::serialNumber[] = {0x77, 0x22, 0x33, 0x45, 0x67, 0x89};
+/// define the BLE service UUID
+uint8_t HspBLE::envServiceUUID[] = {0x5c,0x6e,0x40,0xe8,0x3b,0x7f,0x42,0x86,0xa5,0x2f,0xda,0xec,0x46,0xab,0xe8,0x51};
+
+HspBLE *HspBLE::instance = NULL;
+
+/**
+* @brief Constructor that inits the BLE helper object
+* @param ble Pointer to the mbed BLE object
+*/
+HspBLE::HspBLE(BLE *ble) {
+  bluetoothLE = new BluetoothLE(ble, NUMBER_OF_CHARACTERISTICS);
+  instance = this;
+  notificationUpdateRoundRobin = 0;
+}
+
+/**
+* @brief Constructor that deletes the bluetoothLE object
+*/
+HspBLE::~HspBLE(void) { delete bluetoothLE; }
+
+/**
+* @brief Initialize all of the HSP characteristics, initialize the ble service
+* and attach callbacks
+*/
+void HspBLE::init(void) {
+  uint8_t *serialNumberPtr;
+  // uint8_t serialNumberBuffer[6];
+  serialNumberPtr = MAX30001_Helper_getVersion();
+  printf("MAX30001 Version = %02X:%02X:%02X:%02X:%02X:%02X...\n",
+         serialNumberPtr[0], serialNumberPtr[1], serialNumberPtr[2],
+         serialNumberPtr[3], serialNumberPtr[4], serialNumberPtr[5]);
+  serialNumberPtr[3] = 0x00;
+  serialNumberPtr[4] = 0x00;
+  serialNumberPtr[5] = 0x03;
+  printf("BLE DeviceID = %02X:%02X:%02X:%02X:%02X:%02X...\n",
+         serialNumberPtr[0], serialNumberPtr[1], serialNumberPtr[2],
+         serialNumberPtr[3], serialNumberPtr[4], serialNumberPtr[5]);
+
+    bluetoothLE->addCharacteristic(new Characteristic(2 /* number of bytes */,temperatureTopCharUUID,GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_READ | GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY));
+    bluetoothLE->addCharacteristic(new Characteristic(2 /* number of bytes */,temperatureBottomCharUUID,GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_READ | GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY));
+    bluetoothLE->addCharacteristic(new Characteristic(6 /* number of bytes */,accelerometerCharUUID,GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_READ | GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY));
+    bluetoothLE->addCharacteristic(new Characteristic(4 /* number of bytes */,heartrateCharUUID,GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_READ | GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY));
+    bluetoothLE->addCharacteristic(new Characteristic(8 /* number of bytes */,pressureCharUUID,GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_READ | GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY));
+    bluetoothLE->addCharacteristic(new Characteristic(32 /* number of bytes */,dataCharUUID,GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_READ | GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_WRITE));
+    bluetoothLE->addCharacteristic(new Characteristic(1 /* number of bytes */,commandCharUUID,GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_READ | GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_WRITE));
+    bluetoothLE->initService(serialNumberPtr, deviceName, sizeof(deviceName),envServiceUUID);
+
+  bluetoothLE->onDataWritten(&HspBLE::_onDataWritten);
+  ticker.attach(this, &HspBLE::tickerHandler, 1);
+}
+
+void HspBLE::_onDataWritten(int index) {
+  HspBLE::instance->onDataWritten(index);
+}
+
+/**
+* @brief Callback for written characteristics
+* @param index Index of whose characteristic is written to
+*/
+void HspBLE::onDataWritten(int index) {
+  int length;
+  uint8_t *data;
+  printf("onDataWritten ");
+  if (index == CHARACTERISTIC_CMD) {
+    data = bluetoothLE->getDataWritten(index, &length);
+    if (length >= 1) {
+        	if (data[0] == 0x00) startDataLogging = false;
+        	if (data[0] == 0x01) startDataLogging = true;
+        	printf("onDataWritten index %d, data %02X, length %d ",index,data[0],length); fflush(stdout);
+
+    }
+  }
+}
+
+void HspBLE::pollSensor(int sensorId, uint8_t *data) {
+
+  switch (sensorId) {
+  case CHARACTERISTIC_TEMP_TOP: {
+    uint16_t uShort;
+    Peripherals::max30205_top()->readTemperature(&uShort);
+    data[0] = HIGH_BYTE(uShort);
+    data[1] = LOW_BYTE(uShort);
+  } break;
+  case CHARACTERISTIC_TEMP_BOTTOM: {
+    uint16_t uShort;
+    Peripherals::max30205_bottom()->readTemperature(&uShort);
+    data[0] = HIGH_BYTE(uShort);
+    data[1] = LOW_BYTE(uShort);
+  } break;
+  case CHARACTERISTIC_ACCELEROMETER: {
+    int i;
+    uint8_t *bytePtr;
+    int16_t acclPtr[3];
+    Peripherals::lis2dh()->get_motion_cached(&acclPtr[0], &acclPtr[1],
+                                             &acclPtr[2]);
+    bytePtr = reinterpret_cast<uint8_t *>(&acclPtr);
+    for (i = 0; i < sizeof(acclPtr); i++)
+      data[i] = bytePtr[i];
+  } break;
+  case CHARACTERISTIC_PRESSURE: {
+    int i;
+    uint8_t *bytePtr;
+    float temperature;
+    float pressure;
+    Peripherals::bmp280()->ReadCompData(&temperature, &pressure);
+    bytePtr = reinterpret_cast<uint8_t *>(&temperature);
+    for (i = 0; i < sizeof(float); i++)
+      data[i] = bytePtr[i];
+    bytePtr = reinterpret_cast<uint8_t *>(&pressure);
+    for (i = 0; i < sizeof(float); i++)
+      data[i + sizeof(float)] = bytePtr[i];
+  } break;
+  case CHARACTERISTIC_HEARTRATE: {
+    int i;
+    uint8_t *bytePtr;
+    MAX30001::max30001_t heartrateData;
+    Peripherals::max30001()->max30001_ReadHeartrateData(&heartrateData);
+    bytePtr = reinterpret_cast<uint8_t *>(&heartrateData);
+    for (i = 0; i < sizeof(MAX30001::max30001_t); i++)
+      data[i] = bytePtr[i];
+  } break;
+  }
+}
+
+bool HspBLE::getStartDataLogging(void) { return startDataLogging; }
+
+/**
+* @brief Timer Callback that updates all sensor characteristic notifications
+*/
+void HspBLE::tickerHandler(void) {
+  uint8_t data[8];
+  if (bluetoothLE->isConnected()) {
+    pollSensor(CHARACTERISTIC_TEMP_TOP, data);
+    bluetoothLE->notifyCharacteristic(CHARACTERISTIC_TEMP_TOP, data);
+    pollSensor(CHARACTERISTIC_TEMP_BOTTOM, data);
+    bluetoothLE->notifyCharacteristic(CHARACTERISTIC_TEMP_BOTTOM, data);
+    pollSensor(CHARACTERISTIC_ACCELEROMETER, data);
+    bluetoothLE->notifyCharacteristic(CHARACTERISTIC_ACCELEROMETER, data);
+    pollSensor(CHARACTERISTIC_HEARTRATE, data);
+    bluetoothLE->notifyCharacteristic(CHARACTERISTIC_HEARTRATE, data);
+    pollSensor(CHARACTERISTIC_PRESSURE, data);
+    bluetoothLE->notifyCharacteristic(CHARACTERISTIC_PRESSURE, data);
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/e4a10ed6eb92/HSP/Hsp_BLE/HspBLE.h	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,92 @@
+/*******************************************************************************
+ * Copyright (C) 2016 Maxim Integrated Products, Inc., All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+ * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Except as contained in this notice, the name of Maxim Integrated
+ * Products, Inc. shall not be used except as stated in the Maxim Integrated
+ * Products, Inc. Branding Policy.
+ *
+ * The mere transfer of this software does not imply any licenses
+ * of trade secrets, proprietary technology, copyrights, patents,
+ * trademarks, maskwork rights, or any other form of intellectual
+ * property whatsoever. Maxim Integrated Products, Inc. retains all
+ * ownership rights.
+ *******************************************************************************
+ */
+#ifndef _HSPBLE_H_
+#define _HSPBLE_H_
+
+#include "mbed.h"
+#include "BluetoothLE.h"
+
+/// define the number of characteristics used on the HSP platform
+#define NUMBER_OF_CHARACTERISTICS (7)
+
+/// indicies of the characteristics used
+#define CHARACTERISTIC_TEMP_TOP (0)
+#define CHARACTERISTIC_TEMP_BOTTOM (1)
+#define CHARACTERISTIC_ACCELEROMETER (2)
+#define CHARACTERISTIC_HEARTRATE (3)
+#define CHARACTERISTIC_PRESSURE (4)
+#define CHARACTERISTIC_DATA (5)
+#define CHARACTERISTIC_CMD (6)
+
+class HspBLE {
+public:
+  HspBLE(BLE *ble);
+  ~HspBLE(void);
+  void init(void);
+  static void _onDataWritten(int index);
+  void onDataWritten(int index);
+  void updateNotification(int index);
+  void pollSensor(int sensorId, uint8_t *data);
+  bool getStartDataLogging(void);
+  static HspBLE *instance;
+
+private:
+  void tickerHandler(void);
+  void testPattern(uint8_t *data, int length, bool clear);
+
+  /// pointer to the helper BLE object
+  BluetoothLE *bluetoothLE;
+  /// ticker that is used to periodically update the characteristic
+  /// notifications
+  Ticker ticker;
+
+  /// value that controls the notifications to be sent in a round robin fashion
+  int notificationUpdateRoundRobin;
+
+  /// charateristic UUIDs statically defined
+  static uint8_t temperatureTopCharUUID[];
+  static uint8_t temperatureBottomCharUUID[];
+  static uint8_t accelerometerCharUUID[];
+  static uint8_t heartrateCharUUID[];
+  static uint8_t pressureCharUUID[];
+  static uint8_t dataCharUUID[];
+  static uint8_t commandCharUUID[];
+  static uint8_t envServiceUUID[];
+  static uint8_t deviceName[];
+  static uint8_t serialNumber[];
+
+  /// application specific
+  bool startDataLogging;
+};
+
+#endif // _HSPBLE_H_
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/e4a10ed6eb92/HSP/Interfaces/I2C_RPC.cpp	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,85 @@
+/*******************************************************************************
+ * Copyright (C) 2016 Maxim Integrated Products, Inc., All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+ * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Except as contained in this notice, the name of Maxim Integrated
+ * Products, Inc. shall not be used except as stated in the Maxim Integrated
+ * Products, Inc. Branding Policy.
+ *
+ * The mere transfer of this software does not imply any licenses
+ * of trade secrets, proprietary technology, copyrights, patents,
+ * trademarks, maskwork rights, or any other form of intellectual
+ * property whatsoever. Maxim Integrated Products, Inc. retains all
+ * ownership rights.
+ *******************************************************************************
+ */
+#include <stdint.h>
+#include "StringHelper.h"
+#include "I2C_RPC.h"
+#include "Peripherals.h"
+
+//******************************************************************************
+// input
+// [instance] [slaveAddress] [writeNumber] [](data to write) [readNumber]
+// output data to read
+int I2C_WriteRead(char argStrs[32][32], char replyStrs[32][32]) {
+  uint8_t args[16];
+  uint8_t reply[16];
+  uint8_t writeNumber;
+  uint8_t readNumber;
+  uint8_t instance;
+  uint8_t slaveAddress;
+  int ret1;
+  int ret2;
+  I2C *i2c;
+  // get the number of bytes to write
+  ProcessArgs(argStrs, args, 3); // parse [instance] [slaveAddress] [writeNumber]
+  instance = args[0];
+  slaveAddress = args[1];
+  writeNumber = args[2];
+  // parse [instance] [slaveAddress] [writeNumber] [](data to write)
+  // [readNumber]
+  ProcessArgs(argStrs, args, writeNumber + 4);
+  readNumber = args[writeNumber + 3];
+
+  if (instance == 1) {
+    i2c = Peripherals::i2c1();
+  }
+  if (instance == 2) {
+    i2c = Peripherals::i2c2();
+  }
+  ret1 = 0;
+  ret2 = 0;
+
+  if (writeNumber != 0) {
+    ret1 = i2c->write((int)slaveAddress, (char *)&args[3], (int)writeNumber);
+  }
+  if (readNumber != 0) {
+    ret2 = i2c->read((int)slaveAddress, (char *)reply, (int)readNumber);
+  }
+
+	if (ret1 != 0) reply[0] = 0xFF;
+	if (ret2 != 0) reply[0] = 0xFF;
+
+
+  // reply[0] = 0x80;
+  FormatReply(reply, readNumber, replyStrs);
+  return 0;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/e4a10ed6eb92/HSP/Interfaces/I2C_RPC.h	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,43 @@
+/*******************************************************************************
+ * Copyright (C) 2016 Maxim Integrated Products, Inc., All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+ * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Except as contained in this notice, the name of Maxim Integrated
+ * Products, Inc. shall not be used except as stated in the Maxim Integrated
+ * Products, Inc. Branding Policy.
+ *
+ * The mere transfer of this software does not imply any licenses
+ * of trade secrets, proprietary technology, copyrights, patents,
+ * trademarks, maskwork rights, or any other form of intellectual
+ * property whatsoever. Maxim Integrated Products, Inc. retains all
+ * ownership rights.
+ *******************************************************************************
+ */
+#ifndef _I2C_RPC_H_
+#define _I2C_RPC_H_
+
+#include "mbed.h"
+
+int I2C_Init(char argStrs[32][32], char replyStrs[32][32]);
+int I2C_Write(char argStrs[32][32], char replyStrs[32][32]);
+int I2C_Read(char argStrs[32][32], char replyStrs[32][32]);
+int I2C_WriteRead(char argStrs[32][32], char replyStrs[32][32]);
+
+#endif /* _I2C_RPC_H_ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/e4a10ed6eb92/HSP/Interfaces/QuadSpiInterface.cpp	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,107 @@
+/*******************************************************************************
+ * Copyright (C) 2016 Maxim Integrated Products, Inc., All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+ * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Except as contained in this notice, the name of Maxim Integrated
+ * Products, Inc. shall not be used except as stated in the Maxim Integrated
+ * Products, Inc. Branding Policy.
+ *
+ * The mere transfer of this software does not imply any licenses
+ * of trade secrets, proprietary technology, copyrights, patents,
+ * trademarks, maskwork rights, or any other form of intellectual
+ * property whatsoever. Maxim Integrated Products, Inc. retains all
+ * ownership rights.
+ *******************************************************************************
+ */
+#include "QuadSpiInterface.h"
+
+/**
+* @brief Constructor that accepts pin names for the QUAD SPI interface
+* @param mosi master out slave in pin name
+* @param miso master in slave out pin name
+* @param sclk serial clock pin name
+* @param cs chip select pin name
+*/
+QuadSpiInterface::QuadSpiInterface(PinName mosi, PinName miso, PinName sclk,
+                                   PinName cs)
+    : spi(mosi, miso, sclk), csPin(cs) {
+
+    }
+
+/**
+* @brief Transmit and recieve QUAD SPI data
+* @param tx_buf pointer to transmit byte buffer
+* @param tx_size number of bytes to transmit
+* @param rx_buf pointer to the recieve buffer
+* @param rx_size number of bytes to recieve
+* @param last flag to indicate if this is the last QUAD SPI transaction for the
+* current chip select cycle
+*/
+int QuadSpiInterface::SPI_Transmit(const uint8_t *tx_buf, uint32_t tx_size,
+                                   uint8_t *rx_buf, uint32_t rx_size,
+                                   int last) {
+  uint32_t i;
+  int result = 0;
+  int index = 0;
+  // lower chip select
+  csPin = 0;
+  // write bytes out QUAD SPI
+  spi.setQuadMode();
+  for (i = 0; i < tx_size; i++) {
+    rx_buf[index] = spi.write((int)tx_buf[i]);
+    index++;
+  }
+  // read in bytes from QUAD SPI
+  for (i = 0; i < rx_size; i++) {
+    rx_buf[index] = (uint8_t)spi.read();
+    index++;
+  }
+  // raise chip select if this is the last transaction
+    if (last) csPin = 1;
+  return result;
+}
+
+/**
+* @brief Transmit and recieve QUAD SPI data
+* @param tx_buf pointer to transmit byte buffer
+* @param tx_size number of bytes to transmit
+* @param rx_buf pointer to the recieve buffer
+* @param rx_size number of bytes to recieve
+* @param last flag to indicate if this is the last QUAD SPI transaction for the
+* current chip select cycle
+*/
+int QuadSpiInterface::SPI_Transmit4Wire(const uint8_t *tx_buf, uint32_t tx_size,
+                                        uint8_t *rx_buf, uint32_t rx_size,
+                                        int last) {
+  uint32_t i;
+  int result = 0;
+  int index = 0;
+  // lower chip select
+  csPin = 0;
+  // write bytes out Single SPI
+  spi.setSingleMode();
+  for (i = 0; i < tx_size; i++) {
+    rx_buf[index] = spi.write((int)tx_buf[i]);
+    index++;
+  }
+  // raise chip select if this is the last transaction
+    if (last) csPin = 1;
+  return result;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/e4a10ed6eb92/HSP/Interfaces/QuadSpiInterface.h	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,80 @@
+/*******************************************************************************
+ * Copyright (C) 2016 Maxim Integrated Products, Inc., All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+ * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Except as contained in this notice, the name of Maxim Integrated
+ * Products, Inc. shall not be used except as stated in the Maxim Integrated
+ * Products, Inc. Branding Policy.
+ *
+ * The mere transfer of this software does not imply any licenses
+ * of trade secrets, proprietary technology, copyrights, patents,
+ * trademarks, maskwork rights, or any other form of intellectual
+ * property whatsoever. Maxim Integrated Products, Inc. retains all
+ * ownership rights.
+ *******************************************************************************
+ */
+#ifndef _QUADSPIINTERFACE_H_
+#define _QUADSPIINTERFACE_H_
+
+#include "mbed.h"
+#include "QuadSpi.h"
+
+class QuadSpiInterface {
+public:
+  /**
+  * @brief Constructor that accepts pin names for the QUAD SPI interface
+  * @param mosi master out slave in pin name
+  * @param miso master in slave out pin name
+  * @param sclk serial clock pin name
+  * @param cs chip select pin name
+  */
+  QuadSpiInterface(PinName mosi, PinName miso, PinName sclk, PinName cs);
+  /**
+  * @brief Transmit and recieve QUAD SPI data
+  * @param tx_buf pointer to transmit byte buffer
+  * @param tx_size number of bytes to transmit
+  * @param rx_buf pointer to the recieve buffer
+  * @param rx_size number of bytes to recieve
+  * @param last flag to indicate if this is the last QUAD SPI transaction for
+  * the current chip select cycle
+  */
+  int SPI_Transmit(const uint8_t *tx_buf, uint32_t tx_size, uint8_t *rx_buf,
+                   uint32_t rx_size, int last = 1);
+
+  /**
+  * @brief Transmit and recieve Four Wrire SPI data
+  * @param tx_buf pointer to transmit byte buffer
+  * @param tx_size number of bytes to transmit
+  * @param rx_buf pointer to the recieve buffer
+  * @param rx_size number of bytes to recieve
+  * @param last flag to indicate if this is the last QUAD SPI transaction for
+  * the current chip select cycle
+  */
+  int SPI_Transmit4Wire(const uint8_t *tx_buf, uint32_t tx_size,
+                        uint8_t *rx_buf, uint32_t rx_size, int last = 1);
+
+private:
+  // QUAD SPI object
+  QuadSPI spi;
+  // chip select object
+  DigitalOut csPin;
+};
+
+#endif // _QUADSPIINTERFACE_H_
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/e4a10ed6eb92/HSP/LoggingService/DataLoggingService.cpp	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,567 @@
+/*******************************************************************************
+ * Copyright (C) 2016 Maxim Integrated Products, Inc., All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+ * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Except as contained in this notice, the name of Maxim Integrated
+ * Products, Inc. shall not be used except as stated in the Maxim Integrated
+ * Products, Inc. Branding Policy.
+ *
+ * The mere transfer of this software does not imply any licenses
+ * of trade secrets, proprietary technology, copyrights, patents,
+ * trademarks, maskwork rights, or any other form of intellectual
+ * property whatsoever. Maxim Integrated Products, Inc. retains all
+ * ownership rights.
+ *******************************************************************************
+ */
+#include "mbed.h"
+#include "Logging.h"
+#include "Streaming.h"
+#include "RpcServer.h"
+#include "S25FS512.h"
+#include "BMP280.h"
+#include "PacketFifo.h"
+#include "DataLoggingService.h"
+#include "ServiceNonInterrupt.h"
+#include "HspLed.h"
+#include "MAX30001_helper.h"
+#include "MAX30101_helper.h"
+#include "StringInOut.h"
+#include "StringHelper.h"
+#include "Peripherals.h"
+#include "Device_Logging.h"
+
+/// BMP280 logging object reference
+extern Device_Logging *bmp280_Logging;
+/// MAX14720 instance 0 logging object reference
+extern Device_Logging *MAX30205_0_Logging;
+/// MAX14720 instance 1 logging object reference
+extern Device_Logging *MAX30205_1_Logging;
+
+#define PING_PONG_BUFFER_SIZE 512
+#define HALF_OF_PING_PONG_BUFFER_SIZE PING_PONG_BUFFER_SIZE / 2
+#define MISSION_DEFINITION_SIZE 4096
+
+eLoggingTrigger loggingTrigger;
+
+/// buffer where mission strings are stored
+char loggingMissionCmds[MISSION_DEFINITION_SIZE];
+/// This houses two 256 byte ram concatenated to act as a ping-pong
+uint8_t PingPong_SRAM[PING_PONG_BUFFER_SIZE];
+uint32_t buttonTrigger = 0;
+
+eLoggingOutput loggingOutput;
+// extern int bleStartCommand;
+bool volatile globalFlag;
+extern int highDataRate;
+static uint32_t currentPage;
+static uint32_t sramIndex;
+/// flag to indicate that sram buffer 0 is dirty and will need to be flushed
+static uint32_t sram_buffer_0_dirty;
+/// flag to indicate that sram buffer 1 is dirty and will need to be flushed
+static uint32_t sram_buffer_1_dirty;
+/// usb byte buffer for sending out a bulk transfer
+static uint8_t usb_block[64];
+/// running index used to accumulate bytes to send as a block via bulk transfer
+static uint16_t usb_block_index = 0;
+
+typedef enum {
+  eStartEvent_NULL,
+  eStartEvent_BLE,
+  eStartEvent_BUTTON,
+  eStartEvent_RPC_TO_USB,
+  eStartEvent_RPC_TO_FLASH
+} eStartEvent;
+static eStartEvent startEvent;
+
+/**
+* @brief Sets a flag to start USB logging (streaming)
+*/
+void LoggingService_StartLoggingUsb(void) {
+  loggingTrigger = eTriggerLog_RPC_USB;
+}
+
+/**
+* @brief Sets a flag to start flash logging
+*/
+void LoggingService_StartLoggingFlash(void) {
+  loggingTrigger = eTriggerLog_RPC_FLASH;
+}
+
+/**
+* @brief Checks the various logging start condition
+* @return 1 if a start condition is true, 0 if there is no start condition
+*/
+static bool _LoggingService_CheckStartCondition(void) {
+  bool buttonPressed;
+  buttonPressed = Peripherals::pushButton()->GetButtonFallState();
+
+  // default not logging USB or flash
+  loggingOutput = eLogToNothing;
+  startEvent = eStartEvent_NULL;
+  if (buttonPressed) {
+    Peripherals::pushButton()->clearButtonFallState();
+    // a falling state has been detected... wait for a fraction of a second and
+    // re-read the pin
+    //   only start datalogging if the pin was released within this wait time
+    wait(0.75f);
+    int buttonRead = Peripherals::pushButton()->Read();
+    // if after a period of time the button is still pressed then get out
+    if (buttonRead == 0)
+      return 0;
+    buttonTrigger = 0;
+
+    loggingTrigger = eTriggerLog_BUTTON;
+    loggingOutput = eLogToFlash;
+    startEvent = eStartEvent_BUTTON;
+    return true;
+  }
+  if (loggingTrigger == eTriggerLog_RPC_FLASH) {
+    loggingOutput = eLogToFlash;
+    startEvent = eStartEvent_RPC_TO_FLASH;
+    return true;
+  }
+  if (Peripherals::hspBLE()->getStartDataLogging()) {
+    loggingTrigger = eTriggerLog_BLE;
+    loggingOutput = eLogToFlash;
+    startEvent = eStartEvent_BLE;
+    return true;
+  }
+  // check if start is from RPC call for USB streaming
+  if (loggingTrigger == eTriggerLog_RPC_USB) {
+    loggingOutput = eLogtoUsb;
+    startEvent = eStartEvent_RPC_TO_USB;
+    return true;
+  }
+  return false;
+}
+
+/**
+* @brief Read the mission string from flash into a buffer
+* @return false if a mission was not defined, true if mission was read and
+* buffered
+*/
+static bool _LoggingService_ReadMissionFromFlash(void) {
+  // get mission from flash
+  Logging_ReadMissionFromFlash((uint8_t *)loggingMissionCmds);
+  if (Logging_IsMissionDefined((uint8_t *)loggingMissionCmds) == 0) {
+    return false;
+  }
+  printf(loggingMissionCmds);
+  fflush(stdout);
+  RPC_ProcessCmds(loggingMissionCmds);
+  return true;
+}
+
+/**
+* @brief Process a RPC command that is pointed to.
+* @param cmd RPC string to process
+*/
+void ProcessCmd(char *cmd) {
+  char cmd_[256];
+  char reply[512];
+  strcpy(cmd_, cmd);
+  RPC_call(cmd_, reply);
+}
+
+/**
+* @brief Buffer sensor fifo data in ram buffers, when a ram buffer is full (a
+* flash page worth of data is accumulated) then flash that buffer.
+*        A buffer ping pong method is used so that one buffer can be flashing as
+* the other buffer fills with sensor fifo data.
+* @param fifoData Sensor data taken from the fifo to be stored into flash
+*/
+static void _LoggingServer_OutputToFlash(uint32_t fifoData) {
+  uint32_t index;
+  char str[128];
+  uint8_t *ptr;
+  //
+  // Log To Flash
+  //
+  // i.e. there is data, read one 32-bit size data at a time.
+  // put the fifo data into the ping-pong SRAM
+  PingPong_SRAM[sramIndex++] = fifoData & 0xFF; // LSByte goes into index N
+  PingPong_SRAM[sramIndex++] = (fifoData >> 8) & 0xFF;
+  PingPong_SRAM[sramIndex++] = (fifoData >> 16) & 0xFF;
+  PingPong_SRAM[sramIndex++] = (fifoData >> 24) & 0xFF; // MSByte goes into index N+3
+
+  // flag this buffer as dirty
+  if (sramIndex <= 256)
+    sram_buffer_0_dirty = 1;
+  else
+    sram_buffer_1_dirty = 1;
+
+  if (sramIndex == 256 ||
+      sramIndex == 512) // Either Ping SRAM or Pong SRAM location is full
+  {                     // therefore write to Flash
+
+    index = sramIndex - 256;
+    ptr = &PingPong_SRAM[index];
+    sprintf(str, "currentPage=%d", currentPage);
+    Peripherals::s25FS512()->writePage_Helper(currentPage, ptr, 0);
+
+    // this page is no longer dirty
+    if (index == 0)
+      sram_buffer_0_dirty = 0;
+    if (index == 256)
+      sram_buffer_1_dirty = 0;
+
+    currentPage++;
+  }
+  sramIndex = sramIndex % 512; // Wrap around the index
+}
+
+/**
+* @brief If flash ram buffers are flagged as dirty, flush to flash
+*/
+static void _LoggingServer_WriteDirtySramBufferToFlash(void) {
+  uint8_t *ptr = PingPong_SRAM;
+  if (sram_buffer_0_dirty == 0 && sram_buffer_1_dirty == 0)
+    return;
+  if (sram_buffer_0_dirty == 1) {
+    ptr += 0;
+  }
+  if (sram_buffer_1_dirty == 1) {
+    ptr += 256;
+  }
+  printf("_LoggingServer_WriteDirtySramBufferToFlash:%d,%d\n",
+         sram_buffer_0_dirty, sram_buffer_1_dirty);
+  fflush(stdout);
+  // s25fs512_WritePage_Helper(currentPage, ptr, 0);
+  Peripherals::s25FS512()->writePage_Helper(currentPage, ptr, 0);
+}
+
+/**
+* @brief Initialize the USB block running index
+* @param fifoData Sensor data taken from the fifo to be sent out USB
+*/
+static void _LoggingServer_OutputToCdcAcm(uint32_t fifoData) {
+  uint8_t *ptr;
+  uint8_t str[16];
+  sprintf((char *)str, "%X ", fifoData);
+  ptr = str;
+  usb_block_index = 0;
+  while (*ptr != 0) {
+    usb_block[usb_block_index] = *ptr;
+    ptr++;
+    usb_block_index++;
+  }
+  Peripherals::usbSerial()->writeBlock(usb_block, usb_block_index);
+}
+
+/**
+* @brief Initialize the USB block running index
+*/
+static void _LoggingServer_OutputToCdcAcm_Start(void) { usb_block_index = 0; }
+
+/**
+* @brief Buffer up fifoData from sensors, do a USB block transfer if buffer is
+* full
+* @param fifoData Sensor data taken from the fifo to be send out USB within a
+* bulk block transfer
+* @return Return the success status of the writeblock operation
+*/
+static bool _LoggingServer_OutputToCdcAcm_Block(uint32_t fifoData) {
+  uint8_t str[64];
+  uint8_t *ptr;
+  bool result;
+  //
+  // Log to CDCACM
+  //
+  result = true;
+  sprintf((char *)str, "%X ", fifoData);
+  ptr = str;
+  while (*ptr != 0) {
+    usb_block[usb_block_index] = *ptr;
+    ptr++;
+    usb_block_index++;
+    if (usb_block_index >= 64) {
+      result = Peripherals::usbSerial()->writeBlock(usb_block, 64);
+      usb_block_index = 0;
+    }
+  }
+  return result;
+}
+
+/**
+* @brief Output a full USB block via bulk transfer
+*/
+static void _LoggingServer_OutputToCdcAcm_End(void) {
+  if (usb_block_index == 0)
+    return;
+  Peripherals::usbSerial()->writeBlock(usb_block, usb_block_index - 1);
+}
+
+/**
+* @brief Blink LED pattern that indicates that the flash end boundary has been
+* reached
+*/
+static void BlinkEndOfDatalogging(void) {
+  // blink to signal end of logging
+  Peripherals::hspLed()->pattern(0x55555555, 20);
+  wait(2);
+}
+
+/**
+* @brief Reads the first data page of flash, if all FF's then the page is empty
+* @return 1 if the flash is empty as indicated by the first data page of the
+* flash, 0 if not
+*/
+int isFlashEmpty(void) {
+  int i;
+  uint8_t data[256];
+  int firstDataPage = Logging_GetLoggingStartPage();
+  Peripherals::s25FS512()->readPages_Helper(firstDataPage, firstDataPage, data, 0);
+  for (i = 0; i < 256; i++) {
+    if (data[i] != 0xFF)
+      return 0;
+  }
+  return 1;
+}
+
+/**
+* @brief Blink LED pattern that indicates that the flash is not empty and a new
+* flash logging session can not occur
+*/
+void BlinkFlashNotEmpty(void) {
+  Peripherals::hspLed()->pattern(0x55555555, 20);
+  wait(1);
+}
+
+void ExecuteDefaultMission(void) {
+  ProcessCmd("/MAX30001/CAL_InitStart 01 01 01 03 7FF 00");
+  ProcessCmd("/MAX30001/ECG_InitStart 01 01 01 00 02 03 1F 0 00 00 01");
+  ProcessCmd("/MAX30001/RtoR_InitStart 01 03 0F 00 03 01 00 00 01");
+  ProcessCmd("/MAX30001/Rbias_FMSTR_Init 01 02 01 01 00");
+  ProcessCmd("/LIS2DH/InitStart 02 01");
+}
+
+void LoggingService_Init(void) { loggingTrigger = eTriggerLog_NULL; }
+
+/**
+* @brief This routine checks to see if a USB or flash logging action needs to be taken
+*           The routine checks for a start condition via button press, USB command, or BLE command 
+*           Once one of these start conditions is present, the logging begins until stopped or memory is full
+* @return 1 if successful, 0 if error or logging was aborted and no logging occurred
+*/
+uint8_t LoggingService_ServiceRoutine(void) {
+  uint32_t fifoData;
+  uint32_t endPage;
+  USBSerial *usbSerial = Peripherals::usbSerial();
+  // BMP280 *bmp280 = Peripherals::bmp280();
+  bool buttonPressed;
+  int packetBurstCount = 0;
+  HspLed *hspLed = Peripherals::hspLed();
+
+  sramIndex = 0;
+  // only start logging if conditions exist
+
+	if (_LoggingService_CheckStartCondition() == false) return 0;
+	printf("Begin Logging...");
+	if (startEvent == eStartEvent_NULL) printf("eStartEvent_NULL..."); 
+	if (startEvent == eStartEvent_BLE) printf("eStartEvent_BLE..."); 
+	if (startEvent == eStartEvent_BUTTON) printf("eStartEvent_BUTTON..."); 
+	if (startEvent == eStartEvent_RPC_TO_USB) printf("eStartEvent_RPC_TO_USB..."); 
+	if (startEvent == eStartEvent_RPC_TO_FLASH) printf("eStartEvent_RPC_TO_FLASH..."); 
+	fflush(stdout);
+
+  // start logging stuttered blink pattern
+  hspLed->pattern(0xA0F3813, 20);
+
+  if (startEvent == eStartEvent_RPC_TO_FLASH ||
+      startEvent == eStartEvent_BUTTON) {
+    // check to see if datalog already in flash... abort and force user to erase
+    // flash if needed
+    if (loggingOutput == eLogToFlash) {
+      if (isFlashEmpty() == 0) {
+        Logging_SetStart(false);
+        // bleStartCommand = 0x00;
+        BlinkFlashNotEmpty();
+        hspLed->blink(1000);
+        printf("Abort Logging, flash log exists. ");
+        fflush(stdout);
+        return 0;
+      }
+    }
+  }
+
+  if (startEvent == eStartEvent_BLE) {
+    // check for mission in flash
+    if (_LoggingService_ReadMissionFromFlash() == false) {
+      // if there is no mission in flash then do a default mission for the sake
+      // of ble Android app working "out-of-the-box" and stream RtoR and Accel
+      printf("No Mission in Flash...ExecuteDefaultMission...");
+      fflush(stdout);
+      ExecuteDefaultMission();
+      // do not log this data
+      loggingOutput = eLogToNothing;
+    } else {
+      // there is a mission in flash check if there is already logged data
+      if (isFlashEmpty() == 0) {
+        // just do default mission
+        printf("Logged Data Detected...ExecuteDefaultMission...");
+        fflush(stdout);
+        ExecuteDefaultMission();
+        // do not log this data
+        loggingOutput = eLogToNothing;
+      } else {
+        // flag that we are logging to flash
+        loggingOutput = eLogToFlash;
+      }
+    }
+  }
+
+  // if we are logging to flash then read mission in flash
+  if (loggingOutput == eLogToFlash) {
+    if (_LoggingService_ReadMissionFromFlash() ==
+        false) { // if there is no mission in flash then get out
+      Logging_SetStart(false);
+      Peripherals::hspLed()->pattern(0xC3C3C3C3, 20);
+      wait(2);
+      printf("Abort Logging, Mission does not exist. ");
+      fflush(stdout);
+      return 0;
+    }
+    currentPage = Logging_GetLoggingStartPage();
+    endPage = Logging_GetLoggingEndPage();
+  }
+
+  MAX30001_Helper_SetupInterrupts();
+  if (MAX30001_AnyStreamingSet() == 1) {
+    MAX30001_Helper_StartSync();
+  }
+
+  SetDataLoggingStream(TRUE);
+  ServiceNonInterrupt_Init();
+  ServiceNonInterrupt_StartTimer();
+
+  while (usbSerial->readable()) {
+    usbSerial->_getc();
+  }
+  fifo_clear(GetUSBIncomingFifo()); // clear USB serial incoming fifo
+  fifo_clear(GetStreamOutFifo());
+
+  sram_buffer_0_dirty = 0;
+  sram_buffer_1_dirty = 0;
+
+
+	if (loggingOutput == eLogToNothing) printf("eLogToNothing..."); fflush(stdout);
+	if (loggingOutput == eLogToFlash) printf("eLogToFlash..."); fflush(stdout);
+	if (loggingOutput == eLogtoUsb) printf("eLogtoUsb..."); fflush(stdout);
+	printf("highDataRate=%d...",highDataRate); fflush(stdout);
+
+
+  Peripherals::timestampTimer()->reset();
+  Peripherals::timestampTimer()->start();
+
+  _LoggingServer_OutputToCdcAcm_Start();
+  while (1) {
+    if (loggingOutput == eLogToFlash) {
+      // check if we are at the end of flash
+      if (currentPage >= endPage) {
+        BlinkEndOfDatalogging(); // blink for 3 seconds to signal end of logging
+        break;
+      }
+    }
+
+    if (startEvent == eStartEvent_BUTTON) {
+      buttonPressed = Peripherals::pushButton()->GetButtonFallState();
+      if (buttonPressed) {
+        Peripherals::pushButton()->clearButtonFallState();
+        // if there is a dirty sram buffer... flush it to flash
+        _LoggingServer_WriteDirtySramBufferToFlash();
+        BlinkEndOfDatalogging(); // blink for 3 seconds to signal end of logging
+        break;
+      }
+    }
+
+    if (loggingTrigger == eTriggerLog_BLE) {
+      if (Peripherals::hspBLE()->getStartDataLogging() == false) {
+        // if there is a dirty sram buffer... flush it to flash
+        _LoggingServer_WriteDirtySramBufferToFlash();
+        BlinkEndOfDatalogging(); // blink for 3 seconds to signal end of logging
+        break;
+      }
+    }
+
+    if (startEvent == eStartEvent_RPC_TO_USB ||
+        startEvent == eStartEvent_RPC_TO_FLASH) {
+      if (usbSerial->available()) {
+        if (loggingOutput == eLogToFlash) {
+          _LoggingServer_WriteDirtySramBufferToFlash();
+        }
+        wait(0.2f);
+        while (usbSerial->available()) {
+          usbSerial->_getc();
+        }
+        fifo_clear(GetUSBIncomingFifo()); // clear USB serial incoming fifo
+        fifo_clear(GetStreamOutFifo());
+        break;
+      }
+    }
+
+    // check to see if data is available
+    packetBurstCount = 0;
+    while (PacketFifo_Empty() == 0) {
+      if (packetBurstCount >= 100)
+        break;
+      fifoData = PacketFifo_GetUint32();
+      if (loggingOutput == eLogToFlash) {
+        _LoggingServer_OutputToFlash(fifoData);
+      }
+      if (loggingOutput == eLogtoUsb) {
+        if (highDataRate == 0)
+          _LoggingServer_OutputToCdcAcm(fifoData);
+        else
+          _LoggingServer_OutputToCdcAcm_Block(fifoData);
+      }
+      packetBurstCount++;
+    }
+
+    if (PacketFifo_Empty() != 0) {
+      Peripherals::ble()->waitForEvent();
+    }
+    ServiceNonInterrupt_BMP280(bmp280_Logging);
+    ServiceNonInterrupt_MAX30205(MAX30205_0_Logging,
+                                 Peripherals::max30205_top(),
+                                 PACKET_MAX30205_TEMP_TOP);
+    ServiceNonInterrupt_MAX30205(MAX30205_1_Logging,
+                                 Peripherals::max30205_bottom(),
+                                 PACKET_MAX30205_TEMP_BOTTOM);
+  }
+  _LoggingServer_OutputToCdcAcm_End();
+  printf("End Logging.\n");
+  fflush(stdout);
+
+  bmp280_Logging->stop();
+  MAX30205_0_Logging->stop();
+  MAX30205_1_Logging->stop();
+  MAX30001_Helper_Stop(); // if any MAX30001 streams have been started, stop
+                          // them
+  MAX30101_Helper_Stop(); // if any MAX30101 streams have been started, stop
+                          // them
+  Peripherals::lis2dh()->stop();
+  SetDataLoggingStream(FALSE);
+  Peripherals::timestampTimer()->stop();
+  hspLed->blink(1000);
+  // default to non-usb packet speed optimizing
+  highDataRate = 0;
+  loggingTrigger = eTriggerLog_NULL;
+  return 1;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/e4a10ed6eb92/HSP/LoggingService/DataLoggingService.h	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,84 @@
+/*******************************************************************************
+ * Copyright (C) 2016 Maxim Integrated Products, Inc., All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+ * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Except as contained in this notice, the name of Maxim Integrated
+ * Products, Inc. shall not be used except as stated in the Maxim Integrated
+ * Products, Inc. Branding Policy.
+ *
+ * The mere transfer of this software does not imply any licenses
+ * of trade secrets, proprietary technology, copyrights, patents,
+ * trademarks, maskwork rights, or any other form of intellectual
+ * property whatsoever. Maxim Integrated Products, Inc. retains all
+ * ownership rights.
+ *******************************************************************************
+ */
+#ifndef _LOGGINGSERVICE_H_
+#define _LOGGINGSERVICE_H_
+
+#include "mbed.h"
+
+/// types of logging
+typedef enum {
+  /// do not log
+  eLogToNothing,
+  /// log to USB
+  eLogtoUsb,
+  /// Log to external flash memory
+  eLogToFlash
+} eLoggingOutput;
+
+/// types of logging
+typedef enum {
+  eTriggerLog_NULL,
+  eTriggerLog_RPC_USB,
+  eTriggerLog_RPC_FLASH,
+  eTriggerLog_BUTTON,
+  eTriggerLog_BLE,
+} eLoggingTrigger;
+
+/// extern that indicates the hardware button on the HSP was pressed
+extern uint32_t buttonTrigger;
+
+void LoggingService_Init(void);
+
+/**
+* @brief This routine checks to see if a USB or flash logging action needs to be
+* taken
+*           The routine checks for a start condition via button press, USB
+* command, or BLE command
+*           Once one of these start conditions is present, the logging begins
+* until stopped or memory is full
+* @return 1 if successful, 0 if error or logging was aborted and no logging
+* occurred
+*/
+uint8_t LoggingService_ServiceRoutine(void);
+/**
+* @brief This is called via one of the RPC USB functions to set start conditons
+* to start streaming USB
+*/
+void LoggingService_StartLoggingUsb(void);
+/**
+* @brief This is called via one of the RPC USB functions to set start conditons
+* to start logging to flash
+*/
+void LoggingService_StartLoggingFlash(void);
+
+#endif /* _LOGGINGSERVICE_H_ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/e4a10ed6eb92/HSP/LoggingService/Device_Logging.cpp	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,72 @@
+/*******************************************************************************
+ * Copyright (C) 2016 Maxim Integrated Products, Inc., All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+ * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Except as contained in this notice, the name of Maxim Integrated
+ * Products, Inc. shall not be used except as stated in the Maxim Integrated
+ * Products, Inc. Branding Policy.
+ *
+ * The mere transfer of this software does not imply any licenses
+ * of trade secrets, proprietary technology, copyrights, patents,
+ * trademarks, maskwork rights, or any other form of intellectual
+ * property whatsoever. Maxim Integrated Products, Inc. retains all
+ * ownership rights.
+ *******************************************************************************
+ */
+
+#include "Device_Logging.h"
+
+/**
+* @brief Check if logging is enabled for this device
+*/
+int Device_Logging::isLoggingEnabled(void) { return enabled; }
+
+/**
+* @brief Returns the sample rate for the device, rate is in seconds
+*/
+int Device_Logging::getLoggingSampleRate(void) { return sampleRate; }
+
+/**
+* @brief Initialize the sampling rate for the device
+* @param sampleRate Rate to log device output in seconds
+*/
+void Device_Logging::initStart(int sampleRate) {
+  this->sampleRate = sampleRate;
+  enabled = 1;
+}
+
+/**
+* @brief Disables further datalog and streaming sampling for the device
+* @param time Time for next sample in seconds, time is relative to a timer
+*/
+void Device_Logging::stop(void) { enabled = 0; }
+
+/**
+* @brief Gets a value that represents when device needs to be sampled again,
+* used for datalogging and usb streaming
+*/
+int Device_Logging::getNextSampleTime(void) { return nextSampleTime; }
+
+/**
+* @brief Sets a value that represents when device needs to be sampled again,
+* used for datalogging and usb streaming
+* @param time Time for next sample in seconds, time is relative to a timer
+*/
+void Device_Logging::setNextSampleTime(int time) { nextSampleTime = time; }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/e4a10ed6eb92/HSP/LoggingService/Device_Logging.h	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,83 @@
+/*******************************************************************************
+ * Copyright (C) 2016 Maxim Integrated Products, Inc., All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+ * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Except as contained in this notice, the name of Maxim Integrated
+ * Products, Inc. shall not be used except as stated in the Maxim Integrated
+ * Products, Inc. Branding Policy.
+ *
+ * The mere transfer of this software does not imply any licenses
+ * of trade secrets, proprietary technology, copyrights, patents,
+ * trademarks, maskwork rights, or any other form of intellectual
+ * property whatsoever. Maxim Integrated Products, Inc. retains all
+ * ownership rights.
+ *******************************************************************************
+ */
+#ifndef _DEVICE_LOGGING_H_
+#define _DEVICE_LOGGING_H_
+
+#include "mbed.h"
+
+/**
+* @brief  Class that is used to store device logging parameters when logging to
+* flash or streaming usb
+*/
+class Device_Logging {
+public:
+  /**
+  * @brief Check if logging is enabled for this device
+  */
+  int isLoggingEnabled(void);
+  /**
+  * @brief Returns the sample rate for the device, rate is in seconds
+  */
+  int getLoggingSampleRate(void);
+  /**
+  * @brief Initialize the sampling rate for the device
+  * @param sampleRate Rate to log device output in seconds
+  */
+  void initStart(int sampleRate);
+  /**
+  * @brief Gets a value that represents when device needs to be sampled again,
+  * used for datalogging and usb streaming
+  */
+  int getNextSampleTime(void);
+  /**
+  * @brief Sets a value that represents when device needs to be sampled again,
+  * used for datalogging and usb streaming
+  * @param time Time for next sample in seconds, time is relative to a timer
+  */
+  void setNextSampleTime(int time);
+  /**
+  * @brief Disables further datalog and streaming sampling for the device
+  * @param time Time for next sample in seconds, time is relative to a timer
+  */
+  void stop(void);
+
+private:
+  /// The sample rate in seconds
+  int sampleRate;
+  /// If logging is enabled or not
+  int enabled;
+  /// Bookkeeping var to keep track of the next sample time
+  int nextSampleTime;
+};
+
+#endif /* _DEVICE_LOGGING_H_ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/e4a10ed6eb92/HSP/LoggingService/Logging.cpp	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,105 @@
+/*******************************************************************************
+ * Copyright (C) 2016 Maxim Integrated Products, Inc., All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+ * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Except as contained in this notice, the name of Maxim Integrated
+ * Products, Inc. shall not be used except as stated in the Maxim Integrated
+ * Products, Inc. Branding Policy.
+ *
+ * The mere transfer of this software does not imply any licenses
+ * of trade secrets, proprietary technology, copyrights, patents,
+ * trademarks, maskwork rights, or any other form of intellectual
+ * property whatsoever. Maxim Integrated Products, Inc. retains all
+ * ownership rights.
+ *******************************************************************************
+ */
+#include "mbed.h"
+#include "RpcServer.h"
+#include "Logging.h"
+#include "S25FS512.h"
+#include "Peripherals.h"
+
+/// length of flash page as dictated by the device
+#define LENGTH_OF_FLASH_PAGE 256 // length of flash page in bytes
+/// size in bytes of the external flash device on the HSP platform
+#define SIZE_OF_EXTERNAL_FLASH                                                 \
+  (16777216 / 2) // length of external flash in bytes
+/// start page of where the mission is defined
+#define MISSION_DEFINITION_START_PAGE 0x00
+/// end page of the mission
+#define MISSION_DEFINITION_END_PAGE 0x0F
+/// page of where the logging data starts
+#define LOGGING_START_PAGE 0x12
+/// the last logging page
+#define LOGGING_END_PAGE (SIZE_OF_EXTERNAL_FLASH / LENGTH_OF_FLASH_PAGE)
+
+/// static flag to know if logging was started via RPC
+static bool startLoggingViaRpc = false;
+
+/**
+* @brief This will read the mission location and if there is something valid,
+* then run the Logging_ProcessMissionCmds()
+* @param cmdBuffer buffer
+*/
+uint32_t Logging_IsMissionDefined(uint8_t *cmdBuffer) {
+  uint32_t valid = 1;
+  if ((cmdBuffer[0] == 0xFF) || (cmdBuffer[0] == 0x0))
+    valid = 0;
+  return valid;
+}
+
+/**
+* @brief Read the mission from flash and place in buffer
+* @param buffer pointer to byte array that will contain the read results
+*/
+int8_t Logging_ReadMissionFromFlash(uint8_t *buffer) {
+  return Peripherals::s25FS512()->readPages_Helper(
+      MISSION_DEFINITION_START_PAGE, MISSION_DEFINITION_END_PAGE, buffer, 0);
+}
+
+//******************************************************************************
+// return the page where mission is defined, Mission specific
+uint32_t Logging_GetMissionStartPage(void) {
+  return MISSION_DEFINITION_START_PAGE;
+}
+
+//******************************************************************************
+// return the page where the mission definition ends, Mission specific
+uint32_t Logging_GetMissionEndPage(void) { return MISSION_DEFINITION_END_PAGE; }
+
+//******************************************************************************
+// Returns the location where the Writing can start from, for data logging...
+uint32_t Logging_GetLoggingStartPage(void) { return LOGGING_START_PAGE; }
+
+//******************************************************************************
+// Returns the end location available where the Flash ends essentially.... for
+// data logging.
+uint32_t Logging_GetLoggingEndPage(void) { return LOGGING_END_PAGE; }
+
+//******************************************************************************
+void Logging_SetStart(bool state) { startLoggingViaRpc = state; }
+
+//******************************************************************************
+bool Logging_GetStart(void) { return startLoggingViaRpc; }
+
+//******************************************************************************
+// for debugging... always say that usb is not connected... for easy bench
+// testing
+uint32_t Usb_IsConnected(void) { return 0; }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/e4a10ed6eb92/HSP/LoggingService/Logging.h	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,35 @@
+#ifndef _LOGGING_H_
+#define _LOGGING_H_
+
+#include "mbed.h"
+
+/**
+* @brief This will read the mission location and if there is something valid,
+* then run the  Logging_ProcessMissionCmds()
+* @param cmdBuffer buffer
+*/
+uint32_t Logging_IsMissionDefined(uint8_t *cmdBuffer);
+
+int8_t Logging_ReadMissionFromFlash(uint8_t *buffer);
+
+// return the page where mission is defined, Mission specific
+uint32_t Logging_GetMissionStartPage(void);
+
+// return the page where the mission definition ends, Mission specific
+uint32_t Logging_GetMissionEndPage(void);
+
+// Returns the location where the Writing can start from, for data logging...
+uint32_t Logging_GetLoggingStartPage(void);
+
+// Returns the end location available where the Flash ends essentially.... for
+// data logging.
+uint32_t Logging_GetLoggingEndPage(void);
+
+// returns one if the usb is connected, zero if not
+uint32_t Usb_IsConnected(void);
+
+void Logging_SetStart(bool state);
+
+bool Logging_GetStart(void);
+
+#endif /* _LOGGING_H_ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/e4a10ed6eb92/HSP/LoggingService/Logging_RPC.cpp	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,279 @@
+/*******************************************************************************
+ * Copyright (C) 2016 Maxim Integrated Products, Inc., All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+ * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Except as contained in this notice, the name of Maxim Integrated
+ * Products, Inc. shall not be used except as stated in the Maxim Integrated
+ * Products, Inc. Branding Policy.
+ *
+ * The mere transfer of this software does not imply any licenses
+ * of trade secrets, proprietary technology, copyrights, patents,
+ * trademarks, maskwork rights, or any other form of intellectual
+ * property whatsoever. Maxim Integrated Products, Inc. retains all
+ * ownership rights.
+ ******************************************************************************
+ */
+#include "StringHelper.h"
+#include <stdint.h>
+#include "Streaming.h"
+#include "StringInOut.h"
+#include "DataLoggingService.h"
+#include "Peripherals.h"
+#include "Logging.h"
+
+extern char loggingMissionCmds[4096];
+uint32_t missionCmdIndex;
+
+ //******************************************************************************
+ int Logging_RPC_StartMissionDefine(char argStrs[32][32],
+                                   char replyStrs[32][32]) {
+  uint32_t i;
+  uint32_t reply[1];
+
+  // reset the missionCmdIndex to the beginning of the cmd buffer
+  missionCmdIndex = 0;
+  // clear the mission command buffer, fill with zeros
+  for (i = 0; i < sizeof(loggingMissionCmds); i++) {
+    loggingMissionCmds[i] = 0;
+  }
+
+  reply[0] = 0x80;
+  FormatReply32(reply, sizeof(reply) / sizeof(uint32_t), replyStrs);
+  return 0;
+}
+
+//******************************************************************************
+int Logging_RPC_AppendMissionCmd(char argStrs[32][32], char replyStrs[32][32]) {
+  uint32_t reply[1];
+  char *strPtr;
+  uint32_t count = 0;
+  uint8_t result = 0x80;
+  // append the string to the mission cmd log
+  strPtr = argStrs[0];
+  while (*strPtr != 0) {
+    loggingMissionCmds[missionCmdIndex] = *strPtr;
+    missionCmdIndex++;
+    strPtr++;
+    // do not overrun buffer
+    if (missionCmdIndex > (sizeof(loggingMissionCmds) - 2)) {
+      result = 0xFF;
+      break;
+    }
+    count++;
+    // do not read more than max count in incoming string
+    if (count > (32 * 32)) {
+      result = 0xFF;
+      break;
+    }
+  }
+  if (result != 0x80) {
+    reply[0] = 0xFF;
+    FormatReply32(reply, sizeof(reply) / sizeof(uint32_t), replyStrs);
+    return 0;
+  }
+  // add cr/lf to the end of this cmd string
+  loggingMissionCmds[missionCmdIndex++] = 13;
+  loggingMissionCmds[missionCmdIndex++] = 10;
+
+  reply[0] = 0x80;
+  FormatReply32(reply, sizeof(reply) / sizeof(uint32_t), replyStrs);
+  return 0;
+}
+
+//******************************************************************************
+int Logging_RPC_EndMissionDefine(char argStrs[32][32], char replyStrs[32][32]) {
+  uint32_t reply[1];
+  reply[0] = 0x80;
+  FormatReply32(reply, sizeof(reply) / sizeof(uint32_t), replyStrs);
+  return 0;
+}
+
+//******************************************************************************
+int Logging_RPC_WriteMission(char argStrs[32][32], char replyStrs[32][32]) {
+  uint8_t page;
+  char *ptr;
+  uint32_t reply[1];
+
+  Peripherals::s25FS512()->parameterSectorErase_Helper(0x0);
+  ptr = loggingMissionCmds;
+  for (page = 0; page < 16; page++) {
+    Peripherals::s25FS512()->writePage_Helper(page, (uint8_t *)ptr, 0);
+    ptr += 256;
+  }
+
+  reply[0] = 0x80;
+  FormatReply32(reply, sizeof(reply) / sizeof(uint32_t), replyStrs);
+  return 0;
+}
+
+//******************************************************************************
+int Logging_RPC_ReadMission(char argStrs[32][32], char replyStrs[32][32]) {
+  char *ptr;
+  uint32_t i;
+  // read sector 0
+  ptr = loggingMissionCmds;
+  for (i = 0; i < 16; i++) {
+    Peripherals::s25FS512()->readPages_Helper(i, i, (uint8_t *)ptr, 0);
+    ptr += 256;
+  }
+  // strip header by shifting payload left
+  ptr = loggingMissionCmds;
+  for (i = 0; i < sizeof(loggingMissionCmds); i++) {
+    if (*ptr == 13) {
+      *ptr = ':';
+    } else if (*ptr == 10) {
+      *ptr = ' ';
+    } 
+    ptr++;
+  }
+  if (loggingMissionCmds[0] == 0xFF || loggingMissionCmds[0] == 0x0) {
+    sprintf(loggingMissionCmds, "%s", "null ");
+  }
+  // send it out via uart
+  putStr(loggingMissionCmds);
+  replyStrs[0][0] = 0;
+  return 0;
+}
+
+//******************************************************************************
+int Logging_RPC_EraseMission(char argStrs[32][32], char replyStrs[32][32]) {
+  uint32_t reply[1];
+  Peripherals::s25FS512()->parameterSectorErase_Helper(0x0);
+  reply[0] = 0x80;
+  FormatReply32(reply, sizeof(reply) / sizeof(uint32_t), replyStrs);
+  return 0;
+}
+
+#define SECTOR_SIZE_256K 0x10000
+#define PAGE_INC_256K 0x400
+#define SECTOR_SIZE_4K 0x1000
+#define PAGE_INC_4K 0x10
+#define TOTAL_SECTOR_NUMBER 263
+
+//******************************************************************************
+int Logging_EraseWrittenSectors(char argStrs[32][32], char replyStrs[32][32]) {
+  uint32_t reply[1];
+  uint8_t data[512];
+  uint32_t address;
+  uint32_t pageNumber;
+  uint32_t pageEmpty;
+  uint32_t currentSector;
+
+  pageNumber = PAGE_INC_4K;
+  address = SECTOR_SIZE_4K;
+  currentSector = 0;
+  printf("Logging_EraseWrittenSectors ");
+  fflush(stdout);
+  printf("pageNumber %d 0x%X ", pageNumber, pageNumber);
+  fflush(stdout);
+  printf("SECTOR_SIZE_4K %d 0x%X ...", SECTOR_SIZE_4K, SECTOR_SIZE_4K);
+  fflush(stdout);
+  // always erase this sector... the first part is used for the mission resume
+  // table
+  Peripherals::s25FS512()->sectorErase_Helper(address);
+  address += SECTOR_SIZE_4K;
+  while (currentSector < TOTAL_SECTOR_NUMBER) {
+    // sample the page
+    pageNumber = address >> 8;
+    Peripherals::s25FS512()->readPages_Helper(pageNumber, pageNumber, data, 0);
+    pageEmpty = Peripherals::s25FS512()->isPageEmpty(data);
+    if (pageEmpty == 0) {
+      Peripherals::s25FS512()->sectorErase_Helper(address);
+    } else {
+      // stop processing... all of the sectors from here on out should be empty
+      // printf("Logging_EraseWrittenSectors break ");  fflush(stdout);
+      // break;
+    }
+    currentSector++;
+    if (currentSector < 8) {
+      address += SECTOR_SIZE_4K;
+    }
+    if (currentSector == 8) {
+      address = SECTOR_SIZE_256K;
+    }
+    if (currentSector > 8) {
+      address += SECTOR_SIZE_256K;
+    }
+  }
+  reply[0] = 0x80;
+  FormatReply32(reply, sizeof(reply) / sizeof(uint32_t), replyStrs);
+  printf("Logging_EraseWrittenSectors done. \n");
+  fflush(stdout);
+  return 0;
+}
+
+//******************************************************************************
+int Logging_Start(char argStrs[32][32], char replyStrs[32][32]) {
+  uint32_t reply[1];
+  Logging_SetStart(true);
+  reply[0] = 0x80; // indicate success
+  FormatReply32(reply, sizeof(reply) / sizeof(uint32_t), replyStrs);
+  return 0;
+}
+
+//******************************************************************************
+int Logging_GetLastWrittenPage(char argStrs[32][32], char replyStrs[32][32]) {
+  uint32_t reply[1];
+
+  uint32_t page;
+  uint32_t lastPage;
+  uint32_t pageEmpty;
+  uint8_t data[512];
+
+  printf("Logging_GetLastWrittenPage ");
+  fflush(stdout);
+  lastPage = Logging_GetLoggingEndPage();
+  for (page = 2; page <= lastPage; page++) {
+    // Peripherals::serial()->printf("checking page %d ",page); fflush(stdout);
+    // sample the page
+    Peripherals::s25FS512()->readPages_Helper(page, page, data, 0);
+    pageEmpty = Peripherals::s25FS512()->isPageEmpty(data);
+    if (pageEmpty != 0) {
+      break;
+    }
+  }
+  if (page > lastPage)
+    page = lastPage;
+  printf("last page %d, 0x%X ", page, page);
+  fflush(stdout);
+  reply[0] = page;
+  FormatReply32(reply, sizeof(reply) / sizeof(uint32_t), replyStrs);
+  return 0;
+}
+
+extern int highDataRate;
+//******************************************************************************
+int Logging_StartLoggingUsb(char argStrs[32][32], char replyStrs[32][32]) {
+  uint32_t reply[1];
+  // highDataRate = 0;
+  LoggingService_StartLoggingUsb();
+  reply[0] = 0x80;
+  FormatReply32(reply, sizeof(reply) / sizeof(uint32_t), replyStrs);
+  return 0;
+}
+//******************************************************************************
+int Logging_StartLoggingFlash(char argStrs[32][32], char replyStrs[32][32]) {
+  uint32_t reply[1];
+  // highDataRate = 0;
+  LoggingService_StartLoggingFlash();
+  reply[0] = 0x80;
+  FormatReply32(reply, sizeof(reply) / sizeof(uint32_t), replyStrs);
+  return 0;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/e4a10ed6eb92/HSP/LoggingService/Logging_RPC.h	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,55 @@
+/*******************************************************************************
+ * Copyright (C) 2016 Maxim Integrated Products, Inc., All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+ * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Except as contained in this notice, the name of Maxim Integrated
+ * Products, Inc. shall not be used except as stated in the Maxim Integrated
+ * Products, Inc. Branding Policy.
+ *
+ * The mere transfer of this software does not imply any licenses
+ * of trade secrets, proprietary technology, copyrights, patents,
+ * trademarks, maskwork rights, or any other form of intellectual
+ * property whatsoever. Maxim Integrated Products, Inc. retains all
+ * ownership rights.
+ *******************************************************************************
+ */
+#ifndef _LOGGING_H_
+#define _LOGGING_H_
+
+int Logging_RPC_StartMissionDefine(char argStrs[32][32], char replyStrs[32][32]);
+int Logging_RPC_AppendMissionCmd(char argStrs[32][32], char replyStrs[32][32]);
+int Logging_RPC_EndMissionDefine(char argStrs[32][32], char replyStrs[32][32]);
+int Logging_RPC_WriteMission(char argStrs[32][32], char replyStrs[32][32]);
+int Logging_RPC_ReadMission(char argStrs[32][32], char replyStrs[32][32]);
+int Logging_RPC_EraseMission(char argStrs[32][32], char replyStrs[32][32]);
+int Logging_RPC_TestMission(char argStrs[32][32], char replyStrs[32][32]);
+int Logging_RPC_TestWriteLog(char argStrs[32][32], char replyStrs[32][32]);
+int Logging_RPC_TestReadLog(char argStrs[32][32], char replyStrs[32][32]);
+int Logging_RPC_TestBulkErase(char argStrs[32][32], char replyStrs[32][32]);
+int Logging_RPC_TestSectorsErase(char argStrs[32][32], char replyStrs[32][32]);
+int Logging_RPC_TestReadPage(char argStrs[32][32], char replyStrs[32][32]);
+int Logging_RPC_TestWritePage(char argStrs[32][32], char replyStrs[32][32]);
+int Logging_EraseWrittenSectors(char argStrs[32][32], char replyStrs[32][32]);
+int Logging_StartLoggingUsb(char argStrs[32][32], char replyStrs[32][32]);
+int Logging_StartLoggingFlash(char argStrs[32][32], char replyStrs[32][32]);
+int Logging_GetLastWrittenPage(char argStrs[32][32], char replyStrs[32][32]);
+int Logging_Start(char argStrs[32][32], char replyStrs[32][32]);
+
+#endif /* _LOGGING_H_ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/e4a10ed6eb92/HSP/LoggingService/ServiceNonInterrupt.cpp	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,142 @@
+/*******************************************************************************
+ * Copyright (C) 2016 Maxim Integrated Products, Inc., All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+ * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Except as contained in this notice, the name of Maxim Integrated
+ * Products, Inc. shall not be used except as stated in the Maxim Integrated
+ * Products, Inc. Branding Policy.
+ *
+ * The mere transfer of this software does not imply any licenses
+ * of trade secrets, proprietary technology, copyrights, patents,
+ * trademarks, maskwork rights, or any other form of intellectual
+ * property whatsoever. Maxim Integrated Products, Inc. retains all
+ * ownership rights.
+ *******************************************************************************
+ */
+#include "ServiceNonInterrupt.h"
+#include "Streaming.h"
+#include "BMP280.h"
+#include "PacketFifo.h"
+#include "MAX30205.h"
+#include "Stream.h"
+#include "BMP280.h"
+#include "PacketFifo.h"
+#include "Peripherals.h"
+#include "Device_Logging.h"
+
+/// timer used for devices that do not have interrupt capability
+static Timer nonInterruptTimer;
+
+/// reference to logging object for the BMP280
+extern Device_Logging *bmp280_Logging;
+/// reference to logging object for the MAX30205 (instance 0)
+extern Device_Logging *MAX30205_0_Logging;
+/// reference to logging object for the MAX30205 (instance 1)
+extern Device_Logging *MAX30205_1_Logging;
+
+/**
+* @brief Initialize the book keeping variables for non interrupt devices
+*/
+void ServiceNonInterrupt_Init(void) {
+  // clear out the next time member in the device logging class
+  //   this is so that the devices are sampled the very first go-around
+  bmp280_Logging->setNextSampleTime(0);
+  MAX30205_0_Logging->setNextSampleTime(0);
+  MAX30205_1_Logging->setNextSampleTime(0);
+}
+
+/**
+* @brief Stop the 1 second timer
+*/
+void ServiceNonInterrupt_StartTimer(void) {
+  nonInterruptTimer.start();
+  nonInterruptTimer.reset();
+}
+
+/**
+* @brief Stop the 1 second timer
+*/
+void ServiceNonInterrupt_StopTimer(void) { nonInterruptTimer.stop(); }
+
+/**
+* @brief Get the current count of the timer
+* @return timer count in seconds
+*/
+static int ServiceNonInterrupt_GetTimerCount(void) {
+  return nonInterruptTimer.read();
+}
+
+/**
+* @brief Log the BMP280 sensor value if it is time
+* @param deviceLogging pointer to object that keeps track of logging for a
+* device
+*/
+void ServiceNonInterrupt_BMP280(Device_Logging *deviceLogging) {
+  int currentTime;
+  uint32_t bmp280_data[2]; // index 0 - Temp (deg C), index 1 - Press (Pa).
+                           // Divide the result by 10 to get the correct answer.
+  float temp_C, press_P;
+  int nextTime;
+
+  if (deviceLogging->isLoggingEnabled() == 0)
+    return;
+  currentTime = ServiceNonInterrupt_GetTimerCount();
+  nextTime = deviceLogging->getNextSampleTime();
+  if ((nextTime == 0) || (currentTime >= nextTime)) {
+    nextTime = currentTime + deviceLogging->getLoggingSampleRate();
+    deviceLogging->setNextSampleTime(nextTime);
+    Peripherals::bmp280()->ReadCompData(
+        &temp_C, &press_P); // Read the Temp (index 0)  and Pressure (index 1)
+    bmp280_data[0] = (int32_t)(temp_C * 10);
+    bmp280_data[1] = (int32_t)(press_P * 10);
+    PacketFifo_InsertPacket(PACKET_BMP280_PRESSURE, &bmp280_data[0],
+                            2); // Read it and insert it into the FIFO
+  }
+}
+
+/**
+* @brief Log the BMP280 sensor value if it is time
+* @param deviceLogging pointer to object that keeps track of logging for a
+* device
+* @param device pointer to the device instance (MAX30205 instance 0 or MAX30205
+* instance 1)
+* @param packetId packet id that is used when building a packet
+*/
+void ServiceNonInterrupt_MAX30205(Device_Logging *deviceLogging,
+                                  MAX30205 *device, uint32_t packetId) {
+  int currentTime;
+  uint32_t data;
+  uint16_t tempData;
+  int nextTime;
+
+  if (deviceLogging->isLoggingEnabled() == 0)
+    return;
+  currentTime = ServiceNonInterrupt_GetTimerCount();
+  nextTime = deviceLogging->getNextSampleTime();
+  if ((nextTime == 0) || (currentTime >= nextTime)) {
+    nextTime = currentTime + deviceLogging->getLoggingSampleRate();
+    deviceLogging->setNextSampleTime(nextTime);
+    device->readTemperature(&tempData);
+    // assemble this in the correct order
+    data = (uint32_t)((tempData >> 8) + ((tempData & 0xFF) << 8));
+    PacketFifo_InsertPacket(packetId, &data,
+                            1); // Read it and insert it into the FIFO
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/e4a10ed6eb92/HSP/LoggingService/ServiceNonInterrupt.h	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,66 @@
+/*******************************************************************************
+ * Copyright (C) 2016 Maxim Integrated Products, Inc., All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+ * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Except as contained in this notice, the name of Maxim Integrated
+ * Products, Inc. shall not be used except as stated in the Maxim Integrated
+ * Products, Inc. Branding Policy.
+ *
+ * The mere transfer of this software does not imply any licenses
+ * of trade secrets, proprietary technology, copyrights, patents,
+ * trademarks, maskwork rights, or any other form of intellectual
+ * property whatsoever. Maxim Integrated Products, Inc. retains all
+ * ownership rights.
+ *******************************************************************************
+ */
+#ifndef _SERVICENONINTERRUPT_H_
+#define _SERVICENONINTERRUPT_H_
+
+#include "mbed.h"
+#include "Device_Logging.h"
+#include "MAX30205.h"
+/**
+* @brief Initialize the book keeping variables for non interrupt devices
+*/
+void ServiceNonInterrupt_Init(void);
+/**
+* @brief Start the 1 second timer
+*/
+void ServiceNonInterrupt_StartTimer(void);
+/**
+* @brief Stop the 1 second timer
+*/
+void ServiceNonInterrupt_StopTimer(void);
+/**
+* @brief Log the BMP280 sensor value if it is time
+* @param deviceLogging pointer to object that keeps track of logging for a device
+*/
+void ServiceNonInterrupt_BMP280(Device_Logging *deviceLogging);
+/**
+* @brief Log the BMP280 sensor value if it is time
+* @param deviceLogging pointer to object that keeps track of logging for a device
+* @param device pointer to the device instance (MAX30205 instance 0 or MAX30205 instance 1)
+* @param packetId packet id that is used when building a packet
+*/
+void ServiceNonInterrupt_MAX30205(Device_Logging *deviceLogging, MAX30205 *device, uint32_t packetId);
+
+#endif /* _SERVICENONINTERRUPT_H_ */
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/e4a10ed6eb92/HSP/QuadSPI/QuadSpi.cpp	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,70 @@
+/*******************************************************************************
+ * Copyright (C) 2016 Maxim Integrated Products, Inc., All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+ * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Except as contained in this notice, the name of Maxim Integrated
+ * Products, Inc. shall not be used except as stated in the Maxim Integrated
+ * Products, Inc. Branding Policy.
+ *
+ * The mere transfer of this software does not imply any licenses
+ * of trade secrets, proprietary technology, copyrights, patents,
+ * trademarks, maskwork rights, or any other form of intellectual
+ * property whatsoever. Maxim Integrated Products, Inc. retains all
+ * ownership rights.
+ *******************************************************************************
+ */
+#include "QuadSpi.h"
+#include "spi_multi_api.h"
+
+/** Initialize a SPI master for Quad SPI
+ *
+ * @param mosi   Pin used for Master Out Slave In
+ * @param miso   Pin used for Master In Slave Out
+ * @param sclk   Pin used for Clock
+ * @param ssel   Pin used for Chip Select
+ */
+QuadSPI::QuadSPI(PinName mosi, PinName miso, PinName sclk, PinName ssel)
+    : SPI(mosi, miso, sclk, ssel) {
+}
+
+/******************************************************************************/
+void QuadSPI::setQuadMode() { spi_master_width(&_spi, WidthQuad); }
+/******************************************************************************/
+void QuadSPI::setSingleMode() { spi_master_width(&_spi, WidthSingle); }
+
+/** Write a byte out in master mode and receive a value
+ *
+ * @param value   Byte Value to send
+ * @return Returns Zero
+ */
+int QuadSPI::write(int value) {
+  aquire();
+  spi_master_write(&_spi, value);
+  return 0;
+}
+
+/** Read a byte in master mode using Quad SPI simplex transfer
+ *
+ * @return Returns the value received from Quad SPI
+ */
+int QuadSPI::read(void) {
+  aquire();
+  return spi_master_read(&_spi);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/e4a10ed6eb92/HSP/QuadSPI/QuadSpi.h	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,88 @@
+/*******************************************************************************
+ * Copyright (C) 2016 Maxim Integrated Products, Inc., All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+ * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Except as contained in this notice, the name of Maxim Integrated
+ * Products, Inc. shall not be used except as stated in the Maxim Integrated
+ * Products, Inc. Branding Policy.
+ *
+ * The mere transfer of this software does not imply any licenses
+ * of trade secrets, proprietary technology, copyrights, patents,
+ * trademarks, maskwork rights, or any other form of intellectual
+ * property whatsoever. Maxim Integrated Products, Inc. retains all
+ * ownership rights.
+ *******************************************************************************
+ */
+#ifndef _QUADSPI_H_
+#define _QUADSPI_H_
+
+#include "mbed.h"
+
+
+
+
+/**
+* This class provides a Quad SPI interface for quad spi devices
+* the class also allows single (4-Wire) communication
+*/
+class QuadSPI : SPI {
+
+public:
+  /** Create a QuadSPI master connected to the specified pins
+   *
+   *  mosi or miso can be specfied as NC if not used
+   *
+   *  @param mosi QuadSPI Master Out, Slave In pin
+   *  @param miso QuadSPI Master In, Slave Out pin
+   *  @param sclk QuadSPI Clock pin
+   *  @param ssel QuadSPI chip select pin
+   */
+  QuadSPI(PinName mosi, PinName miso, PinName sclk, PinName ssel = NC);
+
+  /** Write to the Quad SPI Slave and return the response
+   *
+   *  @param value Data to be sent to the SPI slave
+   *
+   *  @returns
+   *    none
+  */
+  int write(int value);
+
+  /** Read from the Quad SPI Slave and return the response
+   *
+   *  @param none
+   *
+   *  @returns
+   *    Response from the SPI slave
+  */
+  int read(void);
+
+  /** Allow switching to and from Single SPI and Quad SPI
+   *
+   *  @param none
+   *
+   *  @returns
+   *    Response from the SPI slave
+  */
+  void setSingleMode();
+  void setQuadMode();
+};
+
+#endif /* _QUADSPI_H_ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/e4a10ed6eb92/HSP/RpcServer/PacketFifo.cpp	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,56 @@
+/*******************************************************************************
+ * Copyright (C) 2016 Maxim Integrated Products, Inc., All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+ * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Except as contained in this notice, the name of Maxim Integrated
+ * Products, Inc. shall not be used except as stated in the Maxim Integrated
+ * Products, Inc. Branding Policy.
+ *
+ * The mere transfer of this software does not imply any licenses
+ * of trade secrets, proprietary technology, copyrights, patents,
+ * trademarks, maskwork rights, or any other form of intellectual
+ * property whatsoever. Maxim Integrated Products, Inc. retains all
+ * ownership rights.
+ *******************************************************************************
+ */
+#include "RpcFifo.h"
+#include "Streaming.h"
+#include "RpcServer.h"
+
+// this will create a packet and insert it on the "jFifo" to be streamed out or
+// saved in flash
+void PacketFifo_InsertPacket(uint32_t packetId, uint32_t *buffer,
+                             uint32_t numberInBuffer) {
+  StreamPacketUint32(packetId, buffer, numberInBuffer);
+}
+
+// clears the packet fifo "jFifo"
+void PacketFifo_Clear(void) { fifo_clear(GetStreamOutFifo()); }
+
+// returns one if fifo is empty, zero if not empty
+int PacketFifo_Empty(void) { return fifo_empty(GetStreamOutFifo()); }
+
+// returns a uint32 from the fifo, this uint32 is destined to be streamed out
+// USB or saved in flash
+uint32_t PacketFifo_GetUint32(void) {
+  uint32_t val;
+  fifo_get32(GetStreamOutFifo(), &val);
+  return val;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/e4a10ed6eb92/HSP/RpcServer/PacketFifo.h	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,61 @@
+/*******************************************************************************
+* Copyright (C) 2016 Maxim Integrated Products, Inc., All Rights Reserved.
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included
+* in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+* OTHER DEALINGS IN THE SOFTWARE.
+*
+* Except as contained in this notice, the name of Maxim Integrated
+* Products, Inc. shall not be used except as stated in the Maxim Integrated
+* Products, Inc. Branding Policy.
+*
+* The mere transfer of this software does not imply any licenses
+* of trade secrets, proprietary technology, copyrights, patents,
+* trademarks, maskwork rights, or any other form of intellectual
+* property whatsoever. Maxim Integrated Products, Inc. retains all
+* ownership rights.
+*******************************************************************************
+*/
+#ifndef _PACKETFIFO_H_
+#define _PACKETFIFO_H_
+
+#include "mbed.h"
+
+/**
+* this will create a packet and insert it into an outbound fifo to be streamed out or saved in flash
+* @param packetId number id to assign to this packet
+* @param buffer a 32-bit buffer that contains data that will be used in the packet
+* @param numberInBuffer the number of 32-bit elements to be copied from the buffer
+*/
+void PacketFifo_InsertPacket(uint32_t packetId, uint32_t *buffer, uint32_t numberInBuffer);
+
+/**
+* clears the packet outbound fifo
+*/
+void PacketFifo_Clear(void);
+
+/**
+* returns one if outbound fifo is empty, zero if not empty
+*/
+uint32_t PacketFifo_Empty(void);
+
+/** 
+* returns a uint32 from the fifo, this uint32 is destined to be streamed out USB or saved in flash
+*/
+uint32_t PacketFifo_GetUint32(void);
+
+#endif /* _PACKETFIFO_H_ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/e4a10ed6eb92/HSP/RpcServer/RpcDeclarations.h	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,688 @@
+/*******************************************************************************
+ * Copyright (C) 2016 Maxim Integrated Products, Inc., All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+ * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Except as contained in this notice, the name of Maxim Integrated
+ * Products, Inc. shall not be used except as stated in the Maxim Integrated
+ * Products, Inc. Branding Policy.
+ *
+ * The mere transfer of this software does not imply any licenses
+ * of trade secrets, proprietary technology, copyrights, patents,
+ * trademarks, maskwork rights, or any other form of intellectual
+ * property whatsoever. Maxim Integrated Products, Inc. retains all
+ * ownership rights.
+ *******************************************************************************
+ */
+#ifndef _RPCDECLARATIONS_H_
+#define _RPCDECLARATIONS_H_
+
+/// define the parts of a RPC.  ObjectName, MethodName and function
+struct RPC_registeredProcedure {
+    const char *objectName;
+    const char *methodName;
+    //enum eArgType argTypes[4];
+    int (*func)(char args[32][32], char results[32][32]);
+    struct RPC_registeredProcedure *next;
+};
+
+/// used to keep track of the head of the list and the end of a list
+struct RPC_Object {
+    struct RPC_registeredProcedure *head;
+    struct RPC_registeredProcedure *last;
+};
+
+
+#define I2C_NAME "I2c"
+/**
+* @brief  /I2c/WriteRead instance slaveAddress writeNumber dataToWrite readNumber
+* @details Command allows you to write and read generic I2c commands using a given I2c instance master
+* @param instance The I2c master on the Nimitz to use
+* @param slaveAddress Slave address to use when communicating
+* @param writeNumber The number of bytes to write
+* @param dataToWrite A series of space separated  hex values that are to be written
+* @param readNumber The number of bytes to read may be 0 if reading is not needed
+* @details Example: /I2c/WriteRead 1 A0 3 11 22 33 2
+* @details This performs an I2c write and read using instance 1, slave address A0, and writes 3 bytes,
+* @details the 3 bytes that are written are 11 22 33, 2 bytes are meant to be read after the write
+*/
+struct RPC_registeredProcedure  Define_I2c_WriteRead = { I2C_NAME, "WriteRead", I2C_WriteRead };
+
+//example /I2c/WriteRead 1 A0 3 11 22 33 2
+#define System_NAME "System"
+
+/**
+* @brief  /System/ReadVer
+* @details Returns the version string of the FW that is currently running
+* @details Example: /System/ReadVer
+* @details The command returns a version string similar to this: "HSP FW Version 2.0.1f 8/23/16"
+*/
+struct RPC_registeredProcedure  Define_System_ReadVer = { System_NAME, "ReadVer", System_ReadVer };
+/**
+* @brief  /System/ReadBuildTime
+* @details Returns the build string of the FW that is currently running, this is the time and date that the firmware was built
+* @details Example: /System/ReadBuildTime
+* @details The command returns a build string similar to this: "Build Time: Fri Jul 1 15:48:31 2016"
+*/
+struct RPC_registeredProcedure  Define_System_ReadBuildTime = { System_NAME, "ReadBuildTime", System_ReadBuildTime };
+
+#define MAX30101_NAME "MAX30101" //"MAX30101"
+/**
+* @brief  /MAX30101/WriteReg address data
+* @details Returns the version string of the FW that is currently running
+* @param address Register address to write to within the MAX30101
+* @param data The data to write to the MAX30101
+* @details Example: /MAX30101/WriteReg 01 123456
+*/
+struct RPC_registeredProcedure  Define_MAX30101_WriteReg = { MAX30101_NAME, "WriteReg", MAX30101_WriteReg };
+/**
+* @brief  /MAX30101/ReadReg address data
+* @details Returns the version string of the FW that is currently running
+* @param address Register address to write to within the MAX30101
+* @param data The data to write to the MAX30101
+* @details Example: /MAX30101/WriteReg 01 123456
+*/
+struct RPC_registeredProcedure  Define_MAX30101_ReadReg = { MAX30101_NAME, "ReadReg", MAX30101_ReadReg };
+/**
+* @brief  /MAX30101/SpO2mode_init fifo_waterlevel_mark sample_avg sample_rate pulse_width red_led_current ir_led_current
+* @details This function sets up for the SpO2 mode. 
+* @param fifo_waterlevel_mark
+* @param sample_avg
+* @param sample_rate
+* @param pulse_width
+* @param red_led_current
+* @param ir_led_current
+*/
+struct RPC_registeredProcedure  Define_MAX30101_SpO2mode_Init = { MAX30101_NAME, "SpO2mode_init", MAX30101_SpO2mode_init };
+/**
+* @brief  /MAX30101/SpO2mode_init fifo_waterlevel_mark sample_avg sample_rate pulse_width red_led_current ir_led_current
+* @details This function sets up for the SpO2 mode. 
+* @param fifo_waterlevel_mark
+* @param sample_avg
+* @param sample_rate
+* @param pulse_width
+* @param red_led_current
+* @param ir_led_current
+*/
+struct RPC_registeredProcedure  Define_MAX30101_SpO2mode_InitStart = { MAX30101_NAME, "SpO2mode_InitStart", MAX30101_SpO2mode_InitStart };
+/**
+* @brief  /MAX30101/SpO2mode_init fifo_waterlevel_mark sample_avg sample_rate pulse_width red_led_current ir_led_current
+* @details This function sets up for the SpO2 mode. 
+* @param fifo_waterlevel_mark
+* @param sample_avg
+* @param sample_rate
+* @param pulse_width
+* @param red_led_current
+* @param ir_led_current
+*/
+struct RPC_registeredProcedure  Define_MAX30101_HRmode_Init = { MAX30101_NAME, "HRmode_init", MAX30101_HRmode_init };
+/**
+* @brief  /MAX30101/SpO2mode_init fifo_waterlevel_mark sample_avg sample_rate pulse_width red_led_current ir_led_current
+* @details This function sets up for the SpO2 mode. 
+* @param fifo_waterlevel_mark
+* @param sample_avg
+* @param sample_rate
+* @param pulse_width
+* @param red_led_current
+* @param ir_led_current
+*/
+struct RPC_registeredProcedure  Define_MAX30101_HRmode_InitStart = { MAX30101_NAME, "HRmode_InitStart", MAX30101_HRmode_InitStart };
+/**
+* @brief  /MAX30101/SpO2mode_init fifo_waterlevel_mark sample_avg sample_rate pulse_width red_led_current ir_led_current
+* @details This function sets up for the SpO2 mode. 
+* @param fifo_waterlevel_mark
+* @param sample_avg
+* @param sample_rate
+* @param pulse_width
+* @param red_led_current
+* @param ir_led_current
+*/
+struct RPC_registeredProcedure  Define_MAX30101_Multimode_init = { MAX30101_NAME, "Multimode_init", MAX30101_Multimode_init };
+/**
+* @brief  /MAX30101/SpO2mode_init fifo_waterlevel_mark sample_avg sample_rate pulse_width red_led_current ir_led_current
+* @details This function sets up for the SpO2 mode. 
+* @param fifo_waterlevel_mark
+* @param sample_avg
+* @param sample_rate
+* @param pulse_width
+* @param red_led_current
+* @param ir_led_current
+*/
+struct RPC_registeredProcedure  Define_MAX30101_Multimode_InitStart = { MAX30101_NAME, "Multimode_InitStart", MAX30101_Multimode_InitStart };
+/**
+* @brief  /MAX30101/SpO2mode_init fifo_waterlevel_mark sample_avg sample_rate pulse_width red_led_current ir_led_current
+* @details This function sets up for the SpO2 mode. 
+* @param fifo_waterlevel_mark
+* @param sample_avg
+* @param sample_rate
+* @param pulse_width
+* @param red_led_current
+* @param ir_led_current
+*/
+struct RPC_registeredProcedure  Define_MAX30101_SpO2mode_stop = { MAX30101_NAME, "SpO2mode_stop", MAX30101_SpO2mode_stop };
+/**
+* @brief  /MAX30101/SpO2mode_init fifo_waterlevel_mark sample_avg sample_rate pulse_width red_led_current ir_led_current
+* @details This function sets up for the SpO2 mode. 
+* @param fifo_waterlevel_mark
+* @param sample_avg
+* @param sample_rate
+* @param pulse_width
+* @param red_led_current
+* @param ir_led_current
+*/
+struct RPC_registeredProcedure  Define_MAX30101_HRmode_stop = { MAX30101_NAME, "HRmode_stop", MAX30101_HRmode_stop };
+/**
+* @brief  /MAX30101/SpO2mode_init fifo_waterlevel_mark sample_avg sample_rate pulse_width red_led_current ir_led_current
+* @details This function sets up for the SpO2 mode. 
+* @param fifo_waterlevel_mark
+* @param sample_avg
+* @param sample_rate
+* @param pulse_width
+* @param red_led_current
+* @param ir_led_current
+*/
+struct RPC_registeredProcedure  Define_MAX30101_Multimode_stop = { MAX30101_NAME, "Multimode_stop", MAX30101_Multimode_stop };
+
+#define MAX30001_NAME "MAX30001"
+#define MAX30003_NAME "MAX30003"
+
+#define MAX31725_NAME "MAX31725"
+#define MAX30205_NAME "MAX30205"
+
+/**
+* @brief  /MAX30101/SpO2mode_init fifo_waterlevel_mark sample_avg sample_rate pulse_width red_led_current ir_led_current
+* @details This function sets up for the SpO2 mode. 
+* @param fifo_waterlevel_mark
+* @param sample_avg
+* @param sample_rate
+* @param pulse_width
+* @param red_led_current
+* @param ir_led_current
+*/
+struct RPC_registeredProcedure  Define_MAX30001_WriteReg = { MAX30001_NAME, "WriteReg", MAX30001_WriteReg };
+/**
+* @brief  /MAX30101/SpO2mode_init fifo_waterlevel_mark sample_avg sample_rate pulse_width red_led_current ir_led_current
+* @details This function sets up for the SpO2 mode. 
+* @param fifo_waterlevel_mark
+* @param sample_avg
+* @param sample_rate
+* @param pulse_width
+* @param red_led_current
+* @param ir_led_current
+*/
+struct RPC_registeredProcedure  Define_MAX30001_ReadReg = { MAX30001_NAME, "ReadReg", MAX30001_ReadReg };
+/**
+* @brief  /MAX30101/SpO2mode_init fifo_waterlevel_mark sample_avg sample_rate pulse_width red_led_current ir_led_current
+* @details This function sets up for the SpO2 mode. 
+* @param fifo_waterlevel_mark
+* @param sample_avg
+* @param sample_rate
+* @param pulse_width
+* @param red_led_current
+* @param ir_led_current
+*/
+struct RPC_registeredProcedure  Define_MAX30001_Start = { MAX30001_NAME, "Start", MAX30001_Start };
+/**
+* @brief  /MAX30101/SpO2mode_init fifo_waterlevel_mark sample_avg sample_rate pulse_width red_led_current ir_led_current
+* @details This function sets up for the SpO2 mode. 
+* @param fifo_waterlevel_mark
+* @param sample_avg
+* @param sample_rate
+* @param pulse_width
+* @param red_led_current
+* @param ir_led_current
+*/
+struct RPC_registeredProcedure  Define_MAX30001_Stop = { MAX30001_NAME, "Stop", MAX30001_Stop };
+/**
+* @brief  /MAX30101/SpO2mode_init fifo_waterlevel_mark sample_avg sample_rate pulse_width red_led_current ir_led_current
+* @details This function sets up for the SpO2 mode. 
+* @param fifo_waterlevel_mark
+* @param sample_avg
+* @param sample_rate
+* @param pulse_width
+* @param red_led_current
+* @param ir_led_current
+*/
+struct RPC_registeredProcedure  Define_MAX30001_Rbias_FMSTR_Init = { MAX30001_NAME, "Rbias_FMSTR_Init", MAX30001_Rbias_FMSTR_Init };
+/**
+* @brief  /MAX30101/SpO2mode_init fifo_waterlevel_mark sample_avg sample_rate pulse_width red_led_current ir_led_current
+* @details This function sets up for the SpO2 mode. 
+* @param fifo_waterlevel_mark
+* @param sample_avg
+* @param sample_rate
+* @param pulse_width
+* @param red_led_current
+* @param ir_led_current
+*/
+struct RPC_registeredProcedure  Define_MAX30001_CAL_InitStart = { MAX30001_NAME, "CAL_InitStart", MAX30001_CAL_InitStart };
+/**
+* @brief  /MAX30101/SpO2mode_init fifo_waterlevel_mark sample_avg sample_rate pulse_width red_led_current ir_led_current
+* @details This function sets up for the SpO2 mode. 
+* @param fifo_waterlevel_mark
+* @param sample_avg
+* @param sample_rate
+* @param pulse_width
+* @param red_led_current
+* @param ir_led_current
+*/
+struct RPC_registeredProcedure  Define_MAX30001_ECG_InitStart = { MAX30001_NAME, "ECG_InitStart", MAX30001_ECG_InitStart };
+/**
+* @brief  /MAX30101/SpO2mode_init fifo_waterlevel_mark sample_avg sample_rate pulse_width red_led_current ir_led_current
+* @details This function sets up for the SpO2 mode. 
+* @param fifo_waterlevel_mark
+* @param sample_avg
+* @param sample_rate
+* @param pulse_width
+* @param red_led_current
+* @param ir_led_current
+*/
+struct RPC_registeredProcedure  Define_MAX30001_ECGFast_Init = { MAX30001_NAME, "ECGFast_Init", MAX30001_ECGFast_Init };
+/**
+* @brief  /MAX30101/SpO2mode_init fifo_waterlevel_mark sample_avg sample_rate pulse_width red_led_current ir_led_current
+* @details This function sets up for the SpO2 mode. 
+* @param fifo_waterlevel_mark
+* @param sample_avg
+* @param sample_rate
+* @param pulse_width
+* @param red_led_current
+* @param ir_led_current
+*/
+struct RPC_registeredProcedure  Define_MAX30001_PACE_InitStart = { MAX30001_NAME, "PACE_InitStart", MAX30001_PACE_InitStart };
+/**
+* @brief  /MAX30101/SpO2mode_init fifo_waterlevel_mark sample_avg sample_rate pulse_width red_led_current ir_led_current
+* @details This function sets up for the SpO2 mode. 
+* @param fifo_waterlevel_mark
+* @param sample_avg
+* @param sample_rate
+* @param pulse_width
+* @param red_led_current
+* @param ir_led_current
+*/
+struct RPC_registeredProcedure  Define_MAX30001_BIOZ_InitStart = { MAX30001_NAME, "BIOZ_InitStart", MAX30001_BIOZ_InitStart };
+/**
+* @brief  /MAX30101/SpO2mode_init fifo_waterlevel_mark sample_avg sample_rate pulse_width red_led_current ir_led_current
+* @details This function sets up for the SpO2 mode. 
+* @param fifo_waterlevel_mark
+* @param sample_avg
+* @param sample_rate
+* @param pulse_width
+* @param red_led_current
+* @param ir_led_current
+*/
+struct RPC_registeredProcedure  Define_MAX30001_RtoR_InitStart = { MAX30001_NAME, "RtoR_InitStart", MAX30001_RtoR_InitStart };
+/**
+* @brief  /MAX30101/SpO2mode_init fifo_waterlevel_mark sample_avg sample_rate pulse_width red_led_current ir_led_current
+* @details This function sets up for the SpO2 mode. 
+* @param fifo_waterlevel_mark
+* @param sample_avg
+* @param sample_rate
+* @param pulse_width
+* @param red_led_current
+* @param ir_led_current
+*/
+struct RPC_registeredProcedure  Define_MAX30001_Stop_ECG = { MAX30001_NAME, "Stop_ECG", MAX30001_Stop_ECG };
+/**
+* @brief  /MAX30101/SpO2mode_init fifo_waterlevel_mark sample_avg sample_rate pulse_width red_led_current ir_led_current
+* @details This function sets up for the SpO2 mode. 
+* @param fifo_waterlevel_mark
+* @param sample_avg
+* @param sample_rate
+* @param pulse_width
+* @param red_led_current
+* @param ir_led_current
+*/
+struct RPC_registeredProcedure  Define_MAX30001_Stop_PACE = { MAX30001_NAME, "Stop_PACE", MAX30001_Stop_PACE };
+/**
+* @brief  /MAX30101/SpO2mode_init fifo_waterlevel_mark sample_avg sample_rate pulse_width red_led_current ir_led_current
+* @details This function sets up for the SpO2 mode. 
+* @param fifo_waterlevel_mark
+* @param sample_avg
+* @param sample_rate
+* @param pulse_width
+* @param red_led_current
+* @param ir_led_current
+*/
+struct RPC_registeredProcedure  Define_MAX30001_Stop_BIOZ = { MAX30001_NAME, "Stop_BIOZ", MAX30001_Stop_BIOZ };
+/**
+* @brief  /MAX30101/SpO2mode_init fifo_waterlevel_mark sample_avg sample_rate pulse_width red_led_current ir_led_current
+* @details This function sets up for the SpO2 mode. 
+* @param fifo_waterlevel_mark
+* @param sample_avg
+* @param sample_rate
+* @param pulse_width
+* @param red_led_current
+* @param ir_led_current
+*/
+struct RPC_registeredProcedure  Define_MAX30001_Stop_RtoR = { MAX30001_NAME, "Stop_RtoR", MAX30001_Stop_RtoR };
+/**
+* @brief  /MAX30101/SpO2mode_init fifo_waterlevel_mark sample_avg sample_rate pulse_width red_led_current ir_led_current
+* @details This function sets up for the SpO2 mode. 
+* @param fifo_waterlevel_mark
+* @param sample_avg
+* @param sample_rate
+* @param pulse_width
+* @param red_led_current
+* @param ir_led_current
+*/
+struct RPC_registeredProcedure  Define_MAX30001_Stop_Cal = { MAX30001_NAME, "Stop_Cal", MAX30001_Stop_Cal };
+/**
+* @brief  /MAX30101/SpO2mode_init fifo_waterlevel_mark sample_avg sample_rate pulse_width red_led_current ir_led_current
+* @details This function sets up for the SpO2 mode. 
+* @param fifo_waterlevel_mark
+* @param sample_avg
+* @param sample_rate
+* @param pulse_width
+* @param red_led_current
+* @param ir_led_current
+*/
+struct RPC_registeredProcedure  Define_MAX30001_Enable_ECG_LeadON = { MAX30001_NAME, "Enable_ECG_LeadON", MAX30001_Enable_ECG_LeadON };
+/**
+* @brief  /MAX30101/SpO2mode_init fifo_waterlevel_mark sample_avg sample_rate pulse_width red_led_current ir_led_current
+* @details This function sets up for the SpO2 mode. 
+* @param fifo_waterlevel_mark
+* @param sample_avg
+* @param sample_rate
+* @param pulse_width
+* @param red_led_current
+* @param ir_led_current
+*/
+struct RPC_registeredProcedure  Define_MAX30001_Enable_BIOZ_LeadON = { MAX30001_NAME, "Enable_BIOZ_LeadON", MAX30001_Enable_BIOZ_LeadON };
+/**
+* @brief  /MAX30101/SpO2mode_init fifo_waterlevel_mark sample_avg sample_rate pulse_width red_led_current ir_led_current
+* @details This function sets up for the SpO2 mode. 
+* @param fifo_waterlevel_mark
+* @param sample_avg
+* @param sample_rate
+* @param pulse_width
+* @param red_led_current
+* @param ir_led_current
+*/
+struct RPC_registeredProcedure  Define_MAX30001_Read_LeadON = { MAX30001_NAME, "Read_LeadON", MAX30001_Read_LeadON };
+/**
+* @brief  /MAX30101/SpO2mode_init fifo_waterlevel_mark sample_avg sample_rate pulse_width red_led_current ir_led_current
+* @details This function sets up for the SpO2 mode. 
+* @param fifo_waterlevel_mark
+* @param sample_avg
+* @param sample_rate
+* @param pulse_width
+* @param red_led_current
+* @param ir_led_current
+*/
+struct RPC_registeredProcedure  Define_MAX30001_StartTest = { MAX30001_NAME, "StartTest", MAX30001_StartTest };
+/**
+* @brief  /MAX30101/SpO2mode_init fifo_waterlevel_mark sample_avg sample_rate pulse_width red_led_current ir_led_current
+* @details This function sets up for the SpO2 mode. 
+* @param fifo_waterlevel_mark
+* @param sample_avg
+* @param sample_rate
+* @param pulse_width
+* @param red_led_current
+* @param ir_led_current
+*/
+struct RPC_registeredProcedure  Define_MAX30001_INT_assignment = { MAX30001_NAME, "INT_assignment", MAX30001_INT_assignment };
+
+#define LOGGING_NAME "Logging"
+/**
+* @brief  /Logging/StartMissionDefine
+* @details A command to send when you are starting to define a mission
+*/
+struct RPC_registeredProcedure  Define_Logging_StartMissionDefine = { LOGGING_NAME, "StartMissionDefine", Logging_RPC_StartMissionDefine };
+/**
+* @brief  /Logging/AppendMissionCmd missionString
+* @details Specify a RPC command that is part of a mission
+*/
+struct RPC_registeredProcedure  Define_Logging_AppendMissionCmd = { LOGGING_NAME, "AppendMissionCmd", Logging_RPC_AppendMissionCmd };
+/**
+* @brief  /Logging/EndMissionDefine
+* @details RPC command that indicated the end of defining a mission
+*/
+struct RPC_registeredProcedure  Define_Logging_EndMissionDefine = { LOGGING_NAME, "EndMissionDefine", Logging_RPC_EndMissionDefine };
+/**
+* @brief  /Logging/WriteMission
+* @details Write the described mission to flash
+*/
+struct RPC_registeredProcedure  Define_Logging_WriteMission = { LOGGING_NAME, "WriteMission", Logging_RPC_WriteMission };
+/**
+* @brief  /Logging/ReadMission
+* @details Read the mission from flash
+*/
+struct RPC_registeredProcedure  Define_Logging_ReadMission = { LOGGING_NAME, "ReadMission", Logging_RPC_ReadMission };
+/**
+* @brief  /Logging/EraseMission
+* @details Erase the mission in flash
+*/
+struct RPC_registeredProcedure  Define_Logging_EraseMission = { LOGGING_NAME, "EraseMission", Logging_RPC_EraseMission };
+/**
+* @brief  /Logging/EraseWrittenSectors
+* @details Erase the datalog in flash, this erases all of the datalog that has been written to the flash
+*/
+struct RPC_registeredProcedure  Define_Logging_EraseWrittenSectors = { LOGGING_NAME, "EraseWrittenSectors", Logging_EraseWrittenSectors };
+/**
+* @brief  /Logging/StartLoggingUsb
+* @details Start streaming data through USB
+*/
+struct RPC_registeredProcedure  Define_Logging_StartLoggingUsb = { LOGGING_NAME, "StartLoggingUsb", Logging_StartLoggingUsb };
+/**
+* @brief  /Logging/StartLoggingFlash
+* @details Start logging data to flash
+*/
+struct RPC_registeredProcedure  Define_Logging_StartLoggingFlash = { LOGGING_NAME, "StartLoggingFlash", Logging_StartLoggingFlash };
+/**
+* @brief  /Logging/GetLastWrittenPage
+* @details Returns the last page that has been written to flash, this call searchs until it finds an empty flash page
+*/
+struct RPC_registeredProcedure  Define_Logging_GetLastWrittenPage = { LOGGING_NAME, "GetLastWrittenPage", Logging_GetLastWrittenPage };
+/**
+* @brief  /Logging/Start
+* @details Starts a datalogging session into flash, allows the ability to start datalogging via RPC call
+*/
+struct RPC_registeredProcedure  Define_Logging_Start = { LOGGING_NAME, "Start", Logging_Start };
+
+#define LIS2DH_NAME "LIS2DH"
+/**
+* @brief  /LIS2DH/InitStart
+* @details Starts streaming interrupts from the LIS2DH device
+*/
+struct RPC_registeredProcedure  Define_LIS2DH_InitStart = { LIS2DH_NAME, "InitStart", LIS2DH_InitStart };
+/**
+* @brief  /LIS2DH/ReadReg address
+* @details Reads a register
+* @param address Register address to read from
+*/
+struct RPC_registeredProcedure  Define_LIS2DH_ReadReg = { LIS2DH_NAME, "ReadReg", LIS2DH_ReadReg };
+/**
+* @brief  /LIS2DH/WriteReg address data
+* @details Write a register
+* @param address Register address to read from
+* @param data Data to write
+*/
+struct RPC_registeredProcedure  Define_LIS2DH_WriteReg = { LIS2DH_NAME, "WriteReg", LIS2DH_WriteReg };
+/**
+* @brief  /LIS2DH/Stop
+* @details Stop the interrupts within the LIS2DH
+*/
+struct RPC_registeredProcedure  Define_LIS2DH_Stop = { LIS2DH_NAME, "Stop", LIS2DH_Stop };
+
+#define BMP280_NAME "BMP280"
+/**
+* @brief  /BMP280/InitStart
+* @details Start the polling process for the BMP280
+*/
+struct RPC_registeredProcedure  Define_BMP280_InitStart = { BMP280_NAME, "InitStart", BMP280_InitStart };
+
+#define MAX30205_1_NAME "MAX30205_1"
+#define MAX31725_1_NAME "MAX31725_1"
+/**
+* @brief  /MAX30205_1/InitStart
+* @details Start the polling process for the MAX30205 instance 1
+*/
+struct RPC_registeredProcedure  Define_MAX30205_1_InitStart = { MAX30205_1_NAME, "InitStart", MAX30205_1_InitStart };
+struct RPC_registeredProcedure  Define_MAX31725_1_InitStart = { MAX31725_1_NAME, "InitStart", MAX30205_1_InitStart };
+
+#define MAX30205_2_NAME "MAX30205_2"
+#define MAX31725_2_NAME "MAX31725_2"
+/**
+* @brief  /MAX30205_2/InitStart
+* @details Start the polling process for the MAX30205 instance 2
+*/
+struct RPC_registeredProcedure  Define_MAX30205_2_InitStart = { MAX30205_2_NAME, "InitStart", MAX30205_2_InitStart };
+struct RPC_registeredProcedure  Define_MAX31725_2_InitStart = { MAX31725_2_NAME, "InitStart", MAX30205_2_InitStart };
+
+#define LED_NAME "Led"
+/**
+* @brief  /Led/On
+* @details Turn on the HSP onboard LED
+*/
+struct RPC_registeredProcedure  Define_Led_On = { LED_NAME, "On", Led_On };
+/**
+* @brief  /Led/Off
+* @details Turn off the HSP onboard LED
+*/
+struct RPC_registeredProcedure  Define_Led_Off = { LED_NAME, "Off", Led_Off };
+/**
+* @brief  /Led/Blink mS
+* @details Start blinking the HSP onboard LED
+* @param mS Blink using a mS period
+*/
+struct RPC_registeredProcedure  Define_Led_BlinkHz = { LED_NAME, "Blink", Led_BlinkHz };
+/**
+* @brief  /Led/Pattern pattern
+* @details Rotate a 32-bit pattern through the LED so that specific blink patterns can be obtained
+* @param pattern A 32-bit pattern to rotate through
+*/
+struct RPC_registeredProcedure  Define_Led_BlinkPattern = { LED_NAME, "Pattern", Led_BlinkPattern };
+
+#define S25FS512_NAME "S25FS512"
+/**
+* @brief  /S25FS512/ReadId
+* @details Rotate a 32-bit pattern through the LED so that specific blink patterns can be obtained
+* @param pattern A 32-bit pattern to rotate through
+*/
+struct RPC_registeredProcedure  Define_S25FS512_ReadId = { S25FS512_NAME, "ReadId", S25FS512_ReadId };
+/**
+* @brief  /S25FS512/ReadPagesBinary startPage endPage
+* @details Read a page from flash, return the data in binary (non-ascii)
+* @param startPage The Starting page to read from
+* @param endPage The last page to read from
+*/
+struct RPC_registeredProcedure  Define_S25FS512_ReadPagesBinary = { S25FS512_NAME, "ReadPagesBinary", S25FS512_ReadPagesBinary };
+/**
+* @brief  /S25FS512/Reset
+* @details Issue a soft reset to the flash device
+*/
+struct RPC_registeredProcedure  Define_S25FS512_Reset = { S25FS512_NAME, "Reset", S25FS512_Reset };
+/**
+* @brief  /S25FS512/EnableHWReset
+* @details Enable HW resets to the device
+*/
+struct RPC_registeredProcedure  Define_S25FS512_EnableHWReset = { S25FS512_NAME, "EnableHWReset", S25FS512_EnableHWReset };
+/**
+* @brief  /S25FS512/SpiWriteRead
+* @details Write and read SPI to the flash device using Quad SPI
+*/
+struct RPC_registeredProcedure  Define_S25FS512_SpiWriteRead = { S25FS512_NAME, "SpiWriteRead", S25FS512_SpiWriteRead };
+/**
+* @brief  /S25FS512/SpiWriteRead4Wire
+* @details Write and read SPI to the flash device using 4 wire
+*/
+struct RPC_registeredProcedure  Define_S25FS512_SpiWriteRead4Wire = { S25FS512_NAME, "SpiWriteRead4Wire", S25FS512_SpiWriteRead4Wire };
+
+#define TESTING_NAME "Testing"
+/**
+* @brief  /Testing/Test_S25FS512
+* @details Start a testing sequence for this device, returns PASS and FAIL strings and detailed results of the test
+*/
+struct RPC_registeredProcedure  Define_Testing_Test_S25FS512 = { TESTING_NAME, "Test_S25FS512",  Test_S25FS512};
+/**
+* @brief  /Testing/Test_BMP280
+* @details Start a testing sequence for this device, returns PASS and FAIL strings and detailed results of the test
+*/
+struct RPC_registeredProcedure  Define_Testing_Test_BMP280 = { TESTING_NAME, "Test_BMP280",  Test_BMP280};
+/**
+* @brief  /Testing/Test_LIS2DH
+* @details Start a testing sequence for this device, returns PASS and FAIL strings and detailed results of the test
+*/
+struct RPC_registeredProcedure  Define_Testing_Test_LIS2DH = { TESTING_NAME, "Test_LIS2DH", Test_LIS2DH };
+/**
+* @brief  /Testing/Test_LSM6DS3
+* @details Start a testing sequence for this device, returns PASS and FAIL strings and detailed results of the test
+*/
+struct RPC_registeredProcedure  Define_Testing_Test_LSM6DS3 = { TESTING_NAME, "Test_LSM6DS3", Test_LSM6DS3 };
+/**
+* @brief  /Testing/Test_MAX30205_1
+* @details Start a testing sequence for this device, returns PASS and FAIL strings and detailed results of the test
+*/
+struct RPC_registeredProcedure  Define_Testing_Test_MAX30205_1 = { TESTING_NAME, "Test_MAX30205_1", Test_MAX30205_1 };
+/**
+* @brief  /Testing/Test_MAX30205_2
+* @details Start a testing sequence for this device, returns PASS and FAIL strings and detailed results of the test
+*/
+struct RPC_registeredProcedure  Define_Testing_Test_MAX30205_2 = { TESTING_NAME, "Test_MAX30205_2", Test_MAX30205_2 };
+/**
+* @brief  /Testing/Test_MAX30101
+* @details Start a testing sequence for this device, returns PASS and FAIL strings and detailed results of the test
+*/
+struct RPC_registeredProcedure  Define_Testing_Test_MAX30101 = { TESTING_NAME, "Test_MAX30101", Test_MAX30101 };
+/**
+* @brief  /Testing/Test_MAX30001
+* @details Start a testing sequence for this device, returns PASS and FAIL strings and detailed results of the test
+*/
+struct RPC_registeredProcedure  Define_Testing_Test_MAX30001 = { TESTING_NAME, "Test_MAX30001", Test_MAX30001 };
+/**
+* @brief  /Testing/Test_EM9301
+* @details Start a testing sequence for this device, returns PASS and FAIL strings and detailed results of the test
+*/
+struct RPC_registeredProcedure  Define_Testing_Test_EM9301 = { TESTING_NAME, "Test_EM9301", Test_EM9301 };
+/**
+* @brief  /Testing/Test_EM9301
+* @details Start a testing sequence for this device, returns PASS and FAIL strings and detailed results of the test
+*/
+//struct RPC_registeredProcedure  Define_Testing_Test_SensorReadings = { TESTING_NAME, "Test_SensorReadings", Test_EM9301 };
+
+#define MAX14720_NAME "MAX14720"
+/**
+* @brief  /MAX14720/ReadBoostVSet   
+* @details Read the BoostVSet value
+* @return Returns the value from the BoostVSet register of the device
+*/
+struct RPC_registeredProcedure  Define_MAX14720_ReadBoostVSet = { MAX14720_NAME, "ReadBoostVSet", MAX14720_ReadBoostVSet };
+/**
+* @brief  /MAX14720/WriteBoostVSet
+* @details Write the BoostVSet value
+* @param value The binary value to set the BoostVSet register to
+* @return Returns 0x80 on success of the command
+*/
+struct RPC_registeredProcedure  Define_MAX14720_WriteBoostVSet = { MAX14720_NAME, "WriteBoostVSet", MAX14720_WriteBoostVSet };
+/**
+* @brief  /MAX14720/ReadReg   
+* @details Read one of the MAX14720 registers
+* @param address Address of the register to read
+* @return Returns the value from the addressed register from the device
+*/
+struct RPC_registeredProcedure  Define_MAX14720_ReadReg = { MAX14720_NAME, "ReadReg", MAX14720_ReadReg };
+/**
+* @brief  /MAX14720/WriteReg
+* @details Write one of the MAX14720 registers
+* @param address Address of the register to write
+* @param data Value of the data to write
+* @return Returns 0x80 on success of the command
+*/
+struct RPC_registeredProcedure  Define_MAX14720_WriteReg = { MAX14720_NAME, "WriteReg", MAX14720_WriteReg };
+
+#endif /* _RPCDECLARATIONS_H_ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/e4a10ed6eb92/HSP/RpcServer/RpcFifo.cpp	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,253 @@
+/*******************************************************************************
+ * Copyright (C) 2016 Maxim Integrated Products, Inc., All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+ * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Except as contained in this notice, the name of Maxim Integrated
+ * Products, Inc. shall not be used except as stated in the Maxim Integrated
+ * Products, Inc. Branding Policy.
+ *
+ * The mere transfer of this software does not imply any licenses
+ * of trade secrets, proprietary technology, copyrights, patents,
+ * trademarks, maskwork rights, or any other form of intellectual
+ * property whatsoever. Maxim Integrated Products, Inc. retains all
+ * ownership rights.
+ *******************************************************************************
+ */
+#include "mbed.h"
+#include "RpcFifo.h"
+
+/****************************************************************************/
+void fifo_init(fifo_t *fifo, void *mem, unsigned int length) {
+  // atomic FIFO access
+  __disable_irq();
+
+  fifo->rindex = 0;
+  fifo->windex = 0;
+  fifo->data = mem;
+  fifo->length = length;
+
+  __enable_irq();
+}
+
+/****************************************************************************/
+int fifo_put8(fifo_t *fifo, uint8_t element) {
+  // Check if FIFO is full
+  if ((fifo->windex == (fifo->rindex - 1)) ||
+      ((fifo->rindex == 0) && (fifo->windex == (fifo->length - 1)))) {
+    return -1;
+  }
+
+  // atomic FIFO access
+  __disable_irq();
+
+  // Put data into FIFO
+  ((uint8_t *)(fifo->data))[fifo->windex] = element;
+
+  // Increment pointer
+  fifo->windex++;
+  if (fifo->windex == fifo->length) {
+    fifo->windex = 0;
+  }
+
+  __enable_irq();
+
+  return 0;
+}
+
+/****************************************************************************/
+int fifo_get8(fifo_t *fifo, uint8_t *element) {
+  // Check if FIFO is empty
+  if (fifo->rindex == fifo->windex)
+    return -1;
+
+  // atomic FIFO access
+  __disable_irq();
+
+  // Get data from FIFO
+  *element = ((uint8_t *)(fifo->data))[fifo->rindex];
+
+  // Increment pointer
+  fifo->rindex++;
+  if (fifo->rindex == fifo->length) {
+    fifo->rindex = 0;
+  }
+
+  __enable_irq();
+
+  return 0;
+}
+
+/****************************************************************************/
+int fifo_put16(fifo_t *fifo, uint16_t element) {
+  // Check if FIFO is full
+  if ((fifo->windex == (fifo->rindex - 1)) ||
+      ((fifo->rindex == 0) && (fifo->windex == (fifo->length - 1)))) {
+    return -1;
+  }
+
+  // atomic FIFO access
+  __disable_irq();
+
+  // Put data into FIFO
+  ((uint16_t *)(fifo->data))[fifo->windex] = element;
+
+  // Increment pointer
+  fifo->windex++;
+  if (fifo->windex == fifo->length) {
+    fifo->windex = 0;
+  }
+
+  __enable_irq();
+
+  return 0;
+}
+
+/****************************************************************************/
+int fifo_get16(fifo_t *fifo, uint16_t *element) {
+  // Check if FIFO is empty
+  if (fifo->rindex == fifo->windex)
+    return -1;
+
+  // atomic FIFO access
+  __disable_irq();
+
+  // Get data from FIFO
+  *element = ((uint16_t *)(fifo->data))[fifo->rindex];
+
+  // Increment pointer
+  fifo->rindex++;
+  if (fifo->rindex == fifo->length) {
+    fifo->rindex = 0;
+  }
+
+  __enable_irq();
+
+  return 0;
+}
+
+/****************************************************************************/
+int fifo_put32(fifo_t *fifo, uint32_t element) {
+  // Check if FIFO is full
+  if ((fifo->windex == (fifo->rindex - 1)) ||
+      ((fifo->rindex == 0) && (fifo->windex == (fifo->length - 1)))) {
+    return -1;
+  }
+
+  // atomic FIFO access
+  __disable_irq();
+
+  // Put data into FIFO
+  ((uint32_t *)(fifo->data))[fifo->windex] = element;
+
+  // Increment pointer
+  fifo->windex++;
+  if (fifo->windex == fifo->length) {
+    fifo->windex = 0;
+  }
+
+  __enable_irq();
+
+  return 0;
+}
+
+/****************************************************************************/
+int fifo_get32(fifo_t *fifo, uint32_t *element) {
+  // Check if FIFO is empty
+  if (fifo->rindex == fifo->windex)
+    return -1;
+
+  // atomic FIFO access
+  __disable_irq();
+
+  // Get data from FIFO
+  *element = ((uint32_t *)(fifo->data))[fifo->rindex];
+
+  // Increment pointer
+  fifo->rindex++;
+  if (fifo->rindex == fifo->length) {
+    fifo->rindex = 0;
+  }
+
+  __enable_irq();
+
+  return 0;
+}
+/****************************************************************************/
+void fifo_clear(fifo_t *fifo) {
+  // atomic FIFO access
+  __disable_irq();
+
+  fifo->rindex = 0;
+  fifo->windex = 0;
+
+  __enable_irq();
+}
+
+/****************************************************************************/
+int fifo_empty(fifo_t *fifo) { return (fifo->rindex == fifo->windex); }
+
+/****************************************************************************/
+int fifo_full(fifo_t *fifo) {
+  int retval;
+
+  // atomic FIFO access
+  __disable_irq();
+  retval = ((fifo->windex == (fifo->rindex - 1)) ||
+            ((fifo->rindex == 0) && (fifo->windex == (fifo->length - 1))));
+  __enable_irq();
+
+  return retval;
+}
+
+/****************************************************************************/
+unsigned int fifo_level(fifo_t *fifo) {
+  uint16_t value;
+
+  // atomic FIFO access
+  __disable_irq();
+
+  if (fifo->windex >= fifo->rindex) {
+    value = fifo->windex - fifo->rindex;
+  } else {
+    value = fifo->length - fifo->rindex + fifo->windex;
+  }
+
+  __enable_irq();
+
+  return value;
+}
+
+/****************************************************************************/
+unsigned int fifo_remaining(fifo_t *fifo) {
+  uint16_t value;
+
+  // atomic FIFO access
+  __disable_irq();
+
+  if (fifo->rindex > fifo->windex) {
+    value = fifo->rindex - fifo->windex - 1;
+  } else {
+    value = fifo->length - fifo->windex + fifo->rindex - 1;
+  }
+
+  __enable_irq();
+
+  return value;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/e4a10ed6eb92/HSP/RpcServer/RpcFifo.h	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,137 @@
+/*******************************************************************************
+ * Copyright (C) 2016 Maxim Integrated Products, Inc., All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+ * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Except as contained in this notice, the name of Maxim Integrated
+ * Products, Inc. shall not be used except as stated in the Maxim Integrated
+ * Products, Inc. Branding Policy.
+ *
+ * The mere transfer of this software does not imply any licenses
+ * of trade secrets, proprietary technology, copyrights, patents,
+ * trademarks, maskwork rights, or any other form of intellectual
+ * property whatsoever. Maxim Integrated Products, Inc. retains all
+ * ownership rights.
+ *
+ ********************************************************************************
+ */
+#ifndef _RPCFIFO_H_
+#define _RPCFIFO_H_
+
+#include <stdint.h>
+
+/// Structure used for FIFO management
+typedef struct {
+  unsigned int length; ///< FIFO size (number of elements)
+  void *data;          ///< pointer to the FIFO buffer
+  unsigned int rindex; ///< current FIFO read index
+  unsigned int windex; ///< current FIFO write index
+} fifo_t;
+
+/**
+* @param    fifo     FIFO on which to perform the operation
+* @param    mem      memory buffer to use for FIFO element storage
+* @param    length   number of elements that the memory buffer can contain
+* @returns  0 if successful, -1 upon failure
+*/
+void fifo_init(fifo_t *fifo, void *mem, unsigned int length);
+
+/**
+* @brief    Adds and 8-bit element to the FIFO
+* @param    fifo     FIFO on which to perform the operation
+* @param    element  element to add to the FIFO
+* @returns  0 if successful, -1 upon failure
+*/
+int fifo_put8(fifo_t *fifo, uint8_t element);
+
+/**
+* @brief    Gets the next 8-bit element to the FIFO
+* @param    fifo     FIFO on which to perform the operation
+* @param    element  pointer to where to store the element from the FIFO
+* @returns  0 if successful, -1 upon failure
+*/
+int fifo_get8(fifo_t *fifo, uint8_t *element);
+
+/**
+* @brief    Adds the next 16-bit element to the FIFO
+* @param    fifo     FIFO on which to perform the operation
+* @param    element  element to add to the FIFO
+* @returns  0 if successful, -1 upon failure
+*/
+int fifo_put16(fifo_t *fifo, uint16_t element);
+
+/**
+* @brief    Gets the next 16-bit element to the FIFO
+* @param    fifo     FIFO on which to perform the operation
+* @param    element  pointer to where to store the element from the FIFO
+* @returns  0 if successful, -1 upon failure
+*/
+int fifo_get16(fifo_t *fifo, uint16_t *element);
+
+/**
+* @brief    Adds the next 16-bit element to the FIFO
+* @param    fifo     FIFO on which to perform the operation
+* @param    element  element to add to the FIFO
+* @returns  0 if successful, -1 upon failure
+*/
+int fifo_put32(fifo_t *fifo, uint32_t element);
+
+/**
+* @brief    Gets the next 16-bit element to the FIFO
+* @param    fifo     FIFO on which to perform the operation
+* @param    element  pointer to where to store the element from the FIFO
+* @returns  0 if successful, -1 upon failure
+*/
+int fifo_get32(fifo_t *fifo, uint32_t *element);
+
+/**
+* @brief    Immediately resets the FIFO to the empty state
+* @param    fifo   FIFO on which to perform the operation
+*/
+void fifo_clear(fifo_t *fifo);
+
+/**
+* @brief    Determines if the FIFO is empty
+* @param    fifo   FIFO on which to perform the operation
+* @returns  #TRUE if FIFO is empty, #FALSE otherwise
+*/
+int fifo_empty(fifo_t *fifo);
+
+/**
+* @brief    FIFO status function
+* @param    fifo   FIFO on which to perform the operation
+* @returns  #TRUE if FIFO is full, #FALSE otherwise
+*/
+int fifo_full(fifo_t *fifo);
+
+/**
+* @brief    FIFO status function
+* @param    fifo   FIFO on which to perform the operation
+* @returns  the number of elements currently in the FIFO
+*/
+unsigned int fifo_level(fifo_t *fifo);
+
+/**
+* @brief    FIFO status function
+* @param    fifo   FIFO on which to perform the operation
+* @returns  the remaining elements that can be added to the FIFO
+*/
+unsigned int fifo_remaining(fifo_t *fifo);
+
+#endif // _RPCFIFO_H_ 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/e4a10ed6eb92/HSP/RpcServer/RpcServer.cpp	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,445 @@
+/*******************************************************************************
+ * Copyright (C) 2016 Maxim Integrated Products, Inc., All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+ * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Except as contained in this notice, the name of Maxim Integrated
+ * Products, Inc. shall not be used except as stated in the Maxim Integrated
+ * Products, Inc. Branding Policy.
+ *
+ * The mere transfer of this software does not imply any licenses
+ * of trade secrets, proprietary technology, copyrights, patents,
+ * trademarks, maskwork rights, or any other form of intellectual
+ * property whatsoever. Maxim Integrated Products, Inc. retains all
+ * ownership rights.
+ *******************************************************************************
+ */
+#include "RpcServer.h"
+#include "StringInOut.h"
+#include "StringHelper.h"
+#include "MAX30001_RPC.h"
+#include "MAX30101_RPC.h"
+#include "LIS2DH_RPC.h"
+#include "Logging_RPC.h"
+#include "Peripherals.h"
+#include "I2C_RPC.h"
+#include "BMP280_RPC.h"
+#include "MAX30205_RPC.h"
+#include "HspLed_RPC.h"
+#include "S25FS512_RPC.h"
+#include "Testing_RPC.h"
+#include "MAX14720_RPC.h"
+#include "RpcDeclarations.h"
+#include "Device_Logging.h"
+
+/// define the version string that is reported with a RPC "ReadVer" command
+#define FW_VERSION_STRING "HSP FW Version 3.0.0 10/14/16"
+
+char args[32][32];
+char results[32][32];
+
+/// define a fifo for incoming USB data
+static fifo_t fifo;
+/// define a buffer for incoming USB data
+static uint8_t fifoBuffer[128];
+/// define stream out fifo
+static fifo_t fifoStreamOut;
+/// allocate a large fifo buffer for streaming out
+static uint32_t streamOutBuffer[0xC000 / 4];
+
+/// define a device log for the BMP280, keeps track of mission and loggin status
+Device_Logging *bmp280_Logging;
+/// define a device log for the MAX30205 (instance 0), keeps track of mission
+/// and loggin status
+Device_Logging *MAX30205_0_Logging;
+/// define a device log for the MAX30205 (instance 1), keeps track of mission
+/// and loggin status
+Device_Logging *MAX30205_1_Logging;
+
+//******************************************************************************
+fifo_t *GetUSBIncomingFifo(void) { return &fifo; }
+
+//******************************************************************************
+fifo_t *GetStreamOutFifo(void) { return &fifoStreamOut; }
+
+//******************************************************************************
+int System_ReadVer(char argStrs[32][32], char replyStrs[32][32]) {
+  strcpy(replyStrs[0], FW_VERSION_STRING);
+  strcpy(replyStrs[1], "\0");
+  return 0;
+}
+
+//******************************************************************************
+int System_ReadBuildTime(char argStrs[32][32], char replyStrs[32][32]) {
+  // strcpy(replyStrs[0],buildTime);
+  // strcpy(replyStrs[1],"\0");
+  return 0;
+}
+
+//******************************************************************************
+int System_SystemCoreClock(char argStrs[32][32], char replyStrs[32][32]) {
+  sprintf(replyStrs[0], "SystemCoreClock = %d", SystemCoreClock);
+  strcpy(replyStrs[1], "\0");
+  return 0;
+}
+
+//******************************************************************************
+int System_GetTimestamp(char argStrs[32][32], char replyStrs[32][32]) {
+  sprintf(replyStrs[0], "GetTimestamp = %d", 0);
+  strcpy(replyStrs[1], "\0");
+  return 0;
+}
+
+static struct RPC_Object RPC_Procedures = {NULL, NULL};
+
+//******************************************************************************
+void RPC_addProcedure(struct RPC_registeredProcedure *procedure) {
+  struct RPC_Object *obj = &RPC_Procedures;
+  if (obj->last != NULL) {
+    obj->last->next = procedure;
+  }
+  if (obj->head == NULL) {
+    obj->head = procedure;
+  }
+  procedure->next = NULL;
+  obj->last = procedure;
+}
+
+//******************************************************************************
+void RPC_init(void) {
+  bmp280_Logging = new Device_Logging();
+  MAX30205_0_Logging = new Device_Logging();
+  MAX30205_1_Logging = new Device_Logging();
+
+  fifo_init(&fifo, fifoBuffer, sizeof(fifoBuffer));
+  fifo_init(&fifoStreamOut, streamOutBuffer,
+            sizeof(streamOutBuffer) / sizeof(uint32_t));
+
+  // I2c
+  RPC_addProcedure(&Define_I2c_WriteRead);
+
+  // MAX30101
+  RPC_addProcedure(&Define_MAX30101_WriteReg);
+  RPC_addProcedure(&Define_MAX30101_ReadReg);
+  RPC_addProcedure(&Define_MAX30101_SpO2mode_Init);
+  RPC_addProcedure(&Define_MAX30101_HRmode_Init);
+  RPC_addProcedure(&Define_MAX30101_Multimode_init);
+  RPC_addProcedure(&Define_MAX30101_SpO2mode_InitStart);
+  RPC_addProcedure(&Define_MAX30101_HRmode_InitStart);
+  RPC_addProcedure(&Define_MAX30101_Multimode_InitStart);
+  RPC_addProcedure(&Define_MAX30101_SpO2mode_stop);
+  RPC_addProcedure(&Define_MAX30101_HRmode_stop);
+  RPC_addProcedure(&Define_MAX30101_Multimode_stop);
+
+  // MAX30001
+  RPC_addProcedure(&Define_MAX30001_WriteReg);
+  RPC_addProcedure(&Define_MAX30001_ReadReg);
+  RPC_addProcedure(&Define_MAX30001_Start);
+  RPC_addProcedure(&Define_MAX30001_Stop);
+  RPC_addProcedure(&Define_MAX30001_Enable_ECG_LeadON);
+  RPC_addProcedure(&Define_MAX30001_Enable_BIOZ_LeadON);
+  RPC_addProcedure(&Define_MAX30001_Read_LeadON);
+  RPC_addProcedure(&Define_MAX30001_StartTest);
+  RPC_addProcedure(&Define_MAX30001_INT_assignment);
+  RPC_addProcedure(&Define_MAX30001_Rbias_FMSTR_Init);
+  RPC_addProcedure(&Define_MAX30001_CAL_InitStart);
+  RPC_addProcedure(&Define_MAX30001_ECG_InitStart);
+  RPC_addProcedure(&Define_MAX30001_ECGFast_Init);
+  RPC_addProcedure(&Define_MAX30001_PACE_InitStart);
+  RPC_addProcedure(&Define_MAX30001_BIOZ_InitStart);
+  RPC_addProcedure(&Define_MAX30001_RtoR_InitStart);
+  RPC_addProcedure(&Define_MAX30001_Stop_ECG);
+  RPC_addProcedure(&Define_MAX30001_Stop_PACE);
+  RPC_addProcedure(&Define_MAX30001_Stop_BIOZ);
+  RPC_addProcedure(&Define_MAX30001_Stop_RtoR);
+  RPC_addProcedure(&Define_MAX30001_Stop_Cal);
+
+  // Logging
+  RPC_addProcedure(&Define_Logging_StartMissionDefine);
+  RPC_addProcedure(&Define_Logging_AppendMissionCmd);
+  RPC_addProcedure(&Define_Logging_EndMissionDefine);
+  RPC_addProcedure(&Define_Logging_WriteMission);
+  RPC_addProcedure(&Define_Logging_ReadMission);
+  RPC_addProcedure(&Define_Logging_EraseMission);
+  RPC_addProcedure(&Define_Logging_EraseWrittenSectors);
+  RPC_addProcedure(&Define_Logging_StartLoggingUsb);
+  RPC_addProcedure(&Define_Logging_StartLoggingFlash);
+  RPC_addProcedure(&Define_Logging_GetLastWrittenPage);
+  RPC_addProcedure(&Define_Logging_Start);
+
+  // LIS2HD
+  RPC_addProcedure(&Define_LIS2DH_InitStart);
+  RPC_addProcedure(&Define_LIS2DH_ReadReg);
+  RPC_addProcedure(&Define_LIS2DH_WriteReg);
+  RPC_addProcedure(&Define_LIS2DH_Stop);
+
+  // BMP280
+  RPC_addProcedure(&Define_BMP280_InitStart);
+
+  // MAX30205 and MAX31725 Alias
+  RPC_addProcedure(&Define_MAX30205_1_InitStart);
+  RPC_addProcedure(&Define_MAX30205_2_InitStart);
+  RPC_addProcedure(&Define_MAX31725_1_InitStart);
+  RPC_addProcedure(&Define_MAX31725_2_InitStart);
+
+  // led
+  RPC_addProcedure(&Define_Led_On);
+  RPC_addProcedure(&Define_Led_Off);
+  RPC_addProcedure(&Define_Led_BlinkHz);
+  RPC_addProcedure(&Define_Led_BlinkPattern);
+
+  // S25FS512
+  RPC_addProcedure(&Define_S25FS512_ReadId);
+  RPC_addProcedure(&Define_S25FS512_ReadPagesBinary);
+  RPC_addProcedure(&Define_S25FS512_Reset);
+  RPC_addProcedure(&Define_S25FS512_EnableHWReset);
+  RPC_addProcedure(&Define_S25FS512_SpiWriteRead);
+  RPC_addProcedure(&Define_S25FS512_SpiWriteRead4Wire);
+
+  // Testing
+  RPC_addProcedure(&Define_Testing_Test_S25FS512);
+  RPC_addProcedure(&Define_Testing_Test_BMP280);
+  RPC_addProcedure(&Define_Testing_Test_LIS2DH);
+  RPC_addProcedure(&Define_Testing_Test_LSM6DS3);
+  RPC_addProcedure(&Define_Testing_Test_MAX30205_1);
+  RPC_addProcedure(&Define_Testing_Test_MAX30205_2);
+  RPC_addProcedure(&Define_Testing_Test_MAX30101);
+  RPC_addProcedure(&Define_Testing_Test_MAX30001);
+  RPC_addProcedure(&Define_Testing_Test_EM9301);
+
+  // System
+  RPC_addProcedure(&Define_System_ReadVer);
+  RPC_addProcedure(&Define_System_ReadBuildTime);
+
+  // MAX14720
+  RPC_addProcedure(&Define_MAX14720_ReadBoostVSet);
+  RPC_addProcedure(&Define_MAX14720_WriteBoostVSet);
+  RPC_addProcedure(&Define_MAX14720_ReadReg);
+  RPC_addProcedure(&Define_MAX14720_WriteReg);
+}
+
+//******************************************************************************
+struct RPC_registeredProcedure *RPC_lookup(char *objectName, char *methodName) {
+  struct RPC_registeredProcedure *ptr;
+  // lookup all registered methods
+  ptr = RPC_Procedures.head;
+  while (ptr != NULL) {
+    if (strcmp(ptr->objectName, objectName) == 0 &&
+        strcmp(ptr->methodName, methodName) == 0) {
+      // we found a match... return with it
+      return ptr;
+    }
+    ptr = ptr->next;
+  }
+  return NULL;
+}
+
+//******************************************************************************
+char *GetToken(char *inStr, char *outStr, int start, char ch) {
+  int i;
+  int index = 0;
+  int length = strlen(inStr);
+  for (i = start; i < length; i++) {
+    if (inStr[i] != ch) {
+      outStr[index++] = inStr[i];
+    } else {
+      break;
+    }
+  }
+  outStr[index++] = 0;
+  return outStr;
+}
+
+//******************************************************************************
+void SendCommandList(char *reply) {
+  struct RPC_registeredProcedure *ptr;
+  reply[0] = 0;
+  ptr = RPC_Procedures.head;
+  while (ptr != NULL) {
+    strcat(reply, "/");
+    strcat(reply, ptr->objectName);
+    strcat(reply, "/");
+    strcat(reply, ptr->methodName);
+    strcat(reply, ",");
+    ptr = ptr->next;
+  }
+  strcat(reply, "\r\n");
+}
+
+//******************************************************************************
+int CheckForDoubleQuote(char *str) {
+  int doubleQuoteFound;
+  // scan through arguments, see if there is a double quote for a string
+  // argument
+  doubleQuoteFound = 0;
+  while (*str != 0) {
+    if (*str == '\"') {
+      doubleQuoteFound = 1;
+      break;
+    }
+    str++;
+  }
+  return doubleQuoteFound;
+}
+
+//******************************************************************************
+void ExtractDoubleQuoteStr(char *src, char *dst) {
+  int start;
+
+  dst[0] = 0;
+  start = 0;
+  while (*src != 0) {
+    // look for start
+    if ((*src == '\"') && (start == 0)) {
+      start = 1;
+      src++;
+      continue;
+    }
+    // look for end
+    if ((*src == '\"') && (start == 1)) {
+      *dst = 0; // terminate the string
+      break;
+    }
+    if (start == 1) {
+      *dst = *src;
+      dst++;
+    }
+    src++;
+  }
+}
+
+//******************************************************************************
+void RPC_call_test(void) {
+  int doubleQuoteFound;
+  char doubleQuoteStr[64];
+  char *request = "/Logging/AppendMissionCmd \"BMP280 InitStart 1\"";
+
+  // scan through arguments, see if there is a double quote for a string
+  // argument
+  doubleQuoteFound = CheckForDoubleQuote(request);
+  if (doubleQuoteFound) {
+    ExtractDoubleQuoteStr(request, doubleQuoteStr);
+  }
+}
+
+//******************************************************************************
+void RPC_call(char *request, char *reply) {
+  const char slash[2] = "/";
+  const char space[2] = " ";
+  char *objectName;
+  char *methodName;
+  char doubleQuoteStr[64];
+  char requestCpy[128];
+  char *token;
+  int argIndex;
+  int resultIndex;
+  int doubleQuoteFound;
+  struct RPC_registeredProcedure *procedurePtr;
+
+  // clear out the reply
+  reply[0] = 0;
+  // copy the request for scanning and extraction later
+  strcpy(requestCpy, request);
+  // check for beginning forward slash
+  if (request[0] != '/') {
+    return;
+  }
+  // check for only a forward slash
+  if (request[0] == '/' && request[1] == 0) {
+    SendCommandList(reply);
+    return;
+  }
+  strcat(request, " ");
+  // get the object name
+  token = strtok(request, slash);
+  // token = GetToken(request, tokenBuffer, 1, '/');
+  objectName = token;
+  if (objectName == NULL)
+    return; // must have an object name
+  // get the method name
+  token = strtok(NULL, space);
+  methodName = token;
+  if (methodName == NULL)
+    return; // must have a method name
+
+  // scan through arguments, see if there is a double quote for a string
+  // argument
+  doubleQuoteFound = CheckForDoubleQuote(requestCpy);
+
+  if (doubleQuoteFound == 0) {
+    // walk through arguments
+    argIndex = 0;
+    token = strtok(NULL, space);
+    while (token != NULL) {
+      // save this arg in array
+      strcpy(args[argIndex++], token);
+      // read next token arg if any
+      token = strtok(NULL, space);
+    }
+    // terminate the end of the string array with an empty string
+    strcpy(args[argIndex], "\0");
+    strcpy(results[0], "\0");
+  } else {
+    // grab out the double quote string
+    ExtractDoubleQuoteStr(requestCpy, doubleQuoteStr);
+    argIndex = 0;
+    // token = strtok(NULL, quote);
+    strcpy(args[argIndex++], doubleQuoteStr);
+  }
+
+  //
+  // alias the MAX30001 and MAX30003 names
+  //
+  if (strcmp(objectName, MAX30003_NAME) == 0) {
+    strcpy(objectName, MAX30001_NAME);
+  }
+
+  procedurePtr = RPC_lookup(objectName, methodName);
+  if (procedurePtr != NULL) {
+    // printf("RPC_call: %s processing\n",requestCpy);
+    procedurePtr->func(args, results);
+  } else {
+    printf("RPC_call: %s not found\n", requestCpy);
+    // printf("Unable to lookup %s %s", objectName, methodName);
+  }
+
+  // loop while (if) there are results to return
+  resultIndex = 0;
+  strcpy(reply, "\0");
+  while (results[resultIndex][0] != '\0') {
+    strcat(reply, results[resultIndex++]);
+    strcat(reply, " ");
+  }
+  strcat(reply, "\r\n");
+}
+
+//******************************************************************************
+void RPC_ProcessCmds(char *cmds) {
+  char cmd[32 * 32];
+  char *ptrCmds;
+  char reply[512];
+  ptrCmds = cmds;
+
+  while (*ptrCmds != 0) {
+    ptrCmds = ParseUntilCRLF(ptrCmds, cmd, sizeof(cmd));
+    if (*cmd != 0) {
+      RPC_call(cmd, reply);
+    }
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/e4a10ed6eb92/HSP/RpcServer/RpcServer.h	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,66 @@
+/*******************************************************************************
+ * Copyright (C) 2016 Maxim Integrated Products, Inc., All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+ * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Except as contained in this notice, the name of Maxim Integrated
+ * Products, Inc. shall not be used except as stated in the Maxim Integrated
+ * Products, Inc. Branding Policy.
+ *
+ * The mere transfer of this software does not imply any licenses
+ * of trade secrets, proprietary technology, copyrights, patents,
+ * trademarks, maskwork rights, or any other form of intellectual
+ * property whatsoever. Maxim Integrated Products, Inc. retains all
+ * ownership rights.
+ *******************************************************************************
+ */
+#ifndef _RPCSERVER_H_
+#define _RPCSERVER_H_
+
+#include "mbed.h"
+#include "RpcFifo.h"
+#include "Device_Logging.h"
+
+/**
+* @brief Reads the Version of the HSP FCache_Writel
+*/
+int System_ReadVer(char argStrs[32][32], char replyStrs[32][32]);
+/**
+* @brief Reads the built time of the RPC FW
+*/
+int System_ReadBuildTime(char argStrs[32][32], char replyStrs[32][32]);
+
+void RPC__init(void);
+void RPC__call(char *request, char *reply);
+fifo_t *GetUSBIncomingFifo(void);
+fifo_t *GetStreamOutFifo(void);
+/**
+* @brief Batch process RPC commands
+*/
+void RPC_ProcessCmds(char *cmds);
+/**
+* @brief Initialize the RPC server with all of the commands that it supports
+*/
+void RPC_init(void);
+/**
+* @brief Initialize the RPC server with all of the commands that it supports
+*/
+void RPC_call(char *request, char *reply);
+
+#endif // _RPCSERVER_H_ 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/e4a10ed6eb92/HSP/RpcServer/Streaming.cpp	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,187 @@
+/*******************************************************************************
+ * Copyright (C) 2016 Maxim Integrated Products, Inc., All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+ * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Except as contained in this notice, the name of Maxim Integrated
+ * Products, Inc. shall not be used except as stated in the Maxim Integrated
+ * Products, Inc. Branding Policy.
+ *
+ * The mere transfer of this software does not imply any licenses
+ * of trade secrets, proprietary technology, copyrights, patents,
+ * trademarks, maskwork rights, or any other form of intellectual
+ * property whatsoever. Maxim Integrated Products, Inc. retains all
+ * ownership rights.
+ *******************************************************************************
+ */
+#include "RpcServer.h"
+#include "RpcFifo.h"
+#include "Streaming.h"
+#include "Peripherals.h"
+#include "Test_MAX30101.h"
+#include "Test_MAX30001.h"
+#include "MAX30001.h"
+#include "MAX30101.h"
+#include "Peripherals.h"
+
+bool streaming = FALSE;
+bool dataLogging = FALSE;
+
+/**
+* @brief Encodes a 0x55 0xAA signature and a simple checksum to the id byte in
+* the 32 bit field
+* @param id Streaming ID
+*/
+uint32_t StreamIdChecksumCalculate(uint32_t id) {
+  uint32_t sum;
+  uint32_t calculated;
+  sum = 0x55;
+  sum += 0xAA;
+  sum += id;
+  sum &= 0xFF;
+  sum = sum << 8;
+  calculated = 0x55AA0000 + sum + id;
+  return calculated;
+}
+
+/**
+* @brief Creates a packet that will be streamed via USB or saved into flash
+* datalog memory
+* @brief the packet created will be inserted into a fifo to be streamed at a
+* later time
+* @param id Streaming ID
+* @param buffer Pointer to a uint32 array that contains the data to include in
+* the packet
+* @param number Number of elements in the buffer
+*/
+void StreamPacketUint32(uint32_t id, uint32_t *buffer, uint32_t number) {
+  uint32_t checksumId;
+  if (streaming == TRUE || dataLogging == TRUE) {
+    checksumId = StreamIdChecksumCalculate(id);
+    StreamFifoId(checksumId);
+    StreamFifoTimeStamp();
+    StreamFifoLength(number);
+    StreamFifoUint32Array(buffer, number);
+  }
+  if (testing_max30001 == 1) {
+    if (id == MAX30001_DATA_ECG)
+      testing_ecg_flags[TESTING_ECG_FLAG] = 1;
+    if (id == MAX30001_DATA_BIOZ)
+      testing_ecg_flags[TESTING_BIOZ_FLAG] = 1;
+    if (id == MAX30001_DATA_PACE)
+      testing_ecg_flags[TESTING_PACE_FLAG] = 1;
+    if (id == MAX30001_DATA_RTOR)
+      testing_ecg_flags[TESTING_RTOR_FLAG] = 1;
+  }
+  if (testing_max30101 == 1) {
+    if (id == (MAX30101_OXIMETER_DATA + 1))
+      testing_max30101_flags[TESTING_HR_FLAG] = 1;
+    if (id == (MAX30101_OXIMETER_DATA + 2))
+      testing_max30101_flags[TESTING_SPO2_FLAG] = 1;
+    if (id == (MAX30101_OXIMETER_DATA + 3))
+      testing_max30101_flags[TESTING_MULTI_FLAG] = 1;
+  }
+}
+
+/**
+* @brief Insert a buffer into the out going fifo
+* @param buffer Array of uint32 to send to the fifo
+* @param len Length of the array
+*/
+int StreamFifoUint32Array(uint32_t buffer[], uint32_t len) {
+  int status;
+  uint32_t i;
+  for (i = 0; i < len; i++) {
+    status = fifo_put32(GetStreamOutFifo(), buffer[i]);
+    if (status == -1) {
+      printf("FIFO_OF!");
+      fflush(stdout);
+      while (1)
+        ;
+    }
+  }
+  return 0;
+}
+
+/**
+* @brief Insert a timestamp into the out going fifo
+*/
+int StreamFifoTimeStamp(void) {
+  int status;
+  // uint32_t timer = timestamp_GetCurrent(); //RTC_GetVal();
+  uint32_t timer = (uint32_t)Peripherals::timestampTimer()->read_us();
+  status = fifo_put32(GetStreamOutFifo(), timer);
+  if (status == -1) {
+    printf("FIFO_OF!");
+    fflush(stdout);
+    while (1)
+      ;
+  }
+  return 0;
+}
+
+/**
+* @brief Insert a packet id into the out going fifo
+* @param id The uint32 packet id
+*/
+int StreamFifoId(uint32_t id) {
+  int status;
+  status = fifo_put32(GetStreamOutFifo(), id);
+  if (status == -1) {
+    printf("FIFO_OF!");
+    fflush(stdout);
+    while (1)
+      ;
+  }
+  return 0;
+}
+
+/**
+* @brief Insert a length value into the out going fifo
+* @param length A uint32 number representing a length
+*/
+int StreamFifoLength(uint32_t length) {
+  int status;
+  status = fifo_put32(GetStreamOutFifo(), length);
+  if (status == -1) {
+    printf("FIFO_OF!");
+    fflush(stdout);
+    while (1)
+      ;
+  }
+  return 0;
+}
+
+/**
+* @brief Return a value that indicates if the system is streaming data
+* @returns Returns a one or zero value
+*/
+uint8_t IsStreaming(void) { return streaming; }
+
+/**
+* @brief Set a flag to indicate if streaming is enabled
+* @param state A one or zero value
+*/
+void SetStreaming(uint8_t state) { streaming = state; }
+
+/**
+* @brief Set a flag to indicate if datalogging is enabled
+* @param state A one or zero value
+*/
+void SetDataLoggingStream(uint8_t state) { dataLogging = state; }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/e4a10ed6eb92/HSP/RpcServer/Streaming.h	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,94 @@
+/*******************************************************************************
+ * Copyright (C) 2016 Maxim Integrated Products, Inc., All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+ * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Except as contained in this notice, the name of Maxim Integrated
+ * Products, Inc. shall not be used except as stated in the Maxim Integrated
+ * Products, Inc. Branding Policy.
+ *
+ * The mere transfer of this software does not imply any licenses
+ * of trade secrets, proprietary technology, copyrights, patents,
+ * trademarks, maskwork rights, or any other form of intellectual
+ * property whatsoever. Maxim Integrated Products, Inc. retains all
+ * ownership rights.
+ *******************************************************************************
+ */
+#ifndef _STREAMING_H_
+#define _STREAMING_H_
+
+#include "mbed.h"
+
+#define PACKET_LIS2DH 0x20
+
+#define PACKET_MAX30205_TEMP_TOP 0x40
+#define PACKET_MAX30205_TEMP_BOTTOM 0x50
+#define PACKET_BMP280_PRESSURE 0x60
+#define PACKET_LSM6DS3_ACCEL 0x70
+#define PACKET_MAX30205_TEMP 0x80
+#define PACKET_NOP 0x90
+
+/**
+* @brief Creates a packet that will be streamed via USB or saved into flash
+* datalog memory
+* @brief the packet created will be inserted into a fifo to be streamed at a
+* later time
+* @param id Streaming ID
+* @param buffer Pointer to a uint32 array that contains the data to include in
+* the packet
+* @param number Number of elements in the buffer
+*/
+void StreamPacketUint32(uint32_t id, uint32_t *buffer, uint32_t number);
+/**
+* @brief Insert a buffer into the out going fifo
+* @param buffer Array of uint32 to send to the fifo
+* @param len Length of the array
+*/
+int StreamFifoUint32Array(uint32_t buffer[], uint32_t len);
+/**
+* @brief Insert a timestamp into the out going fifo
+*/
+int StreamFifoTimeStamp(void);
+/**
+* @brief Insert a packet id into the out going fifo
+* @param id The uint32 packet id
+*/
+int StreamFifoId(uint32_t id);
+/**
+* @brief Return a value that indicates if the system is streaming data
+* @returns Returns a one or zero value
+*/
+uint8_t IsStreaming(void);
+/**
+* @brief Set a flag to indicate if streaming is enabled
+* @param state A one or zero value
+*/
+void SetStreaming(uint8_t state);
+/**
+* @brief Set a flag to indicate if datalogging is enabled
+* @param state A one or zero value
+*/
+void SetDataLoggingStream(uint8_t state);
+/**
+* @brief Insert a length value into the out going fifo
+* @param length A uint32 number representing a length
+*/
+int StreamFifoLength(uint32_t length);
+
+#endif // _STREAMING_H_ 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/e4a10ed6eb92/HSP/RpcServer/StringHelper.cpp	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,240 @@
+/*******************************************************************************
+ * Copyright (C) 2016 Maxim Integrated Products, Inc., All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+ * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Except as contained in this notice, the name of Maxim Integrated
+ * Products, Inc. shall not be used except as stated in the Maxim Integrated
+ * Products, Inc. Branding Policy.
+ *
+ * The mere transfer of this software does not imply any licenses
+ * of trade secrets, proprietary technology, copyrights, patents,
+ * trademarks, maskwork rights, or any other form of intellectual
+ * property whatsoever. Maxim Integrated Products, Inc. retains all
+ * ownership rights.
+ *******************************************************************************
+ */
+#include "mbed.h"
+#include "StringHelper.h"
+
+/**
+* @brief Process an array of hex alpha numeric strings representing arguments of
+* type uint8
+* @param args Array of strings to process
+* @param argsUintPtr Pointer of uint8 to save converted arguments
+* @param numberOf Number of strings to convert
+*/
+void ProcessArgs(char args[32][32], uint8_t *argsUintPtr, int numberOf) {
+  int i;
+  int val;
+  for (i = 0; i < numberOf; i++) {
+    sscanf(args[i], "%x", &val);
+    argsUintPtr[i] = (uint8_t)val;
+  }
+}
+
+/**
+* @brief Process an array of hex alpha numeric strings representing arguments of
+* type uint32
+* @param args Array of strings to process
+* @param argsUintPtr Pointer of uint32 to save converted arguments
+* @param numberOf Number of strings to convert
+*/
+void ProcessArgs32(char args[32][32], uint32_t *argsUintPtr, int numberOf) {
+  int i;
+  int val;
+  for (i = 0; i < numberOf; i++) {
+    sscanf(args[i], "%x", &val);
+    argsUintPtr[i] = val;
+  }
+}
+
+/**
+* @brief Process an array of decimal numeric strings representing arguments of
+* type uint32
+* @param args Array of strings to process
+* @param argsUintPtr Pointer of uint32 to save converted arguments
+* @param numberOf Number of strings to convert
+*/
+void ProcessArgs32Dec(char args[32][32], uint32_t *argsUintPtr, int numberOf) {
+  int i;
+  int val;
+  for (i = 0; i < numberOf; i++) {
+    sscanf(args[i], "%d", &val);
+    argsUintPtr[i] = val;
+  }
+}
+
+/**
+* @brief Parse a single string in decimal format to a uint32 number
+* @param str String to process
+* @returns Returns the converted number of type uint32
+*/
+uint32_t ParseAsciiDecU32(char *str) {
+  uint32_t val;
+  sscanf(str, "%d", &val);
+  return val;
+}
+
+/**
+* @brief Parse a single string in hex format to a uint32 number
+* @param str String to process
+* @returns Returns the converted number of type uint32
+*/
+uint32_t ParseAsciiHexU32(char *str) {
+  uint32_t val;
+  sscanf(str, "%x", &val);
+  return val;
+}
+
+/**
+* @brief Process a string that is "embedded" within another string using the /"
+* delimiters
+* @brief Extract the string
+* @param str String to process
+* @returns Returns the string
+*/
+void ProcessString(char args[32][32], uint8_t *str, int numberOf) {
+  int i;
+  int start;
+  uint8_t *ptr;
+  uint8_t *strPtr;
+  ptr = (uint8_t *)args;
+  strPtr = str;
+  start = 0;
+  for (i = 0; i < numberOf; i++) {
+    if ((start == 0) && (*ptr == '/"')) {
+      start = 1;
+      ptr++;
+      continue;
+    }
+    if ((start == 1) && (*ptr == '/"')) {
+      break;
+    }
+    if (start == 1) {
+      *strPtr = *ptr;
+      strPtr++;
+    }
+    ptr++;
+  }
+  // terminate the string
+  *strPtr = 0;
+}
+
+/**
+* @brief Parse an incoming string until a CRLF is encountered, dst will contain
+* the parsed string
+* @param src source string to process
+* @param dst destination string to contain the parsed incoming string
+* @param length length of incoming src string
+* @returns updated pointer in src string
+*/
+char *ParseUntilCRLF(char *src, char *dst, int length) {
+  int i;
+  char *srcPtr;
+
+  srcPtr = src;
+  i = 0;
+  *dst = 0;
+  while ((*srcPtr != 0) && (*srcPtr != 13)) {
+    dst[i] = *srcPtr;
+    i++;
+    if (i >= length)
+      break;
+    srcPtr++;
+  }
+  if (*srcPtr == 13)
+    srcPtr++;
+  if (*srcPtr == 10)
+    srcPtr++;
+  dst[i] = 0; // terminate the string
+  return srcPtr;
+}
+
+/**
+* @brief Parse an incoming string hex value into an 8-bit value
+* @param str string to process
+* @returns 8-bit byte that is parsed from the string
+*/
+uint8_t StringToByte(char str[32]) {
+  int val;
+  uint8_t byt;
+  sscanf(str, "%x", &val);
+  byt = (uint8_t)val;
+  return byt;
+}
+
+/**
+* @brief Parse an incoming string hex value into 32-bit value
+* @param str string to process
+* @returns 32-bit value that is parsed from the string
+*/
+uint32_t StringToInt(char str[32]) {
+  int val;
+  uint32_t byt;
+  sscanf(str, "%x", &val);
+  byt = (uint32_t)val;
+  return byt;
+}
+
+/**
+* @brief Format a binary 8-bit array into a string
+* @param uint8Ptr byte buffer to process
+* @param numberOf number of bytes in the buffer
+* @param reply an array of strings to place the converted array values into
+*/
+void FormatReply(uint8_t *uint8Ptr, int numberOf, char reply[32][32]) {
+  int i;
+  for (i = 0; i < numberOf; i++) {
+    sprintf(reply[i], "%02X", uint8Ptr[i]);
+  }
+  strcpy(reply[i], "\0");
+}
+
+/**
+* @brief Format a binary 32-bit array into a string
+* @param uint32Ptr 32-bit value buffer to process
+* @param numberOf number of values in the buffer
+* @param reply an array of strings to place the converted array values into
+*/
+void FormatReply32(uint32_t *uint32Ptr, int numberOf, char reply[32][32]) {
+  int i;
+  for (i = 0; i < numberOf; i++) {
+    sprintf(reply[i], "%02X", uint32Ptr[i]);
+  }
+  strcpy(reply[i], "\0");
+}
+
+/**
+* @brief Format a binary 8-bit array into a string
+* @param data 8-bit value buffer to process
+* @param length number of values in the buffer
+* @param str output string buffer
+* @return output string
+*/
+char *BytesToHexStr(uint8_t *data, uint32_t length, char *str) {
+  uint32_t i;
+  char tmpStr[8];
+  str[0] = 0;
+  for (i = 0; i < length; i++) {
+    sprintf(tmpStr, "%02X ", data[i]);
+    strcat(str, tmpStr);
+  }
+  return str;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/e4a10ed6eb92/HSP/RpcServer/StringHelper.h	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,118 @@
+/*******************************************************************************
+ * Copyright (C) 2016 Maxim Integrated Products, Inc., All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+ * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Except as contained in this notice, the name of Maxim Integrated
+ * Products, Inc. shall not be used except as stated in the Maxim Integrated
+ * Products, Inc. Branding Policy.
+ *
+ * The mere transfer of this software does not imply any licenses
+ * of trade secrets, proprietary technology, copyrights, patents,
+ * trademarks, maskwork rights, or any other form of intellectual
+ * property whatsoever. Maxim Integrated Products, Inc. retains all
+ * ownership rights.
+ *******************************************************************************
+ */
+#ifndef _STRINGHELPER_H_
+#define _STRINGHELPER_H_
+
+#include "mbed.h"
+
+/**
+* @brief Process an array of hex alpha numeric strings representing arguments of
+* type uint8
+* @param args Array of strings to process
+* @param argsUintPtr Pointer of uint8 to save converted arguments
+* @param numberOf Number of strings to convert
+*/
+void ProcessArgs(char args[32][32], uint8_t *argsUintPtr, int numberOf);
+/**
+* @brief Format a binary 8-bit array into a string
+* @param uint8Ptr byte buffer to process
+* @param numberOf number of bytes in the buffer
+* @param reply an array of strings to place the converted array values into
+*/
+void FormatReply(uint8_t *uint8Ptr, int numberOf, char reply[32][32]);
+/**
+* @brief Process an array of hex alpha numeric strings representing arguments of
+* type uint32
+* @param args Array of strings to process
+* @param argsUintPtr Pointer of uint32 to save converted arguments
+* @param numberOf Number of strings to convert
+*/
+void ProcessArgs32(char args[32][32], uint32_t *argsUintPtr, int numberOf);
+/**
+* @brief Process an array of decimal numeric strings representing arguments of
+* type uint32
+* @param args Array of strings to process
+* @param argsUintPtr Pointer of uint32 to save converted arguments
+* @param numberOf Number of strings to convert
+*/
+void ProcessArgs32Dec(char args[32][32], uint32_t *argsUintPtr, int numberOf);
+/**
+* @brief Format a binary 32-bit array into a string
+* @param uint32Ptr 32-bit value buffer to process
+* @param numberOf number of values in the buffer
+* @param reply an array of strings to place the converted array values into
+*/
+void FormatReply32(uint32_t *uint32Ptr, int numberOf, char reply[32][32]);
+/**
+* @brief Parse an incoming string hex value into an 8-bit value
+* @param str string to process
+* @returns 8-bit byte that is parsed from the string
+*/
+uint8_t StringToByte(char str[32]);
+/**
+* @brief Parse an incoming string hex value into 32-bit value
+* @param str string to process
+* @returns 32-bit value that is parsed from the string
+*/
+uint32_t StringToInt(char str[32]);
+/**
+* @brief Parse a single string in decimal format to a uint32 number
+* @param str String to process
+* @returns Returns the converted number of type uint32
+*/
+uint32_t ParseAsciiDecU32(char *str);
+/**
+* @brief Parse a single string in hex format to a uint32 number
+* @param str String to process
+* @returns Returns the converted number of type uint32
+*/
+uint32_t ParseAsciiHexU32(char *str);
+/**
+* @brief Format a binary 8-bit array into a string
+* @param data 8-bit value buffer to process
+* @param length number of values in the buffer
+* @param str output string buffer
+* @return output string
+*/
+char *BytesToHexStr(uint8_t *data, uint32_t length, char *str);
+/**
+* @brief Parse an incoming string until a CRLF is encountered, dst will contain
+* the parsed string
+* @param src source string to process
+* @param dst destination string to contain the parsed incoming string
+* @param length length of incoming src string
+* @returns updated pointer in src string
+*/
+char *ParseUntilCRLF(char *src, char *dst, int length);
+
+#endif // _STRINGHELPER_H_
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/e4a10ed6eb92/HSP/RpcServer/StringInOut.cpp	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,195 @@
+/*******************************************************************************
+ * Copyright (C) 2016 Maxim Integrated Products, Inc., All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+ * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Except as contained in this notice, the name of Maxim Integrated
+ * Products, Inc. shall not be used except as stated in the Maxim Integrated
+ * Products, Inc. Branding Policy.
+ *
+ * The mere transfer of this software does not imply any licenses
+ * of trade secrets, proprietary technology, copyrights, patents,
+ * trademarks, maskwork rights, or any other form of intellectual
+ * property whatsoever. Maxim Integrated Products, Inc. retains all
+ * ownership rights.
+ *******************************************************************************
+ */
+#include "mbed.h"
+#include "USBSerial.h"
+#include "RpcFifo.h"
+#include "RpcServer.h"
+#include "StringInOut.h"
+#include "Peripherals.h"
+
+/// a running index that keeps track of where an incoming string has been
+/// buffered to
+static int lineBuffer_index = 0;
+/// a flag that keeps track of the state of accumulating a string
+static int getLine_State = GETLINE_WAITING;
+
+/**
+* @brief Place incoming USB characters into a fifo
+* @param data_IN buffer of characters
+* @param len length of data
+*/
+int fifoIncomingChars(uint8_t data_IN[], unsigned int len) {
+  int i;
+  for (i = 0; i < len; i++) {
+    fifo_put8(GetUSBIncomingFifo(), data_IN[i]);
+  }
+  return 0;
+}
+
+/**
+* @brief Check the USB incoming fifo to see if there is data to be read
+* @return 1 if there is data to be read, 0 if data is not available
+*/
+int isReadReady(void) {
+  if (fifo_empty(GetUSBIncomingFifo()) == 0)
+    return 1;
+  return 0;
+}
+
+/**
+* @brief Clear the incoming USB read fifo
+*/
+void clearOutReadFifo(void) { fifo_clear(GetUSBIncomingFifo()); }
+
+/**
+* @brief Block until a character can be read from the USB
+* @return the character read
+*/
+char getch(void) {
+  uint8_t ch;
+  // block until char is ready
+  while (isReadReady() == 0) {
+  }
+  // read a char from buffer
+  fifo_get8(GetUSBIncomingFifo(), &ch);
+  return ch;
+}
+
+/**
+* @brief Place incoming USB characters into a fifo
+* @param lineBuffer buffer to place the incoming characters
+* @param bufferLength length of buffer
+* @return GETLINE_WAITING if still waiting for a CRLF, GETLINE_DONE
+*/
+int getLine(char *lineBuffer, int bufferLength) {
+  uint8_t ch;
+
+  USBSerial *serial = Peripherals::usbSerial();
+  if (getLine_State == GETLINE_DONE) {
+    getLine_State = GETLINE_WAITING;
+  }
+  if (serial->available() != 0) {
+    ch = serial->_getc();
+    if (ch != 0x0A && ch != 0x0D) {
+      lineBuffer[lineBuffer_index++] = ch;
+    }
+    if (ch == 0x0D) {
+      lineBuffer[lineBuffer_index++] = 0;
+      lineBuffer_index = 0;
+      getLine_State = GETLINE_DONE;
+    }
+    if (lineBuffer_index > bufferLength) {
+      lineBuffer[bufferLength - 1] = 0;
+      getLine_State = GETLINE_DONE;
+    }
+  }
+  return getLine_State;
+}
+
+/**
+* @brief Block until a fixed number of characters has been accumulated from the
+* incoming USB
+* @param lineBuffer buffer to place the incoming characters
+* @param maxLength length of buffer
+*/
+void getStringFixedLength(uint8_t *lineBuffer, int maxLength) {
+  uint8_t ch;
+  int index = 0;
+  // block until maxLength is captured
+  while (1) {
+    ch = getch();
+    lineBuffer[index++] = ch;
+    if (index == maxLength)
+      return;
+  }
+}
+
+/**
+* @brief Output a string out the USB serial port
+* @param str output this str the USB channel
+*/
+int putStr(const char *str) {
+  Peripherals::usbSerial()->printf("%s", str); // fflush(stdout);
+  // uint8_t *ptr;
+  // uint8_t buffer[256];
+  // int index = 0;
+  /*	int length;
+          ptr = (uint8_t *)str;
+          length = strlen(str);
+
+          Peripherals::usbSerial()->writeBlock(ptr,length);	*/
+  return 0;
+}
+
+/**
+* @brief Outut an array of bytes out the USB serial port
+* @param data buffer to output
+* @param length length of buffer
+*/
+int putBytes(uint8_t *data, uint32_t length) {
+  int sendThis = 64;
+  int sent = 0;
+  int thisLeft;
+  uint8_t *ptr = data;
+  if (length < 64)
+    sendThis = length;
+  do {
+    Peripherals::usbSerial()->writeBlock(ptr, sendThis);
+    sent += sendThis;
+    ptr += sendThis;
+    thisLeft = length - sent;
+    sendThis = 64;
+    if (thisLeft < 64)
+      sendThis = thisLeft;
+  } while (sent != length);
+  return 0;
+}
+
+/**
+* @brief Outut 256 byte blocks out the USB serial using writeBlock bulk
+* transfers
+* @param data buffer of blocks to output
+* @param length length of 256-byte blocks
+*/
+int putBytes256Block(uint8_t *data, int numberBlocks) {
+  int i;
+  uint8_t *ptr;
+  ptr = data;
+  const int BLOCK_SIZE = 32;
+  const int FLASH_PAGE_SIZE = 256;
+  for (i = 0; i < numberBlocks * (FLASH_PAGE_SIZE / BLOCK_SIZE); i++) {
+    Peripherals::usbSerial()->writeBlock(ptr, BLOCK_SIZE);
+    ptr += BLOCK_SIZE;
+  }
+  return 0;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/e4a10ed6eb92/HSP/RpcServer/StringInOut.h	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,94 @@
+/*******************************************************************************
+ * Copyright (C) 2016 Maxim Integrated Products, Inc., All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+ * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Except as contained in this notice, the name of Maxim Integrated
+ * Products, Inc. shall not be used except as stated in the Maxim Integrated
+ * Products, Inc. Branding Policy.
+ *
+ * The mere transfer of this software does not imply any licenses
+ * of trade secrets, proprietary technology, copyrights, patents,
+ * trademarks, maskwork rights, or any other form of intellectual
+ * property whatsoever. Maxim Integrated Products, Inc. retains all
+ * ownership rights.
+ *******************************************************************************
+ */
+#ifndef _STRINGINOUT_H_
+#define _STRINGINOUT_H_
+
+#include "mbed.h"
+#include "USBSerial.h"
+
+/// indicates that a string up to a CRLF is being accumulated
+#define GETLINE_WAITING 1
+/// indicates that a string is being processes
+#define GETLINE_PROCESSING 2
+/// indicates that a CRLF string has been buffered and can be processed
+#define GETLINE_DONE 3
+
+/**
+* @brief Clear the incoming USB read fifo
+*/
+void clearOutReadFifo(void);
+/**
+* @brief Block until a character can be read from the USB
+* @return the character read
+*/
+char getch(void);
+/**
+* @brief Place incoming USB characters into a fifo
+* @param lineBuffer buffer to place the incoming characters
+* @param bufferLength length of buffer
+* @return GETLINE_WAITING if still waiting for a CRLF, GETLINE_DONE
+*/
+int getLine(char *lineBuffer, int bufferLength);
+/**
+* @brief Block until a fixed number of characters has been accumulated from the
+* incoming USB
+* @param lineBuffer buffer to place the incoming characters
+* @param maxLength length of buffer
+*/
+void getStringFixedLength(uint8_t *lineBuffer, int maxLength);
+/**
+* @brief Output a string out the USB serial port
+* @param str output this str the USB channel
+*/
+int putStr(const char *str);
+/**
+* @brief Place incoming USB characters into a fifo
+* @param data_IN buffer of characters
+* @param len length of data
+*/
+int fifoIncomingChars(uint8_t data_IN[], unsigned int len);
+/**
+* @brief Outut an array of bytes out the USB serial port
+* @param data buffer to output
+* @param length length of buffer
+*/
+int putBytes(uint8_t *data, uint32_t length);
+/**
+* @brief Outut 256 byte blocks out the USB serial using writeBlock bulk
+* transfers
+* @param data buffer of blocks to output
+* @param length length of 256-byte blocks
+*/
+int putBytes256Block(uint8_t *data, int numberBlocks);
+
+#endif // _STRINGINOUT_H_
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/e4a10ed6eb92/HSP/System/Peripherals.cpp	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,50 @@
+/*******************************************************************************
+ * Copyright (C) 2016 Maxim Integrated Products, Inc., All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+ * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Except as contained in this notice, the name of Maxim Integrated
+ * Products, Inc. shall not be used except as stated in the Maxim Integrated
+ * Products, Inc. Branding Policy.
+ *
+ * The mere transfer of this software does not imply any licenses
+ * of trade secrets, proprietary technology, copyrights, patents,
+ * trademarks, maskwork rights, or any other form of intellectual
+ * property whatsoever. Maxim Integrated Products, Inc. retains all
+ * ownership rights.
+ *******************************************************************************
+ */
+#include "Peripherals.h"
+
+I2C *Peripherals::mI2c1 = NULL;
+I2C *Peripherals::mI2c2 = NULL;
+USBSerial *Peripherals::mUSBSerial = NULL;
+MAX30101 *Peripherals::mMAX30101 = NULL;
+MAX30001 *Peripherals::mMAX30001 = NULL;
+BMP280 *Peripherals::mBMP280 = NULL;
+HspLed *Peripherals::mHspLed = NULL;
+MAX30205 *Peripherals::mMAX30205_top = NULL;
+MAX30205 *Peripherals::mMAX30205_bottom = NULL;
+LIS2DH *Peripherals::mLIS2DH = NULL;
+Timer *Peripherals::mTimestampTimer = NULL;
+S25FS512 *Peripherals::mS25FS512 = NULL;
+PushButton *Peripherals::mPushButton = NULL;
+BLE *Peripherals::mBLE = NULL;
+MAX14720 *Peripherals::mMAX14720 = NULL;
+HspBLE *Peripherals::mhspBLE = NULL;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/e4a10ed6eb92/HSP/System/Peripherals.h	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,126 @@
+/*******************************************************************************
+ * Copyright (C) 2016 Maxim Integrated Products, Inc., All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+ * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Except as contained in this notice, the name of Maxim Integrated
+ * Products, Inc. shall not be used except as stated in the Maxim Integrated
+ * Products, Inc. Branding Policy.
+ *
+ * The mere transfer of this software does not imply any licenses
+ * of trade secrets, proprietary technology, copyrights, patents,
+ * trademarks, maskwork rights, or any other form of intellectual
+ * property whatsoever. Maxim Integrated Products, Inc. retains all
+ * ownership rights.
+ *******************************************************************************
+ */
+#ifndef _PERIPHERALS_H_
+#define _PERIPHERALS_H_
+
+#include "mbed.h"
+#include "USBSerial.h"
+#include "MAX30101.h"
+#include "HspLed.h"
+#include "MAX30205.h"
+#include "LIS2DH.h"
+#include "MAX30001.h"
+#include "BMP280.h"
+#include "S25FS512.h"
+#include "PushButton.h"
+#include "BLE.h"
+#include "MAX14720.h"
+#include "HspBLE.h"
+
+/**
+* This static class is used as a central locatoin for all devices on the HSP platform
+* it gives (in-effect) a singleton interface for each device so that anywhere in code
+* one can reference on of these devices
+*/
+class Peripherals {
+public:
+    static USBSerial *setUSBSerial(USBSerial * device) { mUSBSerial = device; return device; }
+    static USBSerial *usbSerial(void) { return mUSBSerial; }
+
+    static MAX30101 *max30101(void) { return mMAX30101; }
+    static MAX30101 *setMAX30101(MAX30101 *device) { mMAX30101 = device; return device; }
+    
+    static MAX30205 *max30205_top(void) { return mMAX30205_top; }
+    static MAX30205 *setMAX30205_top(MAX30205 *device) { mMAX30205_top = device; return device; }
+
+    static MAX30205 *max30205_bottom(void) { return mMAX30205_bottom; }
+    static MAX30205 *setMAX30205_bottom(MAX30205 *device) { mMAX30205_bottom = device; return device; }
+
+    static HspLed *hspLed(void) { return mHspLed; }
+    static HspLed *setHspLed(HspLed *device) { mHspLed = device; return device; }
+
+    static LIS2DH *lis2dh(void) { return mLIS2DH; }
+    static LIS2DH *setLIS2DH(LIS2DH *device) { mLIS2DH = device; return device; }
+
+    static MAX30001 *max30001(void) { return mMAX30001; }
+    static MAX30001 *setMAX30001(MAX30001 *device) { mMAX30001 = device; return device; }
+
+    static BMP280 *bmp280(void) { return mBMP280; }
+    static BMP280 *setBMP280(BMP280 *device) { mBMP280 = device; return device; }
+
+    static Timer *timestampTimer(void) { return mTimestampTimer; }
+    static Timer *setTimestampTimer(Timer *timer) { mTimestampTimer = timer; return timer; }
+
+    static I2C *i2c1(void) { return mI2c1; }
+    static I2C *setI2c1(I2C *i2cPort) { mI2c1 = i2cPort; return i2cPort; }
+
+    static I2C *i2c2(void) { return mI2c2; }
+    static I2C *setI2c2(I2C *i2cPort) { mI2c2 = i2cPort; return i2cPort; }
+
+    static S25FS512 *s25FS512(void) { return mS25FS512; }
+    static S25FS512 *setS25FS512(S25FS512 *s25FS512) { mS25FS512 = s25FS512; return s25FS512; }
+
+    static PushButton *pushButton(void) { return mPushButton; }
+    static PushButton *setPushButton(PushButton *pushButton) { mPushButton = pushButton; return pushButton; }
+
+    static BLE *ble(void) { return mBLE; }
+    static BLE *setBLE(BLE *_ble) { mBLE = _ble; return _ble; }
+
+    static HspBLE *hspBLE(void) { return mhspBLE; }
+    static HspBLE *setHspBLE(HspBLE *_hspBLE) { mhspBLE = _hspBLE; return _hspBLE; }
+
+    static MAX14720 *max14720(void) { return mMAX14720; }
+    static MAX14720 *setMAX14720(MAX14720 *_MAX14720) { mMAX14720 = _MAX14720; return _MAX14720; }
+
+private:
+    static I2C *mI2c1;
+    static I2C *mI2c2;
+    static USBSerial *mUSBSerial;
+    static MAX30101 *mMAX30101;
+    static MAX30001 *mMAX30001;
+    static BMP280 *mBMP280;
+    static HspLed *mHspLed;
+    static Serial *mSerial;
+    static MAX30205 *mMAX30205_top;
+    static MAX30205 *mMAX30205_bottom;
+    static LIS2DH *mLIS2DH;
+    static Timer *mTimestampTimer;
+    static S25FS512 *mS25FS512;
+    static PushButton *mPushButton;
+    static BLE *mBLE;
+    static MAX14720 *mMAX14720;
+    static HspBLE *mhspBLE;
+};
+
+#endif // _PERIPHERALS_H_
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/e4a10ed6eb92/HSP/System/System.cpp	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,43 @@
+/*******************************************************************************
+ * Copyright (C) 2016 Maxim Integrated Products, Inc., All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+ * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Except as contained in this notice, the name of Maxim Integrated
+ * Products, Inc. shall not be used except as stated in the Maxim Integrated
+ * Products, Inc. Branding Policy.
+ *
+ * The mere transfer of this software does not imply any licenses
+ * of trade secrets, proprietary technology, copyrights, patents,
+ * trademarks, maskwork rights, or any other form of intellectual
+ * property whatsoever. Maxim Integrated Products, Inc. retains all
+ * ownership rights.
+ *******************************************************************************
+ */
+#include "mbed.h"
+
+//******************************************************************************
+void I2CM_Init_Reset(uint8_t index, int speed) {
+  mxc_i2cm_regs_t *regs = MXC_I2CM_GET_I2CM(index);
+  /* reset module */
+  regs->ctrl = MXC_F_I2CM_CTRL_MSTR_RESET_EN;
+  regs->ctrl = 0;
+  /* enable tx_fifo and rx_fifo */
+  regs->ctrl |= (MXC_F_I2CM_CTRL_TX_FIFO_EN | MXC_F_I2CM_CTRL_RX_FIFO_EN);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/e4a10ed6eb92/HSP/System/System.h	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,41 @@
+/*******************************************************************************
+ * Copyright (C) 2016 Maxim Integrated Products, Inc., All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+ * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Except as contained in this notice, the name of Maxim Integrated
+ * Products, Inc. shall not be used except as stated in the Maxim Integrated
+ * Products, Inc. Branding Policy.
+ *
+ * The mere transfer of this software does not imply any licenses
+ * of trade secrets, proprietary technology, copyrights, patents,
+ * trademarks, maskwork rights, or any other form of intellectual
+ * property whatsoever. Maxim Integrated Products, Inc. retains all
+ * ownership rights.
+ *******************************************************************************
+ */
+#ifndef _SYSTEM_H_
+#define _SYSTEM_H_
+
+/**
+* This issues a reset to the I2C Peripheral 
+*/
+void I2CM_Init_Reset(uint8_t index, int speed);
+
+#endif // _SYSTEM_H_
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/e4a10ed6eb92/HSP/Test/Test_BMP280.cpp	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,61 @@
+/*******************************************************************************
+ * Copyright (C) 2016 Maxim Integrated Products, Inc., All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+ * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Except as contained in this notice, the name of Maxim Integrated
+ * Products, Inc. shall not be used except as stated in the Maxim Integrated
+ * Products, Inc. Branding Policy.
+ *
+ * The mere transfer of this software does not imply any licenses
+ * of trade secrets, proprietary technology, copyrights, patents,
+ * trademarks, maskwork rights, or any other form of intellectual
+ * property whatsoever. Maxim Integrated Products, Inc. retains all
+ * ownership rights.
+ *******************************************************************************
+ */
+#include "Test_BMP280.h"
+#include "Test_Utilities.h"
+
+//******************************************************************************
+void test_BMP280(void (*outputString)(const char *)) {
+  char tempStr[32];
+  int pass;
+  uint8_t readId;
+  BMP280 *bmp280;
+  bmp280 = Peripherals::bmp280();
+
+  // display header
+  outputString("Testing BMP280|");
+
+  // read id test
+  outputString("Read ID: ");
+  readId = bmp280->ReadId();
+  if (readId == BMP280_READID)
+    pass = 1;
+  else
+    pass = 0;
+  sprintf(tempStr, " (%02X)|", readId);
+  outputString(tempStr);
+  _printPassFail(pass, 0, outputString);
+
+  // final results
+  outputString("Result: ");
+  _printPassFail(pass, 0, outputString);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/e4a10ed6eb92/HSP/Test/Test_BMP280.h	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,46 @@
+/*******************************************************************************
+ * Copyright (C) 2016 Maxim Integrated Products, Inc., All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+ * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Except as contained in this notice, the name of Maxim Integrated
+ * Products, Inc. shall not be used except as stated in the Maxim Integrated
+ * Products, Inc. Branding Policy.
+ *
+ * The mere transfer of this software does not imply any licenses
+ * of trade secrets, proprietary technology, copyrights, patents,
+ * trademarks, maskwork rights, or any other form of intellectual
+ * property whatsoever. Maxim Integrated Products, Inc. retains all
+ * ownership rights.
+ *******************************************************************************
+ */
+#ifndef _TEST_BMP280_H_
+#define _TEST_BMP280_H_
+
+#include "mbed.h"
+#include "BMP280.h"
+#include "Peripherals.h"
+
+/**
+* @brief Selftest the BMP280 and output the results as strings using the pointer function 
+* @param outputString Pointer to the function used to output the test results
+*/
+void test_BMP280(void (*outputString)(const char *));
+
+#endif / _TEST_BMP280_H_ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/e4a10ed6eb92/HSP/Test/Test_LIS2DH.cpp	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,64 @@
+/*******************************************************************************
+ * Copyright (C) 2016 Maxim Integrated Products, Inc., All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+ * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Except as contained in this notice, the name of Maxim Integrated
+ * Products, Inc. shall not be used except as stated in the Maxim Integrated
+ * Products, Inc. Branding Policy.
+ *
+ * The mere transfer of this software does not imply any licenses
+ * of trade secrets, proprietary technology, copyrights, patents,
+ * trademarks, maskwork rights, or any other form of intellectual
+ * property whatsoever. Maxim Integrated Products, Inc. retains all
+ * ownership rights.
+ *******************************************************************************
+ */
+#include "Test_LIS2DH.h"
+#include "Test_Utilities.h"
+
+//******************************************************************************
+void test_LIS2DH(void (*outputString)(const char *)) {
+  char tempStr[32];
+  int totalPass = 1;
+  int pass;
+  uint8_t readId;
+  LIS2DH *lis2dh;
+  lis2dh = Peripherals::lis2dh();
+
+  // display header
+  outputString("Testing LIS2DH|");
+
+  // read id test @ 400kHz
+  outputString("Read ID @ 400kHz: ");
+  readId = lis2dh->readId();
+  if (readId == LIS2DH_READID)
+    pass = 1;
+  else
+    pass = 0;
+  _printPassFail(pass, 0, outputString);
+  totalPass &= pass;
+  sprintf(tempStr, " (%02X)|", readId);
+  outputString(tempStr);
+  // end test at 100kHz
+
+  // final results
+  outputString("Result: ");
+  _printPassFail(totalPass, 0, outputString);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/e4a10ed6eb92/HSP/Test/Test_LIS2DH.h	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,46 @@
+/*******************************************************************************
+ * Copyright (C) 2016 Maxim Integrated Products, Inc., All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+ * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Except as contained in this notice, the name of Maxim Integrated
+ * Products, Inc. shall not be used except as stated in the Maxim Integrated
+ * Products, Inc. Branding Policy.
+ *
+ * The mere transfer of this software does not imply any licenses
+ * of trade secrets, proprietary technology, copyrights, patents,
+ * trademarks, maskwork rights, or any other form of intellectual
+ * property whatsoever. Maxim Integrated Products, Inc. retains all
+ * ownership rights.
+ *******************************************************************************
+ */
+#ifndef _TEST_LIS2DH_H_
+#define _TEST_LIS2DH_H_
+
+#include "mbed.h"
+#include "LIS2DH.h"
+#include "Peripherals.h"
+
+/**
+* @brief Selftest the LIS2DH and output the results as strings using the pointer function 
+* @param outputString Pointer to the function used to output the test results
+*/
+void test_LIS2DH(void (*outputString)(const char *));
+
+#endif /* _TEST_LIS2DH_H_ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/e4a10ed6eb92/HSP/Test/Test_MAX30001.cpp	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,169 @@
+/*******************************************************************************
+ * Copyright (C) 2016 Maxim Integrated Products, Inc., All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+ * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Except as contained in this notice, the name of Maxim Integrated
+ * Products, Inc. shall not be used except as stated in the Maxim Integrated
+ * Products, Inc. Branding Policy.
+ *
+ * The mere transfer of this software does not imply any licenses
+ * of trade secrets, proprietary technology, copyrights, patents,
+ * trademarks, maskwork rights, or any other form of intellectual
+ * property whatsoever. Maxim Integrated Products, Inc. retains all
+ * ownership rights.
+ *******************************************************************************
+ */
+#include "Test_MAX30001.h"
+#include "Test_Utilities.h"
+
+uint32_t testing_max30001 = 0;
+uint32_t testing_ecg_flags[4];
+
+//******************************************************************************
+void test_MAX30001(void (*outputString)(const char *)) {
+  int totalPass = 1;
+  int pass;
+  uint32_t foundEcg = 0;
+  uint32_t foundBioz = 0;
+  uint32_t foundPace = 0;
+  uint32_t foundRtoR = 0;
+  uint32_t id;
+  char str2[128];
+  int partVersion; // 0 = 30004
+  // 1 = 30001
+  // 2 = 30002
+  // 3 = 30003
+  Timer timer;
+  MAX30001 *max30001;
+  max30001 = Peripherals::max30001();
+
+  // read the id
+  max30001->max30001_reg_read(MAX30001::INFO, &id);
+  // read id twice because it needs to be read twice
+  max30001->max30001_reg_read(MAX30001::INFO, &id);
+  partVersion = id >> 12;
+  partVersion = partVersion & 0x3;
+
+  // display header
+  if (partVersion == 0)
+    outputString("Testing MAX30004|");
+  if (partVersion == 1) {
+    outputString("Testing MAX30001|");
+    outputString("Testing ECG, RtoR, BioZ, PACE|");
+  }
+  if (partVersion == 2)
+    outputString("Testing MAX30002|");
+  if (partVersion == 3) {
+    outputString("Testing MAX30003|");
+    outputString("Only Testing ECG and RtoR|");
+  }
+  sprintf(str2, "Device ID = 0x%06X|", id);
+  outputString(str2);
+
+  // clear testing flags
+  testing_ecg_flags[TESTING_ECG_FLAG] = 0;
+  testing_ecg_flags[TESTING_BIOZ_FLAG] = 0;
+  testing_ecg_flags[TESTING_PACE_FLAG] = 0;
+  testing_ecg_flags[TESTING_RTOR_FLAG] = 0;
+
+  // start streams
+  testing_max30001 = 1;
+  if (partVersion == 1)
+    outputString("Start Streaming ECG, RtoR, PACE, BIOZ, CAL enabled, "
+                 "verifying streams...|");
+  if (partVersion == 3)
+    outputString(
+        "Start Streaming ECG, RtoR, CAL enabled, verifying streams...|");
+  // max30001_CAL_InitStart(0b1, 0b1, 0b1, 0b011, 0x7FF, 0b0);
+  max30001->max30001_CAL_InitStart(0b1, 0b1, 0b1, 0b011, 0x7FF, 0b0);
+  max30001->max30001_ECG_InitStart(0b1, 0b1, 0b1, 0b0, 0b10, 0b11, 0x1F, 0b00,
+                                   0b00, 0b0, 0b01);
+  if (partVersion == 1)
+    max30001->max30001_PACE_InitStart(0b1, 0b0, 0b0, 0b1, 0x0, 0b0, 0b00, 0b0,
+                                      0b0);
+  if (partVersion == 1)
+    max30001->max30001_BIOZ_InitStart(0b1, 0b1, 0b1, 0b10, 0b11, 0b00, 7, 0b0,
+                                      0b010, 0b0, 0b10, 0b00, 0b00, 2, 0b0,
+                                      0b111, 0b0000);
+  max30001->max30001_RtoR_InitStart(0b1, 0b0011, 0b1111, 0b00, 0b0011, 0b000001,
+                                    0b00, 0b000, 0b01);
+  max30001->max30001_Rbias_FMSTR_Init(0b01, 0b10, 0b1, 0b1, 0b00);
+  max30001->max30001_synch();
+
+  // look for each stream
+  timer.start();
+  while (1) {
+    if ((foundEcg == 0) && (testing_ecg_flags[TESTING_ECG_FLAG] == 1)) {
+      foundEcg = 1;
+      outputString("ECG Stream: PASS|");
+    }
+    if ((foundBioz == 0) && (testing_ecg_flags[TESTING_BIOZ_FLAG] == 1)) {
+      foundBioz = 1;
+      outputString("Bioz Stream: PASS|");
+    }
+    if ((foundPace == 0) && (testing_ecg_flags[TESTING_PACE_FLAG] == 1)) {
+      foundPace = 1;
+      outputString("PACE Stream: PASS|");
+    }
+    if ((foundRtoR == 0) && (testing_ecg_flags[TESTING_RTOR_FLAG] == 1)) {
+      foundRtoR = 1;
+      outputString("RtoR Stream: PASS|");
+    }
+    if ((foundEcg == 1) && (foundBioz == 1) && (foundPace == 1) &&
+        (foundRtoR == 1) && (partVersion == 1)) {
+      break;
+    }
+    if ((foundEcg == 1) && (foundRtoR == 1) && (partVersion == 3)) {
+      break;
+    }
+    if (timer.read() >= TESTING_MAX30001_TIMEOUT_SECONDS) {
+      break;
+    }
+  }
+  timer.stop();
+  if (foundEcg == 0) {
+    outputString("ECG Stream: FAIL|");
+    totalPass &= pass;
+  }
+  if ((foundBioz == 0) && (partVersion == 1)) {
+    outputString("Bioz Stream: FAIL|");
+    totalPass &= pass;
+  }
+  if ((foundPace == 0) && (partVersion == 1)) {
+    outputString("PACE Stream: FAIL|");
+    totalPass &= pass;
+  }
+  if (foundRtoR == 0) {
+    outputString("RtoR Stream: FAIL|");
+    totalPass &= pass;
+  }
+
+  // stop all streams
+  max30001->max30001_Stop_ECG();
+  if (partVersion == 1)
+    max30001->max30001_Stop_PACE();
+  if (partVersion == 1)
+    max30001->max30001_Stop_BIOZ();
+  max30001->max30001_Stop_RtoR();
+  testing_max30001 = 0;
+  // final results
+  outputString("Result: ");
+  _printPassFail(totalPass, 0, outputString);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/e4a10ed6eb92/HSP/Test/Test_MAX30001.h	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,56 @@
+/*******************************************************************************
+ * Copyright (C) 2016 Maxim Integrated Products, Inc., All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+ * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Except as contained in this notice, the name of Maxim Integrated
+ * Products, Inc. shall not be used except as stated in the Maxim Integrated
+ * Products, Inc. Branding Policy.
+ *
+ * The mere transfer of this software does not imply any licenses
+ * of trade secrets, proprietary technology, copyrights, patents,
+ * trademarks, maskwork rights, or any other form of intellectual
+ * property whatsoever. Maxim Integrated Products, Inc. retains all
+ * ownership rights.
+ *******************************************************************************
+ */
+#ifndef _TEST_MAX30001_H_
+#define _TEST_MAX30001_H_
+
+#include "mbed.h"
+#include "MAX30001.h"
+#include "Peripherals.h"
+
+#define TESTING_ECG_FLAG 0
+#define TESTING_BIOZ_FLAG 1
+#define TESTING_PACE_FLAG 2
+#define TESTING_RTOR_FLAG 3
+
+#define TESTING_MAX30001_TIMEOUT_SECONDS 10
+
+extern uint32_t testing_max30001;
+extern uint32_t testing_ecg_flags[4];
+
+/**
+* @brief Selftest the MAX30001 and output the results as strings using the pointer function 
+* @param outputString Pointer to the function used to output the test results
+*/
+void test_MAX30001(void (*outputString)(const char *));
+
+#endif /* _TEST_MAX30101_H_ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/e4a10ed6eb92/HSP/Test/Test_MAX30101.cpp	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,143 @@
+/*******************************************************************************
+ * Copyright (C) 2016 Maxim Integrated Products, Inc., All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+ * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Except as contained in this notice, the name of Maxim Integrated
+ * Products, Inc. shall not be used except as stated in the Maxim Integrated
+ * Products, Inc. Branding Policy.
+ *
+ * The mere transfer of this software does not imply any licenses
+ * of trade secrets, proprietary technology, copyrights, patents,
+ * trademarks, maskwork rights, or any other form of intellectual
+ * property whatsoever. Maxim Integrated Products, Inc. retains all
+ * ownership rights.
+ *******************************************************************************
+ */
+#include "Test_MAX30101.h"
+#include "Test_Utilities.h"
+
+uint32_t testing_max30101 = 0;
+uint32_t testing_max30101_flags[4];
+
+//******************************************************************************
+void test_MAX30101(void (*outputString)(const char *)) {
+  Timer timer;
+  int totalPass = 1;
+  int pass;
+  uint32_t foundHR = 0;
+  uint32_t foundSPO2 = 0;
+  uint32_t foundMULTI = 0;
+  MAX30101 *max30101;
+
+  max30101 = Peripherals::max30101();
+
+  // display header
+  outputString("Testing MAX30101|");
+
+  // clear testing flags
+  testing_max30101_flags[TESTING_HR_FLAG] = 0;
+  testing_max30101_flags[TESTING_SPO2_FLAG] = 0;
+  testing_max30101_flags[TESTING_MULTI_FLAG] = 0;
+  testing_max30101 = 1;
+
+  //
+  // start stream (HR)
+  //
+  outputString("Start HR Streaming...|");
+  max30101->HRmode_init(0x0, 0x00, 0x01, 0x03,
+                        0x33); // This is the HR mode only (IR LED only)
+                               // look for (HR) streaming
+  timer.start();
+  while (1) {
+    if ((foundHR == 0) && (testing_max30101_flags[TESTING_HR_FLAG] == 1)) {
+      foundHR = 1;
+      outputString("HR Stream: PASS|");
+      break;
+    }
+    if (timer.read() >= TESTING_MAX30101_TIMEOUT_SECONDS) {
+      break;
+    }
+  }
+  if (foundHR == 0) {
+    outputString("HR Stream: FAIL|");
+    totalPass &= pass;
+  }
+  // stop stream
+  max30101->HRmode_stop();
+
+  //
+  // start stream (SPO2)
+  //
+  outputString("Start SPO2 Streaming...|");
+  max30101->SpO2mode_init(
+      0xF, 0x00, 0x01, 0x03, 0x33,
+      0x33); // This is the SpO2 mode only (Red and IR LED only)
+  // look for (SPO2) stream
+  timer.reset();
+  while (1) {
+    if ((foundSPO2 == 0) && (testing_max30101_flags[TESTING_SPO2_FLAG] == 1)) {
+      foundSPO2 = 1;
+      outputString("SPO2 Stream: PASS|");
+      break;
+    }
+    if (timer.read() >= TESTING_MAX30101_TIMEOUT_SECONDS) {
+      break;
+    }
+  }
+  if (foundSPO2 == 0) {
+    outputString("SPO2 Stream: FAIL|");
+    totalPass &= pass;
+  }
+  // stop stream
+  max30101->SpO2mode_stop();
+
+  //
+  // start stream (MULTI)
+  //
+  outputString("Start Multi Streaming...|");
+  max30101->Multimode_init(0x00, 0x00, 0x01, 0x03, 0x33, 0x33, 0x33, 0x01, 0x02,
+                           0x03, 0x00); // Up to 4 LED can be turned on over
+  // look for (SPO2) stream
+  timer.reset();
+  while (1) {
+    if ((foundMULTI == 0) &&
+        (testing_max30101_flags[TESTING_MULTI_FLAG] == 1)) {
+      foundMULTI = 1;
+      outputString("Multi Stream: PASS|");
+      break;
+    }
+    if (timer.read() >= TESTING_MAX30101_TIMEOUT_SECONDS) {
+      break;
+    }
+  }
+  if (foundMULTI == 0) {
+    outputString("Multi Stream: FAIL|");
+    totalPass &= pass;
+  }
+  // stop stream
+  max30101->Multimode_stop();
+
+  testing_max30101 = 0;
+
+  timer.stop();
+  // final results
+  outputString("Result: ");
+  _printPassFail(totalPass, 0, outputString);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/e4a10ed6eb92/HSP/Test/Test_MAX30101.h	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,55 @@
+/*******************************************************************************
+ * Copyright (C) 2016 Maxim Integrated Products, Inc., All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+ * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Except as contained in this notice, the name of Maxim Integrated
+ * Products, Inc. shall not be used except as stated in the Maxim Integrated
+ * Products, Inc. Branding Policy.
+ *
+ * The mere transfer of this software does not imply any licenses
+ * of trade secrets, proprietary technology, copyrights, patents,
+ * trademarks, maskwork rights, or any other form of intellectual
+ * property whatsoever. Maxim Integrated Products, Inc. retains all
+ * ownership rights.
+ *******************************************************************************
+ */
+#ifndef _TEST_MAX30101_H_
+#define _TEST_MAX30101_H_
+
+#include "mbed.h"
+#include "MAX30101.h"
+#include "Peripherals.h"
+
+#define TESTING_HR_FLAG 0
+#define TESTING_SPO2_FLAG 1
+#define TESTING_MULTI_FLAG 2
+
+#define TESTING_MAX30101_TIMEOUT_SECONDS 2
+
+extern uint32_t testing_max30101;
+extern uint32_t testing_max30101_flags[4];
+
+/**
+* @brief Selftest the MAX30101 and output the results as strings using the pointer function 
+* @param outputString Pointer to the function used to output the test results
+*/
+void test_MAX30101(void (*outputString)(const char *));
+
+#endif /* _TEST_MAX30101_H_ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/e4a10ed6eb92/HSP/Test/Test_MAX30205.cpp	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,58 @@
+/*******************************************************************************
+ * Copyright (C) 2016 Maxim Integrated Products, Inc., All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+ * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Except as contained in this notice, the name of Maxim Integrated
+ * Products, Inc. shall not be used except as stated in the Maxim Integrated
+ * Products, Inc. Branding Policy.
+ *
+ * The mere transfer of this software does not imply any licenses
+ * of trade secrets, proprietary technology, copyrights, patents,
+ * trademarks, maskwork rights, or any other form of intellectual
+ * property whatsoever. Maxim Integrated Products, Inc. retains all
+ * ownership rights.
+ *******************************************************************************
+ */
+#include "Test_MAX30205.h"
+#include "Test_Utilities.h"
+#include "MAX30205.h"
+#include "Peripherals.h"
+
+//******************************************************************************
+void test_MAX30205(MAX30205 *MAX30205, void (*outputString)(const char *)) {
+  uint16_t value;
+  char tempStr[32];
+  int pass;
+
+  outputString("Write Reg_THYST to 0x1234 @ 400kHz: ");
+  // i2cSetSpeed(MAX30205_I2CM_INSTANCE, I2CM_SPEED_100kHz);
+  MAX30205->reg_THYST_Write(0x1234);
+  outputString("Read Reg_THYST @ 400kHz: ");
+  // i2cSetSpeed(MAX30205_I2CM_INSTANCE, I2CM_SPEED_100kHz);
+  MAX30205->reg_THYST_Read(&value);
+  if (value == 0x1234)
+    pass = 1;
+  else
+    pass = 0;
+  //*totalPass &= *pass;
+  sprintf(tempStr, " (%04X)|", value);
+  outputString(tempStr);
+  _printPassFail(pass, 0, outputString);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/e4a10ed6eb92/HSP/Test/Test_MAX30205.h	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,45 @@
+/*******************************************************************************
+ * Copyright (C) 2016 Maxim Integrated Products, Inc., All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+ * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Except as contained in this notice, the name of Maxim Integrated
+ * Products, Inc. shall not be used except as stated in the Maxim Integrated
+ * Products, Inc. Branding Policy.
+ *
+ * The mere transfer of this software does not imply any licenses
+ * of trade secrets, proprietary technology, copyrights, patents,
+ * trademarks, maskwork rights, or any other form of intellectual
+ * property whatsoever. Maxim Integrated Products, Inc. retains all
+ * ownership rights.
+ *******************************************************************************
+ */
+#ifndef _TEST_MAX30205_H_
+#define _TEST_MAX30205_H_
+
+#include "mbed.h"
+#include "MAX30205.h"
+
+/**
+* @brief Selftest the MAX30101 and output the results as strings using the pointer function 
+* @param outputString Pointer to the function used to output the test results
+*/
+void test_MAX30205(MAX30205 *MAX30205, void (*outputString)(const char *));
+
+#endif /* _TEST_MAX30205_H_ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/e4a10ed6eb92/HSP/Test/Test_S25FS512.cpp	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,111 @@
+/*******************************************************************************
+ * Copyright (C) 2016 Maxim Integrated Products, Inc., All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+ * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Except as contained in this notice, the name of Maxim Integrated
+ * Products, Inc. shall not be used except as stated in the Maxim Integrated
+ * Products, Inc. Branding Policy.
+ *
+ * The mere transfer of this software does not imply any licenses
+ * of trade secrets, proprietary technology, copyrights, patents,
+ * trademarks, maskwork rights, or any other form of intellectual
+ * property whatsoever. Maxim Integrated Products, Inc. retains all
+ * ownership rights.
+ *******************************************************************************
+ */
+#include "Test_S25FS512.h"
+#include "Test_Utilities.h"
+
+//******************************************************************************
+void test_S25FS512(void (*outputString)(const char *)) {
+  char tempStr[32];
+  uint8_t page[264];
+  int totalPass = 1;
+  int pass;
+  int status;
+  int i;
+  uint8_t data[128];
+  S25FS512 *s25FS512;
+
+  s25FS512 = Peripherals::s25FS512();
+
+  // display header
+  outputString("Testing S25FS512|");
+
+  // read id test
+  s25FS512->readIdentification(data, sizeof(data));
+  s25FS512->readIdentification(data, sizeof(data));
+  if ((data[1] == 0x01) && (data[2] == 0x02) && (data[3] == 0x19) &&
+      (data[4] == 0x4D)) {
+    sprintf(tempStr, "Read ID: Pass ");
+    outputString(tempStr);
+  } else {
+    sprintf(tempStr, "Read ID: Fail ");
+    outputString(tempStr);
+    totalPass = 0;
+  }
+  sprintf(tempStr, "(%02X%02X%02X%02X)|", data[1], data[2], data[3], data[4]);
+  outputString(tempStr);
+
+  if (totalPass == 1) {
+    // format sector 0
+    outputString("Formatting Sector 0, ");
+    s25FS512->sectorErase_Helper(0);
+
+    // verify format sector 0
+    outputString("Verifying Format of Sector 0: ");
+    s25FS512->readPages_Helper(0, 0, page, 0);
+    pass = s25FS512->isPageEmpty(page);
+    _printPassFail(pass, 1, outputString);
+    totalPass &= pass;
+
+    // fill page with pattern
+    for (i = 0; i < 256; i++) {
+      page[i] = i;
+    }
+    // write to page 0
+    outputString("Writing Page 0 to pattern, ");
+    s25FS512->writePage_Helper(0, page, 0);
+    // clear pattern in memory
+    for (i = 0; i < 256; i++) {
+      page[i] = 0x00;
+    }
+    // read back page and verify
+    outputString("Read Page Verify: ");
+    s25FS512->readPages_Helper(0, 0, page, 0);
+    // compare memory for pattern
+    pass = 1;
+    for (i = 0; i < 256; i++) {
+      if (page[i] != i)
+        pass = 0;
+    }
+    _printPassFail(pass, 1, outputString);
+    totalPass &= pass;
+
+    // format sector 0 to clean up after tests
+    s25FS512->sectorErase_Helper(0);
+  } else {
+    outputString("Read Id Failed, Skipping rest of test|");
+  }
+
+  // final results
+  outputString("Result: ");
+  _printPassFail(totalPass, 0, outputString);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/e4a10ed6eb92/HSP/Test/Test_S25FS512.h	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,46 @@
+/*******************************************************************************
+ * Copyright (C) 2016 Maxim Integrated Products, Inc., All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+ * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Except as contained in this notice, the name of Maxim Integrated
+ * Products, Inc. shall not be used except as stated in the Maxim Integrated
+ * Products, Inc. Branding Policy.
+ *
+ * The mere transfer of this software does not imply any licenses
+ * of trade secrets, proprietary technology, copyrights, patents,
+ * trademarks, maskwork rights, or any other form of intellectual
+ * property whatsoever. Maxim Integrated Products, Inc. retains all
+ * ownership rights.
+ *******************************************************************************
+ */
+#ifndef _TEST_S25FS512_H_
+#define _TEST_S25FS512_H_
+
+#include "mbed.h"
+#include "S25FS512.h"
+#include "Peripherals.h"
+
+/**
+* @brief Selftest the S25FS512 and output the results as strings using the pointer function 
+* @param outputString Pointer to the function used to output the test results
+*/
+void test_S25FS512(void (*outputString)(const char *));
+
+#endif /* _TEST_S25FS512_H_ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/e4a10ed6eb92/HSP/Test/Test_Utilities.cpp	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,45 @@
+/*******************************************************************************
+ * Copyright (C) 2016 Maxim Integrated Products, Inc., All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+ * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Except as contained in this notice, the name of Maxim Integrated
+ * Products, Inc. shall not be used except as stated in the Maxim Integrated
+ * Products, Inc. Branding Policy.
+ *
+ * The mere transfer of this software does not imply any licenses
+ * of trade secrets, proprietary technology, copyrights, patents,
+ * trademarks, maskwork rights, or any other form of intellectual
+ * property whatsoever. Maxim Integrated Products, Inc. retains all
+ * ownership rights.
+ *******************************************************************************
+ */
+#include "Test_Utilities.h"
+
+//******************************************************************************
+void _printPassFail(int status, int newLine, void (*outputString)(char const *)) {
+  if (status == 1) {
+    outputString("PASS");
+  } else {
+    outputString("FAIL");
+  }
+  if (newLine == 1) {
+    outputString("|");
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/e4a10ed6eb92/HSP/Test/Test_Utilities.h	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,46 @@
+/*******************************************************************************
+ * Copyright (C) 2016 Maxim Integrated Products, Inc., All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+ * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Except as contained in this notice, the name of Maxim Integrated
+ * Products, Inc. shall not be used except as stated in the Maxim Integrated
+ * Products, Inc. Branding Policy.
+ *
+ * The mere transfer of this software does not imply any licenses
+ * of trade secrets, proprietary technology, copyrights, patents,
+ * trademarks, maskwork rights, or any other form of intellectual
+ * property whatsoever. Maxim Integrated Products, Inc. retains all
+ * ownership rights.
+ *******************************************************************************
+ */
+#ifndef _TEST_UTILITIES_H_
+#define _TEST_UTILITIES_H_
+
+#include "mbed.h"
+
+/**
+* Function that will output a pass/fail formated string based on the incoming status value
+* @param status Value that indicated pass or fail status
+* @param newLine Should this call output a new line
+* @param outputString Pointer to a function that will do the actual outputting of the string
+*/
+void _printPassFail(int status, int newLine, void (*outputString)(const char *));
+
+#endif /* _TEST_UTILITIES_H_ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/e4a10ed6eb92/HSP/Test/Testing_RPC.cpp	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,130 @@
+/*******************************************************************************
+ * Copyright (C) 2016 Maxim Integrated Products, Inc., All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+ * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Except as contained in this notice, the name of Maxim Integrated
+ * Products, Inc. shall not be used except as stated in the Maxim Integrated
+ * Products, Inc. Branding Policy.
+ *
+ * The mere transfer of this software does not imply any licenses
+ * of trade secrets, proprietary technology, copyrights, patents,
+ * trademarks, maskwork rights, or any other form of intellectual
+ * property whatsoever. Maxim Integrated Products, Inc. retains all
+ * ownership rights.
+ *******************************************************************************
+ */
+#include <stdint.h>
+#include "StringHelper.h"
+#include "MAX30205.h"
+#include "Test_BMP280.h"
+#include "Test_LIS2DH.h"
+#include "Test_MAX30001.h"
+#include "Test_MAX30101.h"
+#include "Test_MAX30205.h"
+#include "Test_S25FS512.h"
+#include "StringInOut.h"
+
+void outputTestResultString(const char *resultStr);
+
+//******************************************************************************
+int Test_S25FS512(char argStrs[32][32], char replyStrs[32][32]) {
+  uint32_t reply[1];
+  test_S25FS512(outputTestResultString);
+  reply[0] = 0x80;
+  FormatReply32(reply, sizeof(reply) / sizeof(uint32_t), replyStrs);
+  return 0;
+}
+
+//******************************************************************************
+int Test_BMP280(char argStrs[32][32], char replyStrs[32][32]) {
+  uint32_t reply[1];
+  test_BMP280(outputTestResultString);
+  reply[0] = 0x80;
+  FormatReply32(reply, sizeof(reply) / sizeof(uint32_t), replyStrs);
+  return 0;
+}
+
+//******************************************************************************
+int Test_LIS2DH(char argStrs[32][32], char replyStrs[32][32]) {
+  uint32_t reply[1];
+  test_LIS2DH(outputTestResultString);
+  reply[0] = 0x80;
+  FormatReply32(reply, sizeof(reply) / sizeof(uint32_t), replyStrs);
+  return 0;
+}
+
+//******************************************************************************
+int Test_LSM6DS3(char argStrs[32][32], char replyStrs[32][32]) {
+  uint32_t reply[1];
+  reply[0] = 0x80;
+  FormatReply32(reply, sizeof(reply) / sizeof(uint32_t), replyStrs);
+  return 0;
+}
+
+//******************************************************************************
+int Test_MAX30205_1(char argStrs[32][32], char replyStrs[32][32]) {
+  uint32_t reply[1];
+  MAX30205 *max30205;
+  max30205 = Peripherals::max30205_top();
+  test_MAX30205(max30205, outputTestResultString);
+  reply[0] = 0x80;
+  FormatReply32(reply, sizeof(reply) / sizeof(uint32_t), replyStrs);
+  return 0;
+}
+
+//******************************************************************************
+int Test_MAX30205_2(char argStrs[32][32], char replyStrs[32][32]) {
+  uint32_t reply[1];
+  MAX30205 *max30205;
+  max30205 = Peripherals::max30205_bottom();
+  test_MAX30205(max30205, outputTestResultString);
+  reply[0] = 0x80;
+  FormatReply32(reply, sizeof(reply) / sizeof(uint32_t), replyStrs);
+  return 0;
+}
+
+//******************************************************************************
+int Test_MAX30101(char argStrs[32][32], char replyStrs[32][32]) {
+  uint32_t reply[1];
+  test_MAX30101(outputTestResultString);
+  reply[0] = 0x80;
+  FormatReply32(reply, sizeof(reply) / sizeof(uint32_t), replyStrs);
+  return 0;
+}
+
+//******************************************************************************
+int Test_MAX30001(char argStrs[32][32], char replyStrs[32][32]) {
+  uint32_t reply[1];
+  test_MAX30001(outputTestResultString);
+  reply[0] = 0x80;
+  FormatReply32(reply, sizeof(reply) / sizeof(uint32_t), replyStrs);
+  return 0;
+}
+
+//******************************************************************************
+int Test_EM9301(char argStrs[32][32], char replyStrs[32][32]) {
+  uint32_t reply[1];
+  reply[0] = 0x80;
+  FormatReply32(reply, sizeof(reply) / sizeof(uint32_t), replyStrs);
+  return 0;
+}
+
+//******************************************************************************
+void outputTestResultString(const char *resultStr) { putStr(resultStr); }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/e4a10ed6eb92/HSP/Test/Testing_RPC.h	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,73 @@
+/*******************************************************************************
+ * Copyright (C) 2016 Maxim Integrated Products, Inc., All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+ * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Except as contained in this notice, the name of Maxim Integrated
+ * Products, Inc. shall not be used except as stated in the Maxim Integrated
+ * Products, Inc. Branding Policy.
+ *
+ * The mere transfer of this software does not imply any licenses
+ * of trade secrets, proprietary technology, copyrights, patents,
+ * trademarks, maskwork rights, or any other form of intellectual
+ * property whatsoever. Maxim Integrated Products, Inc. retains all
+ * ownership rights.
+ *******************************************************************************
+ */
+#ifndef _TESTING_RPC_H_
+#define _TESTING_RPC_H_
+
+/**
+* RPC executed routine that will perform platform self testing for the S25FS512
+*/
+int Test_S25FS512(char argStrs[32][32], char replyStrs[32][32]);
+/**
+* RPC executed routine that will perform platform self testing for the BMP280
+*/
+int Test_BMP280(char argStrs[32][32], char replyStrs[32][32]);
+/**
+* RPC executed routine that will perform platform self testing for the LIS2DH
+*/
+int Test_LIS2DH(char argStrs[32][32], char replyStrs[32][32]);
+/**
+* RPC executed routine that will perform platform self testing for the LSM6DS3
+*/
+int Test_LSM6DS3(char argStrs[32][32], char replyStrs[32][32]);
+/**
+* RPC executed routine that will perform platform self testing for the MAX30205 
+*/
+int Test_MAX30205_1(char argStrs[32][32], char replyStrs[32][32]);
+/**
+* RPC executed routine that will perform platform self testing for the MAX30205
+*/
+int Test_MAX30205_2(char argStrs[32][32], char replyStrs[32][32]);
+/**
+* RPC executed routine that will perform platform self testing for the MAX30101
+*/
+int Test_MAX30101(char argStrs[32][32], char replyStrs[32][32]);
+/**
+* RPC executed routine that will perform platform self testing for the MAX30001
+*/
+int Test_MAX30001(char argStrs[32][32], char replyStrs[32][32]);
+/**
+* RPC executed routine that will perform platform self testing for the EM9301
+*/
+int Test_EM9301(char argStrs[32][32], char replyStrs[32][32]);
+
+#endif /* _TESTING_RPC_H_ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/e4a10ed6eb92/HSP/main.cpp	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,266 @@
+/*******************************************************************************
+ * Copyright (C) 2016 Maxim Integrated Products, Inc., All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+ * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Except as contained in this notice, the name of Maxim Integrated
+ * Products, Inc. shall not be used except as stated in the Maxim Integrated
+ * Products, Inc. Branding Policy.
+ *
+ * The mere transfer of this software does not imply any licenses
+ * of trade secrets, proprietary technology, copyrights, patents,
+ * trademarks, maskwork rights, or any other form of intellectual
+ * property whatsoever. Maxim Integrated Products, Inc. retains all
+ * ownership rights.
+ *******************************************************************************
+ */
+#include "mbed.h"
+#include "MAX14720.h"
+#include "MAX30101.h"
+#include "MAX30205.h"
+#include "LIS2DH.h"
+#include "USBSerial.h"
+#include "RpcServer.h"
+#include "StringInOut.h"
+#include "Peripherals.h"
+#include "BMP280.h"
+#include "MAX30001.h"
+#include "DataLoggingService.h"
+#include "MAX30101_helper.h"
+#include "S25FS512.h"
+#include "QuadSpiInterface.h"
+#include "PushButton.h"
+#include "BLE.h"
+#include "HspBLE.h"
+#include "USBSerial.h"
+#include "Streaming.h"
+
+/// define the HVOUT Boost Voltage default for the MAX14720 PMIC
+#define HVOUT_VOLTAGE 4500 // set to 4500 mV
+
+/// define all I2C addresses
+#define MAX30205_I2C_SLAVE_ADDR_TOP (0x92)
+#define MAX30205_I2C_SLAVE_ADDR_BOTTOM (0x90)
+#define MAX14720_I2C_SLAVE_ADDR (0x54)
+#define BMP280_I2C_SLAVE_ADDR (0xEC)
+#define MAX30101_I2C_SLAVE_ADDR (0xAE)
+#define LIS2DH_I2C_SLAVE_ADDR (0x32)
+
+///
+/// wire Interfaces
+///
+/// Define with Maxim VID and a Maxim assigned PID, set to version 0x0001 and non-blocking
+USBSerial usbSerial(0x0b6a, 0x0100, 0x0001, false);
+/// I2C Master 1
+I2C i2c1(I2C1_SDA, I2C1_SCL); // used by MAX30205 (1), MAX30205 (2), BMP280
+/// I2C Master 2
+I2C i2c2(I2C2_SDA, I2C2_SCL); // used by MAX14720, MAX30101, LIS2DH
+/// SPI Master 0 with SPI0_SS for use with MAX30001
+SPI spi(SPI0_MOSI, SPI0_MISO, SPI0_SCK, SPI0_SS); // used by MAX30001
+/// SPI Master 1
+QuadSpiInterface quadSpiInterface(SPI1_MOSI, SPI1_MISO, SPI1_SCK,
+                                  SPI1_SS); // used by S25FS512
+
+///
+/// Devices
+///
+/// Pressure Sensor
+BMP280 bmp280(&i2c1, BMP280_I2C_SLAVE_ADDR);
+/// Top Local Temperature Sensor
+MAX30205 MAX30205_top(&i2c1, MAX30205_I2C_SLAVE_ADDR_TOP);
+/// Bottom Local Temperature Sensor
+MAX30205 MAX30205_bottom(&i2c1, MAX30205_I2C_SLAVE_ADDR_BOTTOM);
+/// Accelerometer
+LIS2DH lis2dh(&i2c2, LIS2DH_I2C_SLAVE_ADDR);
+InterruptIn lis2dh_Interrupt(P4_7);
+/// PMIC
+MAX14720 max14720(&i2c2, MAX14720_I2C_SLAVE_ADDR);
+/// Optical Oximeter
+MAX30101 max30101(&i2c2, MAX30101_I2C_SLAVE_ADDR);
+InterruptIn max30101_Interrupt(P4_0);
+/// External Flash
+S25FS512 s25fs512(&quadSpiInterface);
+/// ECG device
+MAX30001 max30001(&spi);
+InterruptIn max30001_InterruptB(P3_6);
+InterruptIn max30001_Interrupt2B(P4_5);
+/// PWM used as fclk for the MAX30001
+PwmOut pwmout(P1_7);
+/// HSP platform LED
+HspLed hspLed(LED_RED);
+/// Packet TimeStamp Timer, set for 1uS
+Timer timestampTimer;
+/// HSP Platform push button
+PushButton pushButton(SW1);
+
+/// BLE instance
+static BLE ble;
+
+/// HSP BluetoothLE specific functions
+HspBLE hspBLE(&ble);
+
+int main() {
+  // hold results for returning funtcoins
+  int result;
+  // local input state of the RPC
+  int inputState;
+  // RPC request buffer
+  char request[128];
+  // RPC reply buffer
+  char reply[128];
+
+  // display start banner
+  printf("Maxim Integrated mbed hSensor 3.0.0 10/14/16\n");
+  fflush(stdout);
+
+  // initialize HVOUT on the MAX14720 PMIC
+  printf("Init MAX14720...\n");
+  fflush(stdout);
+  result = max14720.init();
+  if (result == MAX14720_ERROR)
+    printf("Error initializing MAX14720");
+  max14720.boostEn = MAX14720::BOOST_ENABLED;
+  max14720.boostSetVoltage(HVOUT_VOLTAGE);
+
+  // turn on red led
+  printf("Init HSPLED...\n");
+  fflush(stdout);
+  hspLed.on();
+
+  // set NVIC priorities for GPIO to prevent priority inversion
+  printf("Init NVIC Priorities...\n");
+  fflush(stdout);
+  NVIC_SetPriority(GPIO_P0_IRQn, 5);
+  NVIC_SetPriority(GPIO_P1_IRQn, 5);
+  NVIC_SetPriority(GPIO_P2_IRQn, 5);
+  NVIC_SetPriority(GPIO_P3_IRQn, 5);
+  NVIC_SetPriority(GPIO_P4_IRQn, 5);
+  NVIC_SetPriority(GPIO_P5_IRQn, 5);
+  NVIC_SetPriority(GPIO_P6_IRQn, 5);
+  // used by the MAX30001
+  NVIC_SetPriority(SPI1_IRQn, 0);
+
+  // Be able to statically reference these devices anywhere in the application
+  Peripherals::setS25FS512(&s25fs512);
+  Peripherals::setMAX30205_top(&MAX30205_top);
+  Peripherals::setMAX30205_bottom(&MAX30205_bottom);
+  Peripherals::setBMP280(&bmp280);
+  Peripherals::setLIS2DH(&lis2dh);
+  Peripherals::setUSBSerial(&usbSerial);
+  Peripherals::setTimestampTimer(&timestampTimer);
+  Peripherals::setHspLed(&hspLed);
+  Peripherals::setMAX30101(&max30101);
+  Peripherals::setI2c1(&i2c1);
+  Peripherals::setI2c2(&i2c2);
+  Peripherals::setPushButton(&pushButton);
+  Peripherals::setBLE(&ble);
+  Peripherals::setMAX14720(&max14720);
+  Peripherals::setMAX30001(&max30001);
+  Peripherals::setHspBLE(&hspBLE);
+
+  // init the S25FS256 external flash device
+  printf("Init S25FS512...\n");
+  fflush(stdout);
+  s25fs512.init();
+
+  // init the BMP280
+  printf("Init BMP280...\n");
+  fflush(stdout);
+  bmp280.init(BMP280::OVERSAMPLING_X2_P, BMP280::OVERSAMPLING_X1_T,
+              BMP280::FILT_OFF, BMP280::NORMAL_MODE, BMP280::T_62_5);
+
+  // Initialize BLE base layer
+  printf("Init HSPBLE...\n");
+  fflush(stdout);
+  hspBLE.init();
+
+  // start blinking led1
+  printf("Init HSPLED Blink...\n");
+  fflush(stdout);
+  hspLed.blink(1000);
+
+  // MAX30101 initialize interrupt
+  printf("Init MAX30101 callbacks, interrupt...\n");
+  fflush(stdout);
+  max30101.onInterrupt(&MAX30101_OnInterrupt);
+  max30101.onDataAvailable(&StreamPacketUint32);
+  max30101_Interrupt.fall(&MAX30101MidIntHandler);
+
+  //
+  // MAX30001
+  //
+  printf("Init MAX30001 callbacks, interrupts...\n");
+  fflush(stdout);
+  max30001_InterruptB.disable_irq();
+  max30001_Interrupt2B.disable_irq();
+  max30001_InterruptB.mode(PullUp);
+  max30001_InterruptB.fall(&MAX30001Mid_IntB_Handler);
+  max30001_Interrupt2B.mode(PullUp);
+  max30001_Interrupt2B.fall(&MAX30001Mid_Int2B_Handler);
+  max30001_InterruptB.enable_irq();
+  max30001_Interrupt2B.enable_irq();
+  MAX30001_AllowInterrupts(1);
+  // Configuring the FCLK for the ECG, set to 32.768KHZ
+  printf("Init MAX30001 PWM...\n");
+  fflush(stdout);
+  pwmout.period_us(31);
+  pwmout.write(0.5);          // 0-1 is 0-100%, 0.5 = 50% duty cycle.
+  max30001.max30001_sw_rst(); // Do a software reset of the MAX30001
+    max30001.max30001_INT_assignment(MAX30001::MAX30001_INT_B,    MAX30001::MAX30001_NO_INT,   MAX30001::MAX30001_NO_INT,  //  en_enint_loc,      en_eovf_loc,   en_fstint_loc,
+                                     MAX30001::MAX30001_INT_2B,   MAX30001::MAX30001_INT_2B,   MAX30001::MAX30001_NO_INT,  //  en_dcloffint_loc,  en_bint_loc,   en_bovf_loc,
+                                     MAX30001::MAX30001_INT_2B,   MAX30001::MAX30001_INT_2B,   MAX30001::MAX30001_NO_INT,  //  en_bover_loc,      en_bundr_loc,  en_bcgmon_loc,
+                                     MAX30001::MAX30001_INT_B,    MAX30001::MAX30001_NO_INT,   MAX30001::MAX30001_NO_INT,  //  en_pint_loc,       en_povf_loc,   en_pedge_loc,
+                                     MAX30001::MAX30001_INT_2B,   MAX30001::MAX30001_INT_B,    MAX30001::MAX30001_NO_INT,  //  en_lonint_loc,     en_rrint_loc,  en_samp_loc,
+                                     MAX30001::MAX30001_INT_ODNR, MAX30001::MAX30001_INT_ODNR);                            //  intb_Type,         int2b_Type)
+  max30001.onDataAvailable(&StreamPacketUint32);
+
+  // initialize the LIS2DH accelerometer and interrupts
+  printf("Init LIS2DH interrupt...\n");
+  fflush(stdout);
+  lis2dh.init();
+  lis2dh_Interrupt.fall(&LIS2DHIntHandler);
+  lis2dh_Interrupt.mode(PullUp);
+  // initialize the RPC server
+  printf("Init RPC Server...\n");
+  fflush(stdout);
+  RPC_init();
+  // initialize the logging service
+  printf("Init LoggingService...\n");
+  fflush(stdout);
+  LoggingService_Init();
+
+  // start main loop
+  printf("Start main loop...\n");
+  fflush(stdout);
+  while (1) {
+    // get a RPC string if one is available
+    inputState = getLine(request, sizeof(request));
+    // if a string has been captured, process string
+    if (inputState == GETLINE_DONE) {
+      // process the RPC string
+      RPC_call(request, reply);
+      // output the reply
+      putStr(reply);
+    }
+    // process any logging or streaming requests
+    LoggingService_ServiceRoutine();
+    // allow for ble processing
+    ble.waitForEvent();
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/e4a10ed6eb92/USBDevice.lib	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,1 @@
+http://developer.mbed.org/teams/MaximIntegrated/code/USBDevice/#dad310740b28
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/e4a10ed6eb92/mbed-os.lib	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,1 @@
+https://github.com/ARMmbed/mbed-os/#e435a07d9252f133ea3d9f6c95dfb176f32ab9b6
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/main/AndroidManifest.xml	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,61 @@
+<?xml version="1.0" encoding="utf-8"?><!--
+ Copyright 2013 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+     http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.example.android.bluetoothlegatt"
+    android:versionCode="1"
+    android:versionName="1.0">
+
+    <!-- Min/target SDK versions (<uses-sdk>) managed by build.gradle -->
+
+
+    <!--
+    Declare this required feature if you want to make the app available to BLE-capable
+    devices only.  If you want to make your app available to devices that don't support BLE,
+    you should omit this in the manifest.  Instead, determine BLE capability by using
+    PackageManager.hasSystemFeature(FEATURE_BLUETOOTH_LE)
+    -->
+    <uses-feature
+        android:name="android.hardware.bluetooth_le"
+        android:required="true" />
+
+    <uses-permission android:name="android.permission.BLUETOOTH" />
+    <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
+
+    <application
+        android:icon="@drawable/ic_launcher"
+        android:label="@string/app_name"
+        android:theme="@android:style/Theme.Holo.Light">
+        <activity
+            android:name=".DeviceScanActivity"
+            android:label="@string/app_name">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+
+                <category android:name="android.intent.category.LAUNCHER" />
+            </intent-filter>
+        </activity>
+        <activity
+            android:name=".SensorActivity"
+            android:label="SensorActivity"
+            android:screenOrientation="portrait"></activity>
+
+        <service
+            android:name=".BluetoothLeService"
+            android:enabled="true" />
+
+    </application>
+
+</manifest>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/main/java/com/example/android/bluetoothlegatt/BluetoothLeService.java	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,468 @@
+/*******************************************************************************
+ * Copyright (C) 2016 Maxim Integrated Products, Inc., All Rights Reserved.
+ * <p>
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ * <p>
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ * <p>
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+ * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ * <p>
+ * Except as contained in this notice, the name of Maxim Integrated
+ * Products, Inc. shall not be used except as stated in the Maxim Integrated
+ * Products, Inc. Branding Policy.
+ * <p>
+ * The mere transfer of this software does not imply any licenses
+ * of trade secrets, proprietary technology, copyrights, patents,
+ * trademarks, maskwork rights, or any other form of intellectual
+ * property whatsoever. Maxim Integrated Products, Inc. retains all
+ * ownership rights.
+ * ******************************************************************************
+ */
+package com.example.android.bluetoothlegatt;
+
+import android.app.Service;
+import android.bluetooth.BluetoothAdapter;
+import android.bluetooth.BluetoothDevice;
+import android.bluetooth.BluetoothGatt;
+import android.bluetooth.BluetoothGattCallback;
+import android.bluetooth.BluetoothGattCharacteristic;
+import android.bluetooth.BluetoothGattDescriptor;
+import android.bluetooth.BluetoothGattService;
+import android.bluetooth.BluetoothManager;
+import android.bluetooth.BluetoothProfile;
+import android.content.Context;
+import android.content.Intent;
+import android.os.Binder;
+import android.os.IBinder;
+import android.util.Log;
+
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Queue;
+import java.util.UUID;
+
+/**
+ * Service for managing connection and data communication with a GATT server hosted on a
+ * given Bluetooth LE device.
+ */
+public class BluetoothLeService extends Service {
+    private final static String TAG = BluetoothLeService.class.getSimpleName();
+
+    private BluetoothManager mBluetoothManager;
+    private BluetoothAdapter mBluetoothAdapter;
+    private String mBluetoothDeviceAddress;
+    private BluetoothGatt mBluetoothGatt;
+    private int mConnectionState = STATE_DISCONNECTED;
+
+    private static final int STATE_DISCONNECTED = 0;
+    private static final int STATE_CONNECTING = 1;
+    private static final int STATE_CONNECTED = 2;
+
+    /** ACTION_GATT_CONNECTED: connected to a GATT server.
+     * ACTION_GATT_DISCONNECTED: disconnected from a GATT server.
+     * ACTION_GATT_SERVICES_DISCOVERED: discovered GATT services.
+     * ACTION_DATA_AVAILABLE: received data from the device.
+     *					      this can be a result of read or notification operations.
+     */
+    public final static String ACTION_GATT_CONNECTED =
+            "com.example.bluetooth.le.ACTION_GATT_CONNECTED";
+    public final static String ACTION_GATT_DISCONNECTED =
+            "com.example.bluetooth.le.ACTION_GATT_DISCONNECTED";
+    public final static String ACTION_GATT_SERVICES_DISCOVERED =
+            "com.example.bluetooth.le.ACTION_GATT_SERVICES_DISCOVERED";
+    public final static String ACTION_DATA_AVAILABLE =
+            "com.example.bluetooth.le.ACTION_DATA_AVAILABLE";
+    public final static String EXTRA_DATA =
+            "com.example.bluetooth.le.EXTRA_DATA";
+    public final static String ACTION_CHARACTERISTIC_WRITE =
+            "com.example.bluetooth.le.ACTION_CHARACTERISTIC_WRITE";
+    public final static String EXTRA_DATA_RAW = "com.example.bluetooth.le.EXTRA_DATA_RAW";
+    public final static String EXTRA_UUID_CHAR = "com.example.bluetooth.le.EXTRA_UUID_CHAR";
+    public static String CLIENT_CHARACTERISTIC_CONFIG = "00002902-0000-1000-8000-00805f9b34fb";
+
+    // Implements callback methods for GATT events that the app cares about.  For example,
+    // connection change and services discovered.
+    private final BluetoothGattCallback mGattCallback = new BluetoothGattCallback() {
+        @Override
+        public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
+            String intentAction;
+            if (newState == BluetoothProfile.STATE_CONNECTED) {
+                intentAction = ACTION_GATT_CONNECTED;
+                mConnectionState = STATE_CONNECTED;
+                broadcastUpdate(intentAction);
+                Log.i(TAG, "Connected to GATT server.");
+                // Attempts to discover services after successful connection.
+                Log.i(TAG, "Attempting to start service discovery:" +
+                        mBluetoothGatt.discoverServices());
+
+            } else if (newState == BluetoothProfile.STATE_DISCONNECTED) {
+                intentAction = ACTION_GATT_DISCONNECTED;
+                mConnectionState = STATE_DISCONNECTED;
+                Log.i(TAG, "Disconnected from GATT server.");
+                broadcastUpdate(intentAction);
+            }
+        }
+        
+        /**
+         * Called when the BLE services are discovered
+         * @param gatt Gatt server of the device
+         * @param status Success or fail status
+         */
+        @Override
+        public void onServicesDiscovered(BluetoothGatt gatt, int status) {
+            if (status == BluetoothGatt.GATT_SUCCESS) {
+                broadcastUpdate(ACTION_GATT_SERVICES_DISCOVERED);
+            } else {
+                Log.w(TAG, "onServicesDiscovered received: " + status);
+            }
+        }
+
+        /**
+         * Called when a characteristic is read
+         * @param gatt Gatt server of device
+         * @param characteristic Characteristic that was read from
+         * @param status Success or fail status
+         */
+        @Override
+        public void onCharacteristicRead(BluetoothGatt gatt,
+                                         BluetoothGattCharacteristic characteristic,
+                                         int status) {
+            if (status == BluetoothGatt.GATT_SUCCESS) {
+                broadcastUpdate(ACTION_DATA_AVAILABLE, characteristic);
+            }
+        }
+
+        /**
+         * Called when a characteristic has changed
+         * @param gatt Gatt server of device
+         * @param characteristic Characteristic that has changed
+         */
+        @Override
+        public void onCharacteristicChanged(BluetoothGatt gatt,
+                                            BluetoothGattCharacteristic characteristic) {
+            broadcastUpdate(ACTION_DATA_AVAILABLE, characteristic);
+        }
+
+        /**
+         * Called when a descriptor has been written to...
+         * We will queue the next descriptor to write if there are any pending
+         * @param gatt Gatt server of device
+         * @param descriptor Descriptor that was written to
+         * @param status Success or failure status
+         */
+        @Override
+        public void onDescriptorWrite(BluetoothGatt gatt, BluetoothGattDescriptor descriptor, int status) {
+            super.onDescriptorWrite(gatt, descriptor, status);
+
+            if (status == BluetoothGatt.GATT_SUCCESS) {
+                Log.d(TAG, "Callback: Wrote GATT Descriptor successfully.");
+            } else {
+                Log.d(TAG, "Callback: Error writing GATT Descriptor: " + status);
+            }
+            descriptorWriteQueue.remove();  //pop the item that we just finishing writing
+            //if there is more to write, do it!
+            if (descriptorWriteQueue.size() > 0) {
+                mBluetoothGatt.writeDescriptor(descriptorWriteQueue.element());
+            } else {
+                // we are done with everything in the queue
+                // send a callback event
+                Log.i(TAG, "broadcastUpdate, done with descriptor write queue");
+            }
+        }
+    };
+
+    /**
+     * Broadcast an update to all registered to this service
+     * @param action
+     */
+    private void broadcastUpdate(final String action) {
+        final Intent intent = new Intent(action);
+        sendBroadcast(intent);
+    }
+
+    /**
+     * Broadcast an update that involves a characteristic and its data
+     * @param action
+     * @param characteristic
+     */
+    private void broadcastUpdate(final String action,
+                                 final BluetoothGattCharacteristic characteristic) {
+        final Intent intent = new Intent(action);
+        intent.putExtra(EXTRA_UUID_CHAR, characteristic.getUuid().toString());
+
+        // Always try to add the RAW value
+        final byte[] data = characteristic.getValue();
+        if (data != null && data.length > 0) {
+            intent.putExtra(EXTRA_DATA_RAW, data);
+        }
+        sendBroadcast(intent);
+    }
+
+    /**
+     * Return a binder for this system for android
+     */
+    public class LocalBinder extends Binder {
+        BluetoothLeService getService() {
+            return BluetoothLeService.this;
+        }
+    }
+
+    /**
+     * Bind using a specified intent
+     * @param intent
+     * @return
+     */
+    @Override
+    public IBinder onBind(Intent intent) {
+        return mBinder;
+    }
+
+    /**
+     * Unbind this service
+     * @param intent
+     * @return
+     */
+    @Override
+    public boolean onUnbind(Intent intent) {
+        // After using a given device, you should make sure that BluetoothGatt.close() is called
+        // such that resources are cleaned up properly.  In this particular example, close() is
+        // invoked when the UI is disconnected from the Service.
+        close();
+        return super.onUnbind(intent);
+    }
+
+    /// define a local binder for this service
+    private final IBinder mBinder = new LocalBinder();
+
+    /**
+     * Initializes a reference to the local Bluetooth adapter.
+     * @return Return true if the initialization is successful.
+     */
+    public boolean initialize() {
+        // For API level 18 and above, get a reference to BluetoothAdapter through
+        // BluetoothManager.
+        if (mBluetoothManager == null) {
+            mBluetoothManager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
+            if (mBluetoothManager == null) {
+                Log.e(TAG, "Unable to initialize BluetoothManager.");
+                return false;
+            }
+        }
+
+        mBluetoothAdapter = mBluetoothManager.getAdapter();
+        if (mBluetoothAdapter == null) {
+            Log.e(TAG, "Unable to obtain a BluetoothAdapter.");
+            return false;
+        }
+
+        return true;
+    }
+
+    /**
+     * Connects to the GATT server hosted on the Bluetooth LE device.
+     *
+     * @param address The device address of the destination device.
+     *
+     * @return Return true if the connection is initiated successfully. The connection result
+     *         is reported asynchronously through the
+     *         {@code BluetoothGattCallback#onConnectionStateChange(android.bluetooth.BluetoothGatt, int, int)}
+     *         callback.
+     */
+    public boolean connect(final String address) {
+        if (mBluetoothAdapter == null || address == null) {
+            Log.w(TAG, "BluetoothAdapter not initialized or unspecified address.");
+            return false;
+        }
+
+        // Previously connected device.  Try to reconnect.
+        if (mBluetoothDeviceAddress != null && address.equals(mBluetoothDeviceAddress)
+                && mBluetoothGatt != null) {
+            Log.d(TAG, "Trying to use an existing mBluetoothGatt for connection.");
+            if (mBluetoothGatt.connect()) {
+                mConnectionState = STATE_CONNECTING;
+                return true;
+            } else {
+                return false;
+            }
+        }
+
+        final BluetoothDevice device = mBluetoothAdapter.getRemoteDevice(address);
+        if (device == null) {
+            Log.w(TAG, "Device not found.  Unable to connect.");
+            return false;
+        }
+        // We want to directly connect to the device, so we are setting the autoConnect
+        // parameter to false.
+        mBluetoothGatt = device.connectGatt(this, false, mGattCallback);
+        Log.d(TAG, "Trying to create a new connection.");
+        mBluetoothDeviceAddress = address;
+        mConnectionState = STATE_CONNECTING;
+        return true;
+    }
+
+    /**
+     * Disconnects an existing connection or cancel a pending connection. The disconnection result
+     * is reported asynchronously through the
+     * {@code BluetoothGattCallback#onConnectionStateChange(android.bluetooth.BluetoothGatt, int, int)}
+     * callback.
+     */
+    public void disconnect() {
+        if (mBluetoothAdapter == null || mBluetoothGatt == null) {
+            Log.w(TAG, "BluetoothAdapter not initialized");
+            return;
+        }
+        mBluetoothGatt.disconnect();
+    }
+
+    /**
+     * After using a given BLE device, the app must call this method to ensure resources are
+     * released properly.
+     */
+    public void close() {
+        if (mBluetoothGatt == null) {
+            return;
+        }
+        mBluetoothGatt.close();
+        mBluetoothGatt = null;
+    }
+
+    /**
+     * Request a read on a given {@code BluetoothGattCharacteristic}. The read result is reported
+     * asynchronously through the {@code BluetoothGattCallback#onCharacteristicRead(android.bluetooth.BluetoothGatt, android.bluetooth.BluetoothGattCharacteristic, int)}
+     * callback.
+     *
+     * @param characteristic The characteristic to read from.
+     */
+    public void readCharacteristic(BluetoothGattCharacteristic characteristic) {
+        if (mBluetoothAdapter == null || mBluetoothGatt == null) {
+            Log.w(TAG, "BluetoothAdapter not initialized");
+            return;
+        }
+        mBluetoothGatt.readCharacteristic(characteristic);
+    }
+
+    /**
+     * Enables or disables notification on a give characteristic.
+     *
+     * @param characteristic Characteristic to act on.
+     * @param enabled If true, enable notification.  False otherwise.
+     */
+    public void setCharacteristicNotification(BluetoothGattCharacteristic characteristic,
+                                              boolean enabled) {
+        if (mBluetoothAdapter == null || mBluetoothGatt == null) {
+            Log.w(TAG, "BluetoothAdapter not initialized");
+            return;
+        }
+        mBluetoothGatt.setCharacteristicNotification(characteristic, enabled);
+
+    }
+
+    /**
+     * Retrieves a list of supported GATT services on the connected device. This should be
+     * invoked only after {@code BluetoothGatt#discoverServices()} completes successfully.
+     *
+     * @return A {@code List} of supported services.
+     */
+    public List<BluetoothGattService> getSupportedGattServices() {
+        if (mBluetoothGatt == null) return null;
+
+        return mBluetoothGatt.getServices();
+    }
+
+    /**
+     * Write a characteristic by refering to it by its UUID and its service UUID
+     * @param uuidService UUID of the service of the characteristic
+     * @param uuidCharacteristic UUID of the characteristic to upate
+     * @param data byte array of data to update in the characteristic
+     * @return
+     */
+    public boolean writeCharacteristic(UUID uuidService, UUID uuidCharacteristic, byte[] data) {
+        BluetoothGattService gattService = mBluetoothGatt.getService(uuidService);
+        if (gattService == null) return false;
+        BluetoothGattCharacteristic characteristic;
+        characteristic = gattService.getCharacteristic(uuidCharacteristic);
+        if (characteristic == null) {
+            Log.e(TAG, "char not found!");
+            return false;
+        }
+        //byte[] value = new byte[1];
+        //value[0] = (byte) (21 & 0xFF);
+        characteristic.setValue(data);
+        boolean status = mBluetoothGatt.writeCharacteristic(characteristic);
+        return status;
+    }
+
+    /** A queue used to allow write discriptors to be handled in a serial fashion...
+     * waiting for each one to complete before starting the next
+     */
+    private Queue<BluetoothGattDescriptor> descriptorWriteQueue = new LinkedList<BluetoothGattDescriptor>();
+
+    /**
+     * Subscrible to a characteristic
+     * @param uuidService Service that contains the characteristic
+     * @param uuidCharacteristic The characteristic to subscribe to
+     */
+    public void Subscribe(UUID uuidService, UUID uuidCharacteristic) {
+        if (mBluetoothGatt == null) return;
+        BluetoothGattService gattService = mBluetoothGatt.getService(uuidService);
+        if (gattService == null) return;
+        BluetoothGattCharacteristic characteristic;
+
+        characteristic = gattService.getCharacteristic(uuidCharacteristic);
+        //setCharacteristicNotification(characteristic, true);
+
+        setCharacteristicNotification(characteristic, true);
+        //if (UUID_BLE_SHIELD_RX.equals(characteristic.getUuid())) {
+        BluetoothGattDescriptor descriptor = characteristic.getDescriptor(UUID.fromString(CLIENT_CHARACTERISTIC_CONFIG));
+        descriptor.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
+        //WriteGattDescriptor(descriptor);
+
+        //put the descriptor into the write queue
+        descriptorWriteQueue.add(descriptor);
+        //if there is only 1 item in the queue, then write it.  If more than 1, we handle asynchronously in the callback above
+        if (descriptorWriteQueue.size() == 1) {
+            mBluetoothGatt.writeDescriptor(descriptor);
+        }
+    }
+
+    /**
+     * Unsubscribe to a characteristic
+     * @param uuidService Service that contains the characteristic
+     * @param uuidCharacteristic The characteristic to unsubscribe from
+     */
+    public void Unsubscribe(UUID uuidService, UUID uuidCharacteristic) {
+        if (mBluetoothGatt == null) return;
+        BluetoothGattService gattService = mBluetoothGatt.getService(uuidService);
+        if (gattService == null) return;
+        BluetoothGattCharacteristic characteristic;
+
+        characteristic = gattService.getCharacteristic(uuidCharacteristic);
+        //setCharacteristicNotification(characteristic, true);
+
+        setCharacteristicNotification(characteristic, false);
+        //if (UUID_BLE_SHIELD_RX.equals(characteristic.getUuid())) {
+        BluetoothGattDescriptor descriptor = characteristic.getDescriptor(UUID.fromString(CLIENT_CHARACTERISTIC_CONFIG));
+        descriptor.setValue(BluetoothGattDescriptor.DISABLE_NOTIFICATION_VALUE);
+        //WriteGattDescriptor(descriptor);
+
+        //put the descriptor into the write queue
+        descriptorWriteQueue.add(descriptor);
+        //if there is only 1 item in the queue, then write it.  If more than 1, we handle asynchronously in the callback above
+        if (descriptorWriteQueue.size() == 1) {
+            mBluetoothGatt.writeDescriptor(descriptor);
+        }
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/main/java/com/example/android/bluetoothlegatt/DeviceScanActivity.java	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,289 @@
+/*******************************************************************************
+ * Copyright (C) 2016 Maxim Integrated Products, Inc., All Rights Reserved.
+ * <p>
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ * <p>
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ * <p>
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+ * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ * <p>
+ * Except as contained in this notice, the name of Maxim Integrated
+ * Products, Inc. shall not be used except as stated in the Maxim Integrated
+ * Products, Inc. Branding Policy.
+ * <p>
+ * The mere transfer of this software does not imply any licenses
+ * of trade secrets, proprietary technology, copyrights, patents,
+ * trademarks, maskwork rights, or any other form of intellectual
+ * property whatsoever. Maxim Integrated Products, Inc. retains all
+ * ownership rights.
+ * ******************************************************************************
+ */
+package com.example.android.bluetoothlegatt;
+
+import android.app.Activity;
+import android.app.ListActivity;
+import android.bluetooth.BluetoothAdapter;
+import android.bluetooth.BluetoothDevice;
+import android.bluetooth.BluetoothManager;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.os.Bundle;
+import android.os.Handler;
+import android.view.LayoutInflater;
+import android.view.Menu;
+import android.view.MenuItem;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.BaseAdapter;
+import android.widget.ListView;
+import android.widget.TextView;
+import android.widget.Toast;
+
+import java.util.ArrayList;
+
+/**
+ * Activity for scanning and displaying available Bluetooth LE devices.
+ */
+public class DeviceScanActivity extends ListActivity {
+    public static final String EXTRA_DEVICE = "extra_device";
+    private LeDeviceListAdapter mLeDeviceListAdapter;
+    private BluetoothAdapter mBluetoothAdapter;
+    private boolean mScanning;
+    private Handler mHandler;
+
+    private static final int REQUEST_ENABLE_BT = 1;
+    // Stops scanning after 10 seconds.
+    private static final long SCAN_PERIOD = 10000;
+
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        getActionBar().setTitle("BLE Device Scan");
+        mHandler = new Handler();
+
+        // Use this check to determine whether BLE is supported on the device.  Then you can
+        // selectively disable BLE-related features.
+        if (!getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE)) {
+            Toast.makeText(this, "BLE is not supported", Toast.LENGTH_SHORT).show();
+            finish();
+        }
+
+        // Initializes a Bluetooth adapter.  For API level 18 and above, get a reference to
+        // BluetoothAdapter through BluetoothManager.
+        final BluetoothManager bluetoothManager =
+                (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
+        mBluetoothAdapter = bluetoothManager.getAdapter();
+
+        // Checks if Bluetooth is supported on the device.
+        if (mBluetoothAdapter == null) {
+            Toast.makeText(this, "Bluetooth not supported.", Toast.LENGTH_SHORT).show();
+            finish();
+            return;
+        }
+    }
+
+    @Override
+    public boolean onCreateOptionsMenu(Menu menu) {
+        getMenuInflater().inflate(R.menu.main, menu);
+        if (!mScanning) {
+            menu.findItem(R.id.menu_stop).setVisible(false);
+            menu.findItem(R.id.menu_scan).setVisible(true);
+            menu.findItem(R.id.menu_refresh).setActionView(null);
+        } else {
+            menu.findItem(R.id.menu_stop).setVisible(true);
+            menu.findItem(R.id.menu_scan).setVisible(false);
+            menu.findItem(R.id.menu_refresh).setActionView(
+                    R.layout.actionbar_indeterminate_progress);
+        }
+        return true;
+    }
+
+    @Override
+    public boolean onOptionsItemSelected(MenuItem item) {
+        switch (item.getItemId()) {
+            case R.id.menu_scan:
+                mLeDeviceListAdapter.clear();
+                scanLeDevice(true);
+                break;
+            case R.id.menu_stop:
+                scanLeDevice(false);
+                break;
+        }
+        return true;
+    }
+
+    @Override
+    protected void onResume() {
+        super.onResume();
+
+        // Ensures Bluetooth is enabled on the device.  If Bluetooth is not currently enabled,
+        // fire an intent to display a dialog asking the user to grant permission to enable it.
+        if (!mBluetoothAdapter.isEnabled()) {
+            if (!mBluetoothAdapter.isEnabled()) {
+                Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
+                startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT);
+            }
+        }
+
+        // Initializes list view adapter.
+        mLeDeviceListAdapter = new LeDeviceListAdapter();
+        setListAdapter(mLeDeviceListAdapter);
+        scanLeDevice(true);
+    }
+
+    @Override
+    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
+        // User chose not to enable Bluetooth.
+        if (requestCode == REQUEST_ENABLE_BT && resultCode == Activity.RESULT_CANCELED) {
+            finish();
+            return;
+        }
+        super.onActivityResult(requestCode, resultCode, data);
+    }
+
+    @Override
+    protected void onPause() {
+        super.onPause();
+        scanLeDevice(false);
+        mLeDeviceListAdapter.clear();
+    }
+
+    @Override
+    protected void onListItemClick(ListView l, View v, int position, long id) {
+        final BluetoothDevice device = mLeDeviceListAdapter.getDevice(position);
+        if (device == null) return;
+        //final Intent intent = new Intent(this, DeviceControlActivity.class);
+        //intent.putExtra(DeviceControlActivity.EXTRAS_DEVICE_NAME, device.getName());
+        //intent.putExtra(DeviceControlActivity.EXTRAS_DEVICE_ADDRESS, device.getAddress());
+        if (mScanning) {
+            mBluetoothAdapter.stopLeScan(mLeScanCallback);
+            mScanning = false;
+        }
+        //startActivity(intent);
+
+        final Intent intent = new Intent(this, SensorActivity.class);
+        intent.putExtra(EXTRA_DEVICE, device);
+        startActivity(intent);
+    }
+
+    private void scanLeDevice(final boolean enable) {
+        if (enable) {
+            // Stops scanning after a pre-defined scan period.
+            mHandler.postDelayed(new Runnable() {
+                @Override
+                public void run() {
+                    mScanning = false;
+                    mBluetoothAdapter.stopLeScan(mLeScanCallback);
+                    invalidateOptionsMenu();
+                }
+            }, SCAN_PERIOD);
+
+            mScanning = true;
+            mBluetoothAdapter.startLeScan(mLeScanCallback);
+        } else {
+            mScanning = false;
+            mBluetoothAdapter.stopLeScan(mLeScanCallback);
+        }
+        invalidateOptionsMenu();
+    }
+
+    // Adapter for holding devices found through scanning.
+    private class LeDeviceListAdapter extends BaseAdapter {
+        private ArrayList<BluetoothDevice> mLeDevices;
+        private LayoutInflater mInflator;
+
+        public LeDeviceListAdapter() {
+            super();
+            mLeDevices = new ArrayList<BluetoothDevice>();
+            mInflator = DeviceScanActivity.this.getLayoutInflater();
+        }
+
+        public void addDevice(BluetoothDevice device) {
+            if (!mLeDevices.contains(device)) {
+                mLeDevices.add(device);
+            }
+        }
+
+        public BluetoothDevice getDevice(int position) {
+            return mLeDevices.get(position);
+        }
+
+        public void clear() {
+            mLeDevices.clear();
+        }
+
+        @Override
+        public int getCount() {
+            return mLeDevices.size();
+        }
+
+        @Override
+        public Object getItem(int i) {
+            return mLeDevices.get(i);
+        }
+
+        @Override
+        public long getItemId(int i) {
+            return i;
+        }
+
+        @Override
+        public View getView(int i, View view, ViewGroup viewGroup) {
+            ViewHolder viewHolder;
+            // General ListView optimization code.
+            if (view == null) {
+                view = mInflator.inflate(R.layout.listitem_device, null);
+                viewHolder = new ViewHolder();
+                viewHolder.deviceAddress = (TextView) view.findViewById(R.id.device_address);
+                viewHolder.deviceName = (TextView) view.findViewById(R.id.device_name);
+                view.setTag(viewHolder);
+            } else {
+                viewHolder = (ViewHolder) view.getTag();
+            }
+
+            BluetoothDevice device = mLeDevices.get(i);
+            final String deviceName = device.getName();
+            if (deviceName != null && deviceName.length() > 0)
+                viewHolder.deviceName.setText(deviceName);
+            else
+                viewHolder.deviceName.setText(R.string.unknown_device);
+            viewHolder.deviceAddress.setText(device.getAddress());
+
+            return view;
+        }
+    }
+
+    // Device scan callback.
+    private BluetoothAdapter.LeScanCallback mLeScanCallback =
+            new BluetoothAdapter.LeScanCallback() {
+
+                @Override
+                public void onLeScan(final BluetoothDevice device, int rssi, byte[] scanRecord) {
+                    runOnUiThread(new Runnable() {
+                        @Override
+                        public void run() {
+                            mLeDeviceListAdapter.addDevice(device);
+                            mLeDeviceListAdapter.notifyDataSetChanged();
+                        }
+                    });
+                }
+            };
+
+    static class ViewHolder {
+        TextView deviceName;
+        TextView deviceAddress;
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/main/java/com/example/android/bluetoothlegatt/GattAttributeLookupTable.java	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,408 @@
+/*******************************************************************************
+ * Copyright (C) 2016 Maxim Integrated Products, Inc., All Rights Reserved.
+ * <p>
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ * <p>
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ * <p>
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+ * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ * <p>
+ * Except as contained in this notice, the name of Maxim Integrated
+ * Products, Inc. shall not be used except as stated in the Maxim Integrated
+ * Products, Inc. Branding Policy.
+ * <p>
+ * The mere transfer of this software does not imply any licenses
+ * of trade secrets, proprietary technology, copyrights, patents,
+ * trademarks, maskwork rights, or any other form of intellectual
+ * property whatsoever. Maxim Integrated Products, Inc. retains all
+ * ownership rights.
+ * ******************************************************************************
+ */
+package com.example.android.bluetoothlegatt;
+
+import java.util.HashMap;
+import java.util.Locale;
+import java.util.Map;
+
+/**
+ * This contains an effective look-up table of Service UUID as a key
+ *  and the friendly name of the service as the value
+ */ 
+public class GattAttributeLookupTable {
+    public static final String BASE_GUID = "00000000-0000-1000-8000-00805f9b34fb";
+    public static final String SERVICE_DISCOVERY_PROTOCOL_SDP = "00000001-0000-1000-8000-00805f9b34fb";
+    public static final String USER_DATAGRAM_PROTOCOL_UDP = "00000002-0000-1000-8000-00805f9b34fb";
+    public static final String RADIO_FREQUENCY_COMMUNICATION_PROTOCOL_RFCOMM = "00000003-0000-1000-8000-00805f9b34fb";
+    public static final String TCP = "00000004-0000-1000-8000-00805f9b34fb";
+    public static final String TCSBIN = "00000005-0000-1000-8000-00805f9b34fb";
+    public static final String TCSAT = "00000006-0000-1000-8000-00805f9b34fb";
+    public static final String OBJECT_EXCHANGE_PROTOCOL_OBEX = "00000008-0000-1000-8000-00805f9b34fb";
+    public static final String IP = "00000009-0000-1000-8000-00805f9b34fb";
+    public static final String FTP = "0000000a-0000-1000-8000-00805f9b34fb";
+    public static final String HTTP = "0000000c-0000-1000-8000-00805f9b34fb";
+    public static final String WSP = "0000000e-0000-1000-8000-00805f9b34fb";
+    public static final String BNEP_SVC = "0000000f-0000-1000-8000-00805f9b34fb";
+    public static final String UPNP_PROTOCOL = "00000010-0000-1000-8000-00805f9b34fb";
+    public static final String HIDP = "00000011-0000-1000-8000-00805f9b34fb";
+    public static final String HARDCOPY_CONTROL_CHANNEL_PROTOCOL = "00000012-0000-1000-8000-00805f9b34fb";
+    public static final String HARDCOPY_DATA_CHANNEL_PROTOCOL = "00000014-0000-1000-8000-00805f9b34fb";
+    public static final String HARDCOPY_NOTIFICATION_PROTOCOL = "00000016-0000-1000-8000-00805f9b34fb";
+    public static final String VCTP_PROTOCOL = "00000017-0000-1000-8000-00805f9b34fb";
+    public static final String VDTP_PROTOCOL = "00000019-0000-1000-8000-00805f9b34fb";
+    public static final String CMPT_PROTOCOL = "0000001b-0000-1000-8000-00805f9b34fb";
+    public static final String UDI_C_PLANE_PROTOCOL = "0000001d-0000-1000-8000-00805f9b34fb";
+    public static final String MCAP_CONTROL_CHANNEL = "0000001e-0000-1000-8000-00805f9b34fb";
+    public static final String MCAP_DATA_CHANNEL = "0000001f-0000-1000-8000-00805f9b34fb";
+    public static final String L2CAP = "00000100-0000-1000-8000-00805f9b34fb";
+    public static final String SERVICE_DISCOVERY_SERVER = "00001000-0000-1000-8000-00805f9b34fb";
+    public static final String BROWSE_GROUP_DESCRIPTOR = "00001001-0000-1000-8000-00805f9b34fb";
+    public static final String PUBLIC_BROWSE_GROUP = "00001002-0000-1000-8000-00805f9b34fb";
+    public static final String SPP = "00001101-0000-1000-8000-00805f9b34fb";
+    public static final String LAN_ACCESS_USING_PPP = "00001102-0000-1000-8000-00805f9b34fb";
+    public static final String DUN_GW = "00001103-0000-1000-8000-00805f9b34fb";
+    public static final String OBEX_SYNC = "00001104-0000-1000-8000-00805f9b34fb";
+    public static final String OBEX_OBJECT_PUSH = "00001105-0000-1000-8000-00805f9b34fb";
+    public static final String OBEX_FILE_TRANSFER = "00001106-0000-1000-8000-00805f9b34fb";
+    public static final String IRMC_SYNC_COMMAND = "00001107-0000-1000-8000-00805f9b34fb";
+    public static final String HSP_HS = "00001108-0000-1000-8000-00805f9b34fb";
+    public static final String CORDLESS_TELEPHONY = "00001109-0000-1000-8000-00805f9b34fb";
+    public static final String AUDIO_SOURCE = "0000110a-0000-1000-8000-00805f9b34fb";
+    public static final String AUDIO_SINK = "0000110b-0000-1000-8000-00805f9b34fb";
+    public static final String AV_REMOTE_CONTROL_TARGET = "0000110c-0000-1000-8000-00805f9b34fb";
+    public static final String ADVANCED_AUDIO = "0000110d-0000-1000-8000-00805f9b34fb";
+    public static final String AVRCP_REMOTE = "0000110e-0000-1000-8000-00805f9b34fb";
+    public static final String VIDEO_CONFERENCING = "0000110f-0000-1000-8000-00805f9b34fb";
+    public static final String INTERCOM = "00001110-0000-1000-8000-00805f9b34fb";
+    public static final String FAX = "00001111-0000-1000-8000-00805f9b34fb";
+    public static final String HEADSET_PROFILE_HSP_AUDIO_GATEWAY = "00001112-0000-1000-8000-00805f9b34fb";
+    public static final String WAP = "00001113-0000-1000-8000-00805f9b34fb";
+    public static final String WAP_CLIENT = "00001114-0000-1000-8000-00805f9b34fb";
+    public static final String PANU = "00001115-0000-1000-8000-00805f9b34fb";
+    public static final String NAP = "00001116-0000-1000-8000-00805f9b34fb";
+    public static final String GN = "00001117-0000-1000-8000-00805f9b34fb";
+    public static final String DIRECT_PRINTING = "00001118-0000-1000-8000-00805f9b34fb";
+    public static final String REFERENCE_PRINTING = "00001119-0000-1000-8000-00805f9b34fb";
+    public static final String IMAGING = "0000111a-0000-1000-8000-00805f9b34fb";
+    public static final String IMAGING_RESPONDER = "0000111b-0000-1000-8000-00805f9b34fb";
+    public static final String IMAGING_AUTOMATIC_ARCHIVE = "0000111c-0000-1000-8000-00805f9b34fb";
+    public static final String IMAGING_REFERENCE_OBJECTS = "0000111d-0000-1000-8000-00805f9b34fb";
+    public static final String HANDS_FREE_PROFILE_HFP = "0000111e-0000-1000-8000-00805f9b34fb";
+    public static final String HANDS_FREE_PROFILE_HFP_AUDIO_GATEWAY = "0000111f-0000-1000-8000-00805f9b34fb";
+    public static final String DIRECT_PRINTING_REFERENCE_OBJECTS = "00001120-0000-1000-8000-00805f9b34fb";
+    public static final String REFLECTED_UI = "00001121-0000-1000-8000-00805f9b34fb";
+    public static final String BASIC_PRINTING = "00001122-0000-1000-8000-00805f9b34fb";
+    public static final String PRINTING_STATUS = "00001123-0000-1000-8000-00805f9b34fb";
+    public static final String HID = "00001124-0000-1000-8000-00805f9b34fb";
+    public static final String HARDCOPY_CABLE_REPLACEMENT = "00001125-0000-1000-8000-00805f9b34fb";
+    public static final String HCR_PRINT = "00001126-0000-1000-8000-00805f9b34fb";
+    public static final String HCR_SCAN = "00001127-0000-1000-8000-00805f9b34fb";
+    public static final String COMMON_ISDN_ACCESS = "00001128-0000-1000-8000-00805f9b34fb";
+    public static final String VIDEO_CONFERENCING_GATEWAY = "00001129-0000-1000-8000-00805f9b34fb";
+    public static final String UDIMT = "0000112a-0000-1000-8000-00805f9b34fb";
+    public static final String UDITA = "0000112b-0000-1000-8000-00805f9b34fb";
+    public static final String AUDIO_VIDEO = "0000112c-0000-1000-8000-00805f9b34fb";
+    public static final String SIM_ACCESS = "0000112d-0000-1000-8000-00805f9b34fb";
+    public static final String OBEX_PCE = "0000112e-0000-1000-8000-00805f9b34fb";
+    public static final String OBEX_PSE = "0000112f-0000-1000-8000-00805f9b34fb";
+    public static final String OBEX_PBAP = "00001130-0000-1000-8000-00805f9b34fb";
+    public static final String OBEX_MAS = "00001132-0000-1000-8000-00805f9b34fb";
+    public static final String OBEX_MNS = "00001133-0000-1000-8000-00805f9b34fb";
+    public static final String OBEX_MAP = "00001134-0000-1000-8000-00805f9b34fb";
+    public static final String PNP = "00001200-0000-1000-8000-00805f9b34fb";
+    public static final String GENERIC_NETWORKING = "00001201-0000-1000-8000-00805f9b34fb";
+    public static final String GENERIC_FILE_TRANSFER = "00001202-0000-1000-8000-00805f9b34fb";
+    public static final String GENERIC_AUDIO = "00001203-0000-1000-8000-00805f9b34fb";
+    public static final String GENERIC_TELEPHONY = "00001204-0000-1000-8000-00805f9b34fb";
+    public static final String UPNP = "00001205-0000-1000-8000-00805f9b34fb";
+    public static final String UPNP_IP = "00001206-0000-1000-8000-00805f9b34fb";
+    public static final String ESDP_UPNP_IP_PAN = "00001300-0000-1000-8000-00805f9b34fb";
+    public static final String ESDP_UPNP_IP_LAP = "00001301-0000-1000-8000-00805f9b34fb";
+    public static final String ESDP_UPNP_L2CAP = "00001302-0000-1000-8000-00805f9b34fb";
+    public static final String VIDEO_DISTRIBUTION_PROFILE_VDP_SOURCE = "00001303-0000-1000-8000-00805f9b34fb";
+    public static final String VIDEO_DISTRIBUTION_PROFILE_VDP_SINK = "00001304-0000-1000-8000-00805f9b34fb";
+    public static final String VIDEO_DISTRIBUTION_PROFILE_VDP = "00001305-0000-1000-8000-00805f9b34fb";
+    public static final String HEALTH_DEVICE_PROFILE_HDP = "00001400-0000-1000-8000-00805f9b34fb";
+    public static final String HEALTH_DEVICE_PROFILE_HDP_SOURCE = "00001401-0000-1000-8000-00805f9b34fb";
+    public static final String HEALTH_DEVICE_PROFILE_HDP_SINK = "00001402-0000-1000-8000-00805f9b34fb";
+    public static final String GAP = "00001800-0000-1000-8000-00805f9b34fb";
+    public static final String GATT = "00001801-0000-1000-8000-00805f9b34fb";
+    public static final String IMMEDIATE_ALERT = "00001802-0000-1000-8000-00805f9b34fb";
+    public static final String LINK_LOSS = "00001803-0000-1000-8000-00805f9b34fb";
+    public static final String TX_POWER = "00001804-0000-1000-8000-00805f9b34fb";
+    public static final String HEALTH_THERMOMETER = "00001809-0000-1000-8000-00805f9b34fb";
+    public static final String DEVICE_INFORMATION = "0000180a-0000-1000-8000-00805f9b34fb";
+    public static final String HEART_RATE = "0000180d-0000-1000-8000-00805f9b34fb";
+    public static final String CYCLING_SC = "00001816-0000-1000-8000-00805f9b34fb";
+    public static final String CLIENT_CHARACTERISTIC_CONFIG = "00002902-0000-1000-8000-00805f9b34fb";
+    public static final String DEVICE_NAME = "00002a00-0000-1000-8000-00805f9b34fb";
+    public static final String APPEARANCE = "00002a01-0000-1000-8000-00805f9b34fb";
+    public static final String PERIPHERAL_PRIVACY_FLAG = "00002a02-0000-1000-8000-00805f9b34fb";
+    public static final String RECONNECTION_ADDRESS = "00002a03-0000-1000-8000-00805f9b34fb";
+    public static final String PERIPHERAL_PREFERRED_CONNECTION_PARAMETERS = "00002a04-0000-1000-8000-00805f9b34fb";
+    public static final String SERVICE_CHANGED = "00002a05-0000-1000-8000-00805f9b34fb";
+    public static final String ALERT_LEVEL = "00002a06-0000-1000-8000-00805f9b34fb";
+    public static final String TX_POWER_LEVEL = "00002a07-0000-1000-8000-00805f9b34fb";
+    public static final String DATE_TIME = "00002a08-0000-1000-8000-00805f9b34fb";
+    public static final String DAY_OF_WEEK = "00002a09-0000-1000-8000-00805f9b34fb";
+    public static final String DAY_DATE_TIME = "00002a0a-0000-1000-8000-00805f9b34fb";
+    public static final String EXACT_TIME_256 = "00002a0c-0000-1000-8000-00805f9b34fb";
+    public static final String DST_OFFSET = "00002a0d-0000-1000-8000-00805f9b34fb";
+    public static final String TIME_ZONE = "00002a0e-0000-1000-8000-00805f9b34fb";
+    public static final String LOCAL_TIME_INFORMATION = "00002a0f-0000-1000-8000-00805f9b34fb";
+    public static final String TIME_WITH_DST = "00002a11-0000-1000-8000-00805f9b34fb";
+    public static final String TIME_ACCURACY = "00002a12-0000-1000-8000-00805f9b34fb";
+    public static final String TIME_SOURCE = "00002a13-0000-1000-8000-00805f9b34fb";
+    public static final String REFERENCE_TIME_INFORMATION = "00002a14-0000-1000-8000-00805f9b34fb";
+    public static final String TIME_UPDATE_CONTROL_POINT = "00002a16-0000-1000-8000-00805f9b34fb";
+    public static final String TIME_UPDATE_STATE = "00002a17-0000-1000-8000-00805f9b34fb";
+    public static final String TEMPERATURE_MEASUREMENT = "00002a1c-0000-1000-8000-00805f9b34fb";
+    public static final String TEMPERATURE_TYPE = "00002a1d-0000-1000-8000-00805f9b34fb";
+    public static final String INTERMEDIATE_TEMPERATURE = "00002a1e-0000-1000-8000-00805f9b34fb";
+    public static final String MEASUREMENT_INTERVAL = "00002a21-0000-1000-8000-00805f9b34fb";
+    public static final String SYSTEM_ID = "00002a23-0000-1000-8000-00805f9b34fb";
+    public static final String MODEL_NUMBER_STRING = "00002a24-0000-1000-8000-00805f9b34fb";
+    public static final String SERIAL_NUMBER_STRING = "00002a25-0000-1000-8000-00805f9b34fb";
+    public static final String FIRMWARE_REVISION_STRING = "00002a26-0000-1000-8000-00805f9b34fb";
+    public static final String HARDWARE_REVISION_STRING = "00002a27-0000-1000-8000-00805f9b34fb";
+    public static final String SOFTWARE_REVISION_STRING = "00002a28-0000-1000-8000-00805f9b34fb";
+    public static final String MANUFACTURER_NAME_STRING = "00002a29-0000-1000-8000-00805f9b34fb";
+    public static final String IEEE_1107320601_REGULATORY = "00002a2a-0000-1000-8000-00805f9b34fb";
+    public static final String CURRENT_TIME = "00002a2b-0000-1000-8000-00805f9b34fb";
+    public static final String BLOOD_PRESSURE_MEASUREMENT = "00002a35-0000-1000-8000-00805f9b34fb";
+    public static final String INTERMEDIATE_CUFF_PRESSURE = "00002a36-0000-1000-8000-00805f9b34fb";
+    public static final String HEART_RATE_MEASUREMENT = "00002a37-0000-1000-8000-00805f9b34fb";
+    public static final String BODY_SENSOR_LOCATION = "00002a38-0000-1000-8000-00805f9b34fb";
+    public static final String HEART_RATE_CONTROL_POINT = "00002a39-0000-1000-8000-00805f9b34fb";
+    public static final String ALERT_STATUS = "00002a3f-0000-1000-8000-00805f9b34fb";
+    public static final String RINGER_CONTROL_POINT = "00002a40-0000-1000-8000-00805f9b34fb";
+    public static final String RINGER_SETTING = "00002a41-0000-1000-8000-00805f9b34fb";
+    public static final String ALERT_CATEGORY_ID_BIT_MASK = "00002a42-0000-1000-8000-00805f9b34fb";
+    public static final String ALERT_CATEGORY_ID = "00002a43-0000-1000-8000-00805f9b34fb";
+    public static final String ALERT_NOTIFICATION_CONTROL_POINT = "00002a44-0000-1000-8000-00805f9b34fb";
+    public static final String UNREAD_ALERT_STATUS = "00002a45-0000-1000-8000-00805f9b34fb";
+    public static final String NEW_ALERT = "00002a46-0000-1000-8000-00805f9b34fb";
+    public static final String SUPPORTED_NEW_ALERT_CATEGORY = "00002a47-0000-1000-8000-00805f9b34fb";
+    public static final String SUPPORTED_UNREAD_ALERT_CATEGORY = "00002a48-0000-1000-8000-00805f9b34fb";
+    public static final String BLOOD_PRESSURE_FEATURE = "00002a49-0000-1000-8000-00805f9b34fb";
+    public static final String PNPID = "00002a50-0000-1000-8000-00805f9b34fb";
+    public static final String SC_CONTROL_POINT = "00002a55-0000-1000-8000-00805f9b34fb";
+    public static final String CSC_MEASUREMENT = "00002a5b-0000-1000-8000-00805f9b34fb";
+    public static final String CSC_FEATURE = "00002a5c-0000-1000-8000-00805f9b34fb";
+    public static final String SENSOR_LOCATION = "00002a5d-0000-1000-8000-00805f9b34fb";
+    public static final String ACTIVESYNC = "831c4071-7bc8-4a9c-a01c-15df25a4adbc";
+    public static final String ESTIMOTE_SERVICE = "b9403000-f5f8-466e-aff9-25556b57fe6d";
+    public static final String ESTIMOTE_UUID = "b9403003-f5f8-466e-aff9-25556b57fe6d";
+    public static final String ESTIMOTE_MAJOR = "b9403001-f5f8-466e-aff9-25556b57fe6d";
+    public static final String ESTIMOTE_MINOR = "b9403002-f5f8-466e-aff9-25556b57fe6d";
+    public static final String ESTIMOTE_BATTERY = "b9403041-f5f8-466e-aff9-25556b57fe6d";
+    public static final String ESTIMOTE_TEMPERATURE = "b9403021-f5f8-466e-aff9-25556b57fe6d";
+    public static final String ESTIMOTE_POWER = "b9403011-f5f8-466e-aff9-25556b57fe6d";
+    public static final String ESTIMOTE_ADVERTISING_INTERVAL = "b9403012-f5f8-466e-aff9-25556b57fe6d";
+    public static final String ESTIMOTE_VERSION_SERVICE = "b9404000-f5f8-466e-aff9-25556b57fe6d";
+    public static final String ESTIMOTE_SOFTWARE_VERSION = "b9404001-f5f8-466e-aff9-25556b57fe6d";
+    public static final String ESTIMOTE_HARDWARE_VERSION = "b9404002-f5f8-466e-aff9-25556b57fe6d";
+    public static final String ESTIMOTE_AUTHENTICATION_SERVICE = "b9402000-f5f8-466e-aff9-25556b57fe6d";
+    public static final String ESTIMOTE_ADVERTISING_SEED = "b9402001-f5f8-466e-aff9-25556b57fe6d";
+    public static final String ESTIMOTE_ADVERTISING_VECTOR = "b9402002-f5f8-466e-aff9-25556b57fe6d";
+
+    private final static Map<String, String> sGattAttributesMap = populateGattAttributesMap();
+
+    public static String getAttributeName(final String uuid, final String fallback) {
+        final String name = sGattAttributesMap.get(uuid.toLowerCase(Locale.US));
+        return name == null ? fallback : name;
+    }
+
+    private static Map<String, String> populateGattAttributesMap() {
+        final Map<String, String> map = new HashMap<>();
+
+        map.put(BASE_GUID, "Base GUID");
+        map.put(SERVICE_DISCOVERY_PROTOCOL_SDP, "Service Discovery Protocol (SDP)");
+        map.put(USER_DATAGRAM_PROTOCOL_UDP, "User Datagram Protocol (UDP)");
+        map.put(RADIO_FREQUENCY_COMMUNICATION_PROTOCOL_RFCOMM, "Radio Frequency Communication Protocol (RFCOMM)");
+        map.put(TCP, "TCP");
+        map.put(TCSBIN, "TCSBIN");
+        map.put(TCSAT, "TCSAT");
+        map.put(OBJECT_EXCHANGE_PROTOCOL_OBEX, "Object Exchange Protocol (OBEX)");
+        map.put(IP, "IP");
+        map.put(FTP, "FTP");
+        map.put(HTTP, "HTTP");
+        map.put(WSP, "WSP");
+        map.put(BNEP_SVC, "BNEP_SVC");
+        map.put(UPNP_PROTOCOL, "UPNP Protocol");
+        map.put(HIDP, "HIDP");
+        map.put(HARDCOPY_CONTROL_CHANNEL_PROTOCOL, "Hardcopy Control Channel Protocol");
+        map.put(HARDCOPY_DATA_CHANNEL_PROTOCOL, "Hardcopy Data Channel Protocol");
+        map.put(HARDCOPY_NOTIFICATION_PROTOCOL, "Hardcopy Notification Protocol");
+        map.put(VCTP_PROTOCOL, "VCTP Protocol");
+        map.put(VDTP_PROTOCOL, "VDTP Protocol");
+        map.put(CMPT_PROTOCOL, "CMPT Protocol");
+        map.put(UDI_C_PLANE_PROTOCOL, "UDI C Plane Protocol");
+        map.put(MCAP_CONTROL_CHANNEL, "MCAP Control Channel");
+        map.put(MCAP_DATA_CHANNEL, "MCAP Data Channel");
+        map.put(L2CAP, "L2CAP");
+        map.put(SERVICE_DISCOVERY_SERVER, "Service Discovery Server");
+        map.put(BROWSE_GROUP_DESCRIPTOR, "Browse Group Descriptor");
+        map.put(PUBLIC_BROWSE_GROUP, "Public Browse Group");
+        map.put(SPP, "SPP");
+        map.put(LAN_ACCESS_USING_PPP, "LAN Access Using PPP");
+        map.put(DUN_GW, "DUN_GW");
+        map.put(OBEX_SYNC, "OBEX_SYNC");
+        map.put(OBEX_OBJECT_PUSH, "OBEX Object Push");
+        map.put(OBEX_FILE_TRANSFER, "OBEX File Transfer");
+        map.put(IRMC_SYNC_COMMAND, "IrMC Sync Command");
+        map.put(HSP_HS, "HSP_HS");
+        map.put(CORDLESS_TELEPHONY, "Cordless Telephony");
+        map.put(AUDIO_SOURCE, "Audio Source");
+        map.put(AUDIO_SINK, "Audio Sink");
+        map.put(AV_REMOTE_CONTROL_TARGET, "AV Remote Control Target");
+        map.put(ADVANCED_AUDIO, "ADVANCED_AUDIO");
+        map.put(AVRCP_REMOTE, "AVRCP_REMOTE");
+        map.put(VIDEO_CONFERENCING, "Video Conferencing");
+        map.put(INTERCOM, "Intercom");
+        map.put(FAX, "FAX");
+        map.put(HEADSET_PROFILE_HSP_AUDIO_GATEWAY, "Headset Profile (HSP) - Audio Gateway");
+        map.put(WAP, "WAP");
+        map.put(WAP_CLIENT, "WAP Client");
+        map.put(PANU, "PANU");
+        map.put(NAP, "NAP");
+        map.put(GN, "GN");
+        map.put(DIRECT_PRINTING, "Direct Printing");
+        map.put(REFERENCE_PRINTING, "Reference Printing");
+        map.put(IMAGING, "Imaging");
+        map.put(IMAGING_RESPONDER, "Imaging Responder");
+        map.put(IMAGING_AUTOMATIC_ARCHIVE, "Imaging Automatic Archive");
+        map.put(IMAGING_REFERENCE_OBJECTS, "Imaging Reference Objects");
+        map.put(HANDS_FREE_PROFILE_HFP, "Hands Free Profile (HFP)");
+        map.put(HANDS_FREE_PROFILE_HFP_AUDIO_GATEWAY, "Hands Free Profile (HFP) – Audio Gateway");
+        map.put(DIRECT_PRINTING_REFERENCE_OBJECTS, "Direct Printing Reference Objects");
+        map.put(REFLECTED_UI, "Reflected UI");
+        map.put(BASIC_PRINTING, "Basic Printing");
+        map.put(PRINTING_STATUS, "Printing Status");
+        map.put(HID, "HID");
+        map.put(HARDCOPY_CABLE_REPLACEMENT, "Hardcopy Cable Replacement");
+        map.put(HCR_PRINT, "HCR Print");
+        map.put(HCR_SCAN, "HCR Scan");
+        map.put(COMMON_ISDN_ACCESS, "Common ISDN Access");
+        map.put(VIDEO_CONFERENCING_GATEWAY, "Video Conferencing Gateway");
+        map.put(UDIMT, "UDIMT");
+        map.put(UDITA, "UDITA");
+        map.put(AUDIO_VIDEO, "Audio Video");
+        map.put(SIM_ACCESS, "SIM Access");
+        map.put(OBEX_PCE, "OBEX PCE");
+        map.put(OBEX_PSE, "OBEX PSE");
+        map.put(OBEX_PBAP, "OBEX PBAP");
+        map.put(OBEX_MAS, "OBEX MAS");
+        map.put(OBEX_MNS, "OBEX MNS");
+        map.put(OBEX_MAP, "OBEX MAP");
+        map.put(PNP, "PNP");
+        map.put(GENERIC_NETWORKING, "Generic Networking");
+        map.put(GENERIC_FILE_TRANSFER, "Generic File Transfer");
+        map.put(GENERIC_AUDIO, "Generic Audio");
+        map.put(GENERIC_TELEPHONY, "Generic Telephony");
+        map.put(UPNP, "UPNP");
+        map.put(UPNP_IP, "UPNP IP");
+        map.put(ESDP_UPNP_IP_PAN, "ESDP UPnP IP PAN");
+        map.put(ESDP_UPNP_IP_LAP, "ESDP UPnP IP LAP");
+        map.put(ESDP_UPNP_L2CAP, "ESDP Upnp L2CAP");
+        map.put(VIDEO_DISTRIBUTION_PROFILE_VDP_SOURCE, "Video Distribution Profile (VDP) - Source");
+        map.put(VIDEO_DISTRIBUTION_PROFILE_VDP_SINK, "Video Distribution Profile (VDP) - Sink");
+        map.put(VIDEO_DISTRIBUTION_PROFILE_VDP, "Video Distribution Profile (VDP)");
+        map.put(HEALTH_DEVICE_PROFILE_HDP, "Health Device Profile (HDP)");
+        map.put(HEALTH_DEVICE_PROFILE_HDP_SOURCE, "Health Device Profile (HDP) - Source");
+        map.put(HEALTH_DEVICE_PROFILE_HDP_SINK, "Health Device Profile (HDP) - Sink");
+        map.put(GAP, "GAP");
+        map.put(GATT, "GATT");
+        map.put(IMMEDIATE_ALERT, "IMMEDIATE_ALERT");
+        map.put(LINK_LOSS, "LINK_LOSS");
+        map.put(TX_POWER, "TX_POWER");
+        map.put(HEALTH_THERMOMETER, "Health Thermometer");
+        map.put(DEVICE_INFORMATION, "Device Information");
+        map.put(HEART_RATE, "HEART_RATE");
+        map.put(CYCLING_SC, "CYCLING_SC");
+        map.put(CLIENT_CHARACTERISTIC_CONFIG, "CLIENT_CHARACTERISTIC_CONFIG");
+        map.put(DEVICE_NAME, "Device Name");
+        map.put(APPEARANCE, "Appearance");
+        map.put(PERIPHERAL_PRIVACY_FLAG, "Peripheral Privacy Flag");
+        map.put(RECONNECTION_ADDRESS, "Reconnection Address");
+        map.put(PERIPHERAL_PREFERRED_CONNECTION_PARAMETERS, "Peripheral Preferred Connection Parameters");
+        map.put(SERVICE_CHANGED, "Service Changed");
+        map.put(ALERT_LEVEL, "Alert Level");
+        map.put(TX_POWER_LEVEL, "Tx Power Level");
+        map.put(DATE_TIME, "Date Time");
+        map.put(DAY_OF_WEEK, "Day of Week");
+        map.put(DAY_DATE_TIME, "Day Date Time");
+        map.put(EXACT_TIME_256, "Exact Time 256");
+        map.put(DST_OFFSET, "DST Offset");
+        map.put(TIME_ZONE, "Time Zone");
+        map.put(LOCAL_TIME_INFORMATION, "Local Time Information");
+        map.put(TIME_WITH_DST, "Time with DST");
+        map.put(TIME_ACCURACY, "Time Accuracy");
+        map.put(TIME_SOURCE, "Time Source");
+        map.put(REFERENCE_TIME_INFORMATION, "Reference Time Information");
+        map.put(TIME_UPDATE_CONTROL_POINT, "Time Update Control Point");
+        map.put(TIME_UPDATE_STATE, "Time Update State");
+        map.put(TEMPERATURE_MEASUREMENT, "Temperature Measurement");
+        map.put(TEMPERATURE_TYPE, "Temperature Type");
+        map.put(INTERMEDIATE_TEMPERATURE, "Intermediate Temperature");
+        map.put(MEASUREMENT_INTERVAL, "Measurement Interval");
+        map.put(SYSTEM_ID, "System ID");
+        map.put(MODEL_NUMBER_STRING, "Model Number String");
+        map.put(SERIAL_NUMBER_STRING, "Serial Number String");
+        map.put(FIRMWARE_REVISION_STRING, "Firmware Revision String");
+        map.put(HARDWARE_REVISION_STRING, "Hardware Revision String");
+        map.put(SOFTWARE_REVISION_STRING, "Software Revision String");
+        map.put(MANUFACTURER_NAME_STRING, "Manufacturer Name String");
+        map.put(IEEE_1107320601_REGULATORY, "IEEE 11073-20601 Regulatory");
+        map.put(CURRENT_TIME, "Current Time");
+        map.put(BLOOD_PRESSURE_MEASUREMENT, "Blood Pressure Measurement");
+        map.put(INTERMEDIATE_CUFF_PRESSURE, "Intermediate Cuff Pressure");
+        map.put(HEART_RATE_MEASUREMENT, "Heart Rate Measurement");
+        map.put(BODY_SENSOR_LOCATION, "Body Sensor Location");
+        map.put(HEART_RATE_CONTROL_POINT, "Heart Rate Control Point");
+        map.put(ALERT_STATUS, "Alert Status");
+        map.put(RINGER_CONTROL_POINT, "Ringer Control Point");
+        map.put(RINGER_SETTING, "Ringer Setting");
+        map.put(ALERT_CATEGORY_ID_BIT_MASK, "Alert Category ID Bit Mask");
+        map.put(ALERT_CATEGORY_ID, "Alert Category ID");
+        map.put(ALERT_NOTIFICATION_CONTROL_POINT, "Alert Notification Control Point");
+        map.put(UNREAD_ALERT_STATUS, "Unread Alert Status");
+        map.put(NEW_ALERT, "New Alert");
+        map.put(SUPPORTED_NEW_ALERT_CATEGORY, "Supported New Alert Category");
+        map.put(SUPPORTED_UNREAD_ALERT_CATEGORY, "Supported Unread Alert Category");
+        map.put(BLOOD_PRESSURE_FEATURE, "Blood Pressure Feature");
+        map.put(PNPID, "PNPID");
+        map.put(SC_CONTROL_POINT, "SC_CONTROL_POINT");
+        map.put(CSC_MEASUREMENT, "CSC_MEASUREMENT");
+        map.put(CSC_FEATURE, "CSC_FEATURE");
+        map.put(SENSOR_LOCATION, "SENSOR_LOCATION");
+        map.put(ACTIVESYNC, "ActiveSync");
+        map.put(ESTIMOTE_SERVICE, "Estimote Service");
+        map.put(ESTIMOTE_UUID, "Estimote UUID");
+        map.put(ESTIMOTE_MAJOR, "Estimote Major");
+        map.put(ESTIMOTE_MINOR, "Estimote Minor");
+        map.put(ESTIMOTE_BATTERY, "Estimote Battery");
+        map.put(ESTIMOTE_TEMPERATURE, "Estimote Temperature");
+        map.put(ESTIMOTE_POWER, "Estimote Power");
+        map.put(ESTIMOTE_ADVERTISING_INTERVAL, "Estimote Advertising Interval");
+        map.put(ESTIMOTE_VERSION_SERVICE, "Estimote Version Service");
+        map.put(ESTIMOTE_SOFTWARE_VERSION, "Estimote Software Version");
+        map.put(ESTIMOTE_HARDWARE_VERSION, "Estimote Hardware Version");
+        map.put(ESTIMOTE_AUTHENTICATION_SERVICE, "Estimote Authentication Service");
+        map.put(ESTIMOTE_ADVERTISING_SEED, "Estimote Advertising Seed");
+        map.put(ESTIMOTE_ADVERTISING_VECTOR, "Estimote Advertising Vector");
+
+        return map;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/main/java/com/example/android/bluetoothlegatt/SensorActivity.java	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,653 @@
+/*******************************************************************************
+ * Copyright (C) 2016 Maxim Integrated Products, Inc., All Rights Reserved.
+ * <p>
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ * <p>
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ * <p>
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+ * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ * <p>
+ * Except as contained in this notice, the name of Maxim Integrated
+ * Products, Inc. shall not be used except as stated in the Maxim Integrated
+ * Products, Inc. Branding Policy.
+ * <p>
+ * The mere transfer of this software does not imply any licenses
+ * of trade secrets, proprietary technology, copyrights, patents,
+ * trademarks, maskwork rights, or any other form of intellectual
+ * property whatsoever. Maxim Integrated Products, Inc. retains all
+ * ownership rights.
+ * ******************************************************************************
+ */
+package com.example.android.bluetoothlegatt;
+
+import android.app.Activity;
+import android.bluetooth.BluetoothDevice;
+import android.bluetooth.BluetoothGattCharacteristic;
+import android.bluetooth.BluetoothGattService;
+import android.content.BroadcastReceiver;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.ServiceConnection;
+import android.graphics.Color;
+import android.os.Bundle;
+import android.os.IBinder;
+import android.view.Menu;
+import android.view.MenuItem;
+import android.view.View;
+import android.widget.Button;
+import android.widget.TextView;
+
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.UUID;
+
+import graphing.LineGraphing;
+import graphing.LinePointCollection;
+
+public class SensorActivity extends Activity {
+    /// define intent strings used the pass in data from other activities and services
+    public static final String EXTRA_DEVICE = "extra_device";
+    private static final String LIST_NAME = "NAME";
+    private static final String LIST_UUID = "UUID";
+
+    /// controls
+    protected TextView mConnectionState;
+    protected Button mBtnTest;
+    protected TextView mTextTempTop;
+    protected TextView mTextTempTopRaw;
+    protected TextView mTextTempBottom;
+    protected TextView mTextTempBottomRaw;
+    protected TextView mTextLIS2DH_X;
+    protected TextView mTextLIS2DH_Y;
+    protected TextView mTextLIS2DH_Z;
+    protected TextView mTextLIS2DHRaw;
+    protected TextView mTextPressure;
+    protected TextView mTextTemperature;
+    protected TextView mTextPressureRaw;
+    protected TextView mTextHeartRate;
+    protected TextView mTextHeartRateRaw;
+    protected Button mBtnSubscribe;
+    protected TextView mClickStartBtn;
+    protected TextView mClickStartBtn2;
+    protected TextView mAccelMissionStopped;
+    protected TextView mECGMissionStopped;
+
+    /// accelerometer
+    protected LineGraphing lineGraphingAccelerometer;
+    LinePointCollection linePointCollectionX;
+    LinePointCollection linePointCollectionY;
+    LinePointCollection linePointCollectionZ;
+
+    /// pressure
+    protected LineGraphing lineGraphingPressure;
+    LinePointCollection linePointCollectionPressure;
+
+    /// temperature 1
+    protected LineGraphing lineGraphingTemperature1;
+    LinePointCollection linePointCollectionTemperature1;
+
+    /// temperature 2
+    protected LineGraphing lineGraphingTemperature2;
+    LinePointCollection linePointCollectionTemperature2;
+
+    /// heartrate
+    protected LineGraphing lineGraphingHeartrate;
+    LinePointCollection linePointCollectionHeartrate;
+
+    /// define variables of values that we care about
+    private String mDeviceName;
+    private String mDeviceAddress;
+    private boolean mConnected = false;
+    private String mExportString;
+    private BluetoothGattCharacteristic mNotifyCharacteristic;
+    private BluetoothLeService mBluetoothLeService;
+    private List<List<BluetoothGattCharacteristic>> mGattCharacteristics = new ArrayList<>();
+
+    /// bool used to determine if we should enable the mission start button
+    boolean isMissionButtonEnabled = true;
+
+    /// define the UUIDs of the HSP BLE service and characteristics
+    public final static String BLE_MAXIM_HSP_SERVICE = "5c6e40e8-3b7f-4286-a52f-daec46abe851"; // hsp service
+    public final static String BLE_MAXIM_HSP_TEMPERATURE_TOP_CHARACTERISTIC = "3544531b-00c3-4342-9755-b56abe8e6c67"; // temp top
+    public final static String BLE_MAXIM_HSP_TEMPERATURE_BOTTOM_CHARACTERISTIC = "3544531b-00c3-4342-9755-b56abe8e6a66"; // temp bottom
+    public final static String BLE_MAXIM_HSP_ACCEL_CHARACTERISTIC = "e6c9da1a-8096-48bc-83a4-3fca383705af"; //accel
+    public final static String BLE_MAXIM_HSP_PRESSURE_CHARACTERISTIC = "1d8a1932-da49-49ad-91d8-800832e7e940";  // pressure
+    public final static String BLE_MAXIM_HSP_HEARTRATE_CHARACTERISTIC = "621a00e3-b093-46bf-aadc-abe4c648c569";  // heart rate
+    public final static String BLE_MAXIM_HSP_COMMAND_CHARACTERISTIC = "36e55e37-6b5b-420b-9107-0d34a0e8675a"; // command
+
+    /**
+     * Subscribe to all of the HSP characteristics that we care about
+     */
+    private void subscribeCharacteristics() {
+        for (List<BluetoothGattCharacteristic> chars : mGattCharacteristics) {
+            for (BluetoothGattCharacteristic cha : chars) {
+                if (cha.getService().getUuid().compareTo(UUID.fromString(BLE_MAXIM_HSP_SERVICE)) == 0) {
+                    if (cha.getUuid().compareTo(UUID.fromString(BLE_MAXIM_HSP_TEMPERATURE_TOP_CHARACTERISTIC)) == 0) {
+                        mBluetoothLeService.Subscribe(cha.getService().getUuid(), cha.getUuid());
+                    }
+                    if (cha.getUuid().compareTo(UUID.fromString(BLE_MAXIM_HSP_TEMPERATURE_BOTTOM_CHARACTERISTIC)) == 0) {
+                        mBluetoothLeService.Subscribe(cha.getService().getUuid(), cha.getUuid());
+                    }
+                    if (cha.getUuid().compareTo(UUID.fromString(BLE_MAXIM_HSP_ACCEL_CHARACTERISTIC)) == 0) {
+                        mBluetoothLeService.Subscribe(cha.getService().getUuid(), cha.getUuid());
+                    }
+                    if (cha.getUuid().compareTo(UUID.fromString(BLE_MAXIM_HSP_HEARTRATE_CHARACTERISTIC)) == 0) {
+                        mBluetoothLeService.Subscribe(cha.getService().getUuid(), cha.getUuid());
+                    }
+                    if (cha.getUuid().compareTo(UUID.fromString(BLE_MAXIM_HSP_PRESSURE_CHARACTERISTIC)) == 0) {
+                        mBluetoothLeService.Subscribe(cha.getService().getUuid(), cha.getUuid());
+                    }
+                }
+            }
+        }
+    }
+
+    /**
+     * Called from the activity framework when the activity is created
+     */
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.activity_sensor);
+
+        // bind the misc TextView fields
+        mConnectionState = (TextView) findViewById(R.id.connection_state);
+        mBtnTest = (Button) findViewById(R.id.btnTest);
+        mTextTempTop = (TextView) findViewById(R.id.textTempTop);
+        mTextTempTopRaw = (TextView) findViewById(R.id.textTempTopRaw);
+        mTextTempBottom = (TextView) findViewById(R.id.textTempBottom);
+        mTextTempBottomRaw = (TextView) findViewById(R.id.textTempBottomRaw);
+        mTextLIS2DH_X = (TextView) findViewById(R.id.textLIS2DH_X);
+        mTextLIS2DH_Y = (TextView) findViewById(R.id.textLIS2DH_Y);
+        mTextLIS2DH_Z = (TextView) findViewById(R.id.textLIS2DH_Z);
+        mTextLIS2DHRaw = (TextView) findViewById(R.id.textLIS2DHRaw);
+        mTextPressure = (TextView) findViewById(R.id.textPressure);
+        mTextTemperature = (TextView) findViewById(R.id.textTemperature);
+        mTextPressureRaw = (TextView) findViewById(R.id.textPressureRaw);
+        mTextHeartRate = (TextView) findViewById(R.id.textHeartRate);
+        mTextHeartRateRaw = (TextView) findViewById(R.id.textHeartRateRaw);
+        mBtnSubscribe = (Button) findViewById(R.id.btnSubscribe);
+        mClickStartBtn = (TextView) findViewById(R.id.clickStartBtn);
+        mClickStartBtn2 = (TextView) findViewById(R.id.clickStartBtn2);
+        mAccelMissionStopped = (TextView) findViewById(R.id.textView7);
+        mECGMissionStopped = (TextView) findViewById(R.id.textView8);
+        /// accelerometer
+        lineGraphingAccelerometer = (LineGraphing) findViewById(R.id.lineGraphingAccelerometer);
+        /// pressure
+        lineGraphingPressure = (LineGraphing) findViewById(R.id.lineGraphingPressure);
+        /// temperature 1
+        lineGraphingTemperature1 = (LineGraphing) findViewById(R.id.lineGraphingTemperature1);
+        /// temperature 2
+        lineGraphingTemperature2 = (LineGraphing) findViewById(R.id.lineGraphingTemperature2);
+        /// heartrate
+        lineGraphingHeartrate = (LineGraphing) findViewById(R.id.lineGraphingHeartrate);
+
+        mBtnSubscribe.setOnClickListener(new View.OnClickListener() {
+            @Override
+            public void onClick(View view) {
+                //mBluetoothLeService.connect(mDeviceAddress);
+            }
+        });
+
+        mClickStartBtn2.setOnClickListener(new View.OnClickListener() {
+            @Override
+            public void onClick(View view) {
+                missionClick();
+            }
+        });
+
+        final Intent intent = getIntent();
+        final BluetoothDevice device = intent.getParcelableExtra(EXTRA_DEVICE);
+        mDeviceName = device.getName();
+        mDeviceAddress = device.getAddress();
+        ((TextView) findViewById(R.id.device_address)).setText(mDeviceAddress);
+
+        //getSupportActionBar().setTitle(mDeviceName);
+        //getSupportActionBar().setDisplayHomeAsUpEnabled(true);
+
+        final Intent gattServiceIntent = new Intent(this, BluetoothLeService.class);
+        bindService(gattServiceIntent, mServiceConnection, BIND_AUTO_CREATE);
+
+        // setup the accelerometer linegraph collections
+        linePointCollectionX = new LinePointCollection(Color.RED, 20);
+        linePointCollectionY = new LinePointCollection(Color.GREEN, 20);
+        linePointCollectionZ = new LinePointCollection(Color.BLUE, 20);
+        lineGraphingAccelerometer.addPointCollection(linePointCollectionX);
+        lineGraphingAccelerometer.addPointCollection(linePointCollectionY);
+        lineGraphingAccelerometer.addPointCollection(linePointCollectionZ);
+
+        // setup the pressure linegraph collections
+        linePointCollectionPressure = new LinePointCollection(Color.BLACK, 20);
+        lineGraphingPressure.addPointCollection(linePointCollectionPressure);
+
+        // setup the temperature 1 linegraph collections
+        linePointCollectionTemperature1 = new LinePointCollection(Color.BLACK, 20);
+        lineGraphingTemperature1.addPointCollection(linePointCollectionTemperature1);
+
+        // setup the temperature 2 linegraph collections
+        linePointCollectionTemperature1 = new LinePointCollection(Color.BLACK, 20);
+        lineGraphingTemperature1.addPointCollection(linePointCollectionTemperature1);
+
+        linePointCollectionTemperature2 = new LinePointCollection(Color.BLACK, 20);
+        lineGraphingTemperature2.addPointCollection(linePointCollectionTemperature2);
+
+        linePointCollectionHeartrate = new LinePointCollection(Color.BLACK, 20);
+        lineGraphingHeartrate.addPointCollection(linePointCollectionHeartrate);
+
+
+
+    }
+
+    /**
+     * Called from the activity framework when the activity is paused
+     */
+    @Override
+    protected void onPause() {
+        super.onPause();
+        unregisterReceiver(mGattUpdateReceiver);
+    }
+
+    /**
+     * Called from the activity framework when the activity is resuming
+     */
+    @Override
+    protected void onResume() {
+        super.onResume();
+        registerReceiver(mGattUpdateReceiver, makeGattUpdateIntentFilter());
+        if (mBluetoothLeService != null) {
+            final boolean result = mBluetoothLeService.connect(mDeviceAddress);
+        }
+    }
+
+    /**
+     * Define an intent filter of actions to respond to
+     * @return Returns the intent filter that is created
+     */
+    private static IntentFilter makeGattUpdateIntentFilter() {
+        final IntentFilter intentFilter = new IntentFilter();
+        intentFilter.addAction(BluetoothLeService.ACTION_GATT_CONNECTED);
+        intentFilter.addAction(BluetoothLeService.ACTION_GATT_DISCONNECTED);
+        intentFilter.addAction(BluetoothLeService.ACTION_GATT_SERVICES_DISCOVERED);
+        intentFilter.addAction(BluetoothLeService.ACTION_DATA_AVAILABLE);
+        intentFilter.addAction(BluetoothLeService.ACTION_CHARACTERISTIC_WRITE);
+        return intentFilter;
+    }
+
+    // Code to manage Service lifecycle.
+    private final ServiceConnection mServiceConnection = new ServiceConnection() {
+        @Override
+        public void onServiceConnected(final ComponentName componentName, final IBinder service) {
+            mBluetoothLeService = ((BluetoothLeService.LocalBinder) service).getService();
+            if (!mBluetoothLeService.initialize()) {
+                finish();
+            }
+            // Automatically connects to the device upon successful start-up initialization.
+            mBluetoothLeService.connect(mDeviceAddress);
+        }
+
+        @Override
+        public void onServiceDisconnected(final ComponentName componentName) {
+            mBluetoothLeService = null;
+            //finish();
+        }
+    };
+
+    /**
+     * Handles various events fired by the Service.
+     */
+    private final BroadcastReceiver mGattUpdateReceiver = new BroadcastReceiver() {
+        @Override
+        public void onReceive(final Context context, final Intent intent) {
+            final String action = intent.getAction();
+            if (BluetoothLeService.ACTION_GATT_CONNECTED.equals(action)) {
+                mConnected = true;
+                updateConnectionState(R.string.connected);
+                invalidateOptionsMenu();
+            } else if (BluetoothLeService.ACTION_GATT_DISCONNECTED.equals(action)) {
+                mConnected = false;
+                updateConnectionState(R.string.disconnected);
+                invalidateOptionsMenu();
+                finish();   // get out of this activity and back to the parent
+            } else if (BluetoothLeService.ACTION_GATT_SERVICES_DISCOVERED.equals(action)) {
+                // Show all the supported services and characteristics on the user interface.
+                displayGattServices(mBluetoothLeService.getSupportedGattServices());
+                subscribeCharacteristics();
+            } else if (BluetoothLeService.ACTION_DATA_AVAILABLE.equals(action)) {
+                final String noData = getString(R.string.no_data);
+                final String uuid = intent.getStringExtra(BluetoothLeService.EXTRA_UUID_CHAR);
+                final byte[] dataArr = intent.getByteArrayExtra(BluetoothLeService.EXTRA_DATA_RAW);
+                if (uuid != null) {
+                    UpdateUI(UUID.fromString(uuid), dataArr);
+                }
+            } else if (BluetoothLeService.ACTION_CHARACTERISTIC_WRITE.equals(action)) {
+                final String uuid = intent.getStringExtra(BluetoothLeService.EXTRA_UUID_CHAR);
+                if (uuid.equalsIgnoreCase(BLE_MAXIM_HSP_COMMAND_CHARACTERISTIC)) {
+                    EnableMissionButton(true);
+                }
+            }
+        }
+    };
+
+    /**
+     * Enable or disable the Start Mission Button based on HSP state variable
+     * @param state Enabled or disabled status
+     */
+    private void EnableMissionButton(boolean state) {
+        isMissionButtonEnabled = state;
+        if (state) {
+            mClickStartBtn2.setBackgroundColor(Color.BLACK);
+        } else {
+            mClickStartBtn2.setBackgroundColor(Color.LTGRAY);
+        }
+    }
+
+    /**
+     * Update the connection status
+     * @param resourceId Resource id that is bound to the status test view field
+     */
+    private void updateConnectionState(final int resourceId) {
+        runOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                final int colourId;
+
+                switch (resourceId) {
+                    case R.string.connected:
+                        colourId = android.R.color.holo_green_dark;
+                        break;
+                    case R.string.disconnected:
+                        colourId = android.R.color.holo_red_dark;
+                        break;
+                    default:
+                        colourId = android.R.color.black;
+                        break;
+                }
+
+                mConnectionState.setText(resourceId);
+                mConnectionState.setTextColor(getResources().getColor(colourId));
+            }
+        });
+    }
+
+    /**
+     * Convert the temperature from celsius to fahrenheit
+     * @param celsius temperature to convert
+     * @return converted temperature in fahrenheit
+     */
+    private float ToFahrenheit(float celsius) {
+        return celsius * 9 / 5 + 32;
+    }
+
+    /**
+     * Convert the incoming byte data array into a temperature
+     * @param data Data array containing two elements
+     * @return temperature as a float in celcius
+     */
+    private float ToTemperature(byte[] data) {
+        float value;
+        value = (float) data[1] + (float) data[0] / 256.0f;
+        return value;
+    }
+
+    /**
+     * Convert the portion of the byte array into a float
+     * @param data Array to convert, a part of this array is converted based on a offset
+     * @param offset Offset into the array to extract the float
+     * @return Returns the float that was converted
+     */
+    private float PartialArrayToFloat(byte[] data, int offset) {
+        short value = (short) ((short) (data[offset + 1] << 8) + (short) data[offset]);
+        return (float) value;
+    }
+
+    /**
+     * Calculate the heart rate from the ECG RtoR device
+     * @param data Incoming data to convert
+     * @return Returns a float representing the heart rate
+     */
+    private float CalculateHeartRate(byte[] data) {
+        float t = 8.0f;
+        float value = 0;
+        float RtoR = (float) ((int) data[1] << 8) + (float) data[0];
+        float fmStr = (float) ((int) data[3] << 8) + (float) data[2];
+        if (fmStr == 0.0f) t = 7.813f;
+        if (RtoR > 0.0f) {
+            value = 60000.0f / (RtoR * t);
+        }
+        return value;
+    }
+
+    /**
+     * Update the UI for a given characteristic uuid using data
+     * This will update all of the text view values for the given characteristic
+     * It also will graph the incoming data
+     * @param characteristic Characteristic to update with given data
+     * @param data Data used to update the UI
+     */
+    private void UpdateUI(UUID characteristic, byte[] data) {
+        float x = 0;
+        float y = 0;
+        float z = 0;
+        float value = 0;
+        String str = "";
+        str = bytesToHex(data);
+        // temperature top
+        if (characteristic.compareTo(UUID.fromString(BLE_MAXIM_HSP_TEMPERATURE_TOP_CHARACTERISTIC)) == 0) {
+            mTextTempTopRaw.setText(str);
+            value = ToFahrenheit(ToTemperature(data));
+            mTextTempTop.setText(String.format("%.1f", value) + "F");
+            linePointCollectionTemperature1.addpoint(value);
+            lineGraphingTemperature1.plotPointCollection();
+        }
+        // temperature bottom
+        if (characteristic.compareTo(UUID.fromString(BLE_MAXIM_HSP_TEMPERATURE_BOTTOM_CHARACTERISTIC)) == 0) {
+            mTextTempBottomRaw.setText(str);
+            value = ToFahrenheit(ToTemperature(data));
+            mTextTempBottom.setText(String.format("%.1f", value) + "F");
+            linePointCollectionTemperature2.addpoint(value);
+            lineGraphingTemperature2.plotPointCollection();
+        }
+        // acceleration
+        if (characteristic.compareTo(UUID.fromString(BLE_MAXIM_HSP_ACCEL_CHARACTERISTIC)) == 0) {
+            mTextLIS2DHRaw.setText(str);
+            x = PartialArrayToFloat(data, 0);
+            y = PartialArrayToFloat(data, 2);
+            z = PartialArrayToFloat(data, 4);
+            mTextLIS2DH_X.setText(String.format("X: %.1f", x));
+            mTextLIS2DH_Y.setText(String.format("Y: %.1f", y));
+            mTextLIS2DH_Z.setText(String.format("Z: %.1f", z));
+            linePointCollectionX.addpoint(x);
+            linePointCollectionY.addpoint(y);
+            linePointCollectionZ.addpoint(z);
+            lineGraphingAccelerometer.plotPointCollection();
+        }
+        // pressure
+        if (characteristic.compareTo(UUID.fromString(BLE_MAXIM_HSP_PRESSURE_CHARACTERISTIC)) == 0) {
+            String pressureStr = "";
+            int n = 0;
+            int bits;
+            byte[] arr = {data[0], data[1], data[2], data[3]};
+            ByteBuffer bb = ByteBuffer.wrap(arr);
+            bb.order(ByteOrder.LITTLE_ENDIAN);
+            bits = bb.getInt();
+            float temperature = Float.intBitsToFloat(bits);
+            n = 4;
+            //bits = data[n] | data[n+1]<<8 | data[n+2]<<16 | data[n+3]<<24;
+            byte[] arr2 = {data[4], data[5], data[6], data[7]};
+            ByteBuffer bb2 = ByteBuffer.wrap(arr2);
+            bb2.order(ByteOrder.LITTLE_ENDIAN);
+            bits = bb2.getInt();
+            float pressure = Float.intBitsToFloat(bits);
+            mTextPressure.setText(String.format("%.1f", pressure) + "Pa");
+            linePointCollectionPressure.addpoint(pressure);
+            lineGraphingPressure.plotPointCollection();
+        }
+        // heartrate
+        if (characteristic.compareTo(UUID.fromString(BLE_MAXIM_HSP_HEARTRATE_CHARACTERISTIC)) == 0) {
+            mTextHeartRateRaw.setText(str);
+            value = CalculateHeartRate(data);
+            mTextHeartRate.setText(String.format("%.1f", value));
+            linePointCollectionHeartrate.addpoint(value);
+            lineGraphingHeartrate.plotPointCollection();
+        }
+    }
+
+    /// array of hex ascii values used for hex byte to string conversion
+    final protected static char[] hexArray = "0123456789ABCDEF".toCharArray();
+
+    /**
+     * Convert a series of bytes within a given array into a string
+     * @param bytes Arbitrary array of bytes to convert
+     * @return String is returned containing the bytes as hex ascii values
+     */
+    public static String bytesToHex(byte[] bytes) {
+        char[] hexChars = new char[bytes.length * 2];
+        for (int j = 0; j < bytes.length; j++) {
+            int v = bytes[j] & 0xFF;
+            hexChars[j * 2] = hexArray[v >>> 4];
+            hexChars[j * 2 + 1] = hexArray[v & 0x0F];
+        }
+        return new String(hexChars);
+    }
+
+    /**
+     *  Demonstrates how to iterate through the supported GATT Services/Characteristics.
+     * In this sample, we populate the data structure that is bound to the ExpandableListView
+     * on the UI.
+     * @param gattServices List of services to parse and display
+     */
+    private void displayGattServices(final List<BluetoothGattService> gattServices) {
+        if (gattServices == null) return;
+
+        String uuid = null;
+        final String unknownServiceString = getResources().getString(R.string.unknown_service);
+        final String unknownCharaString = getResources().getString(R.string.unknown_characteristic);
+        final List<Map<String, String>> gattServiceData = new ArrayList<>();
+        final List<List<Map<String, String>>> gattCharacteristicData = new ArrayList<>();
+        mGattCharacteristics = new ArrayList<>();
+
+        // Loops through available GATT Services.
+        for (final BluetoothGattService gattService : gattServices) {
+            final Map<String, String> currentServiceData = new HashMap<>();
+            uuid = gattService.getUuid().toString();
+            currentServiceData.put(LIST_NAME, GattAttributeLookupTable.getAttributeName(uuid, unknownServiceString));
+            currentServiceData.put(LIST_UUID, uuid);
+            gattServiceData.add(currentServiceData);
+
+            final List<Map<String, String>> gattCharacteristicGroupData = new ArrayList<>();
+            final List<BluetoothGattCharacteristic> gattCharacteristics = gattService.getCharacteristics();
+            final List<BluetoothGattCharacteristic> charas = new ArrayList<>();
+
+            // Loops through available Characteristics.
+            for (final BluetoothGattCharacteristic gattCharacteristic : gattCharacteristics) {
+                charas.add(gattCharacteristic);
+                final Map<String, String> currentCharaData = new HashMap<>();
+                uuid = gattCharacteristic.getUuid().toString();
+                currentCharaData.put(LIST_NAME, GattAttributeLookupTable.getAttributeName(uuid, unknownCharaString));
+                currentCharaData.put(LIST_UUID, uuid);
+                gattCharacteristicGroupData.add(currentCharaData);
+            }
+
+            mGattCharacteristics.add(charas);
+            gattCharacteristicData.add(gattCharacteristicGroupData);
+        }
+    }
+
+    /**
+     * Given a TextView, output a string plus units concatenated
+     * @param textView View to set
+     * @param value String representing the value
+     * @param units String representing the units
+     */
+    private void SetSensorText(TextView textView, String value, String units) {
+        textView.setText(value + units);
+    }
+
+    /**
+     * Create the menu for the options
+     * @param menu the menu to set the options for
+     * @return true if created
+     */
+    @Override
+    public boolean onCreateOptionsMenu(final Menu menu) {
+        getMenuInflater().inflate(R.menu.gatt_services, menu);
+        if (mConnected) {
+            menu.findItem(R.id.menu_connect).setVisible(false);
+            menu.findItem(R.id.menu_disconnect).setVisible(true);
+        } else {
+            menu.findItem(R.id.menu_connect).setVisible(true);
+            menu.findItem(R.id.menu_disconnect).setVisible(false);
+        }
+        return true;
+    }
+
+    /**
+     * Called when the user selects a menu item
+     * @param item Selected menu item
+     * @return returns true if the selection was handled
+     */
+    @Override
+    public boolean onOptionsItemSelected(final MenuItem item) {
+        switch (item.getItemId()) {
+            case R.id.menu_connect:
+                mBluetoothLeService.connect(mDeviceAddress);
+                return true;
+            case R.id.menu_disconnect:
+                mBluetoothLeService.disconnect();
+                return true;
+            case android.R.id.home:
+                mBluetoothLeService.disconnect();
+                return true;
+        }
+        return super.onOptionsItemSelected(item);
+    }
+
+    /**
+     * Mission button clicked
+     * @param v The handle of the view clicked
+     */
+    public void onClick(View v) {
+        missionClick();
+    }
+
+    /**
+     * Start or stop the mission
+     */
+    private void missionClick() {
+        byte[] data = new byte[1];
+        //if (isMissionButtonEnabled == false) return;
+
+        if (mClickStartBtn2.getText().toString().equalsIgnoreCase("Stop Mission") == true) {
+            // stop
+            data[0] = 0x00;
+            mBluetoothLeService.writeCharacteristic(UUID.fromString(BLE_MAXIM_HSP_SERVICE), UUID.fromString(BLE_MAXIM_HSP_COMMAND_CHARACTERISTIC), data);
+            mClickStartBtn2.setText("Start Mission");
+            EnableMissionButton(false);
+        } else {
+            // start
+            data[0] = 0x01;
+            mBluetoothLeService.writeCharacteristic(UUID.fromString(BLE_MAXIM_HSP_SERVICE), UUID.fromString(BLE_MAXIM_HSP_COMMAND_CHARACTERISTIC), data);
+            mClickStartBtn2.setText("Stop Mission");
+            EnableMissionButton(false);
+        }
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/main/java/graphing/LineGraphing.java	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,233 @@
+/*******************************************************************************
+ * Copyright (C) 2016 Maxim Integrated Products, Inc., All Rights Reserved.
+ * <p>
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ * <p>
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ * <p>
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+ * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ * <p>
+ * Except as contained in this notice, the name of Maxim Integrated
+ * Products, Inc. shall not be used except as stated in the Maxim Integrated
+ * Products, Inc. Branding Policy.
+ * <p>
+ * The mere transfer of this software does not imply any licenses
+ * of trade secrets, proprietary technology, copyrights, patents,
+ * trademarks, maskwork rights, or any other form of intellectual
+ * property whatsoever. Maxim Integrated Products, Inc. retains all
+ * ownership rights.
+ * ******************************************************************************
+ */
+package graphing;
+
+import android.content.Context;
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.Paint;
+import android.util.AttributeSet;
+import android.view.View;
+
+import java.util.ArrayList;
+
+/**
+ * Provides simple line graphing for one or multiple lines on a single graph
+ */
+public class LineGraphing extends View {
+
+    private Bitmap mBitmap;
+    private Paint mPaint = new Paint();
+    private Canvas mCanvas = new Canvas();
+
+    private float mLastX;
+    private float mScale;
+    private float mLastValue;
+    private float mYOffset;
+    /// the width of this view
+    private float mWidth;
+    /// the height of this view
+    private float mHeight;
+
+    private Paint linePaint = new Paint();
+    private Paint pointPaint = new Paint();
+    private static final int DEFAULT_LINE_STROKE_WIDTH_DP = 2;
+    protected float density;
+    ArrayList<LinePointCollection> pointCollections;
+    float runningMaxY;
+    float runningMinY;
+
+    /**
+     * Default constuctor for a given context
+     * @param context
+     */
+    public LineGraphing(Context context) {
+        super(context);
+        init();
+    }
+
+    /**
+     * Constructor that accomidated a contect and set of attributes
+     * @param context
+     * @param attrs
+     */
+    public LineGraphing(Context context, AttributeSet attrs) {
+        super(context, attrs);
+        this.density = context.getResources().getDisplayMetrics().density;
+        init();
+    }
+
+    /**
+     * Init this view with render paint defaults
+     */
+    private void init() {
+        mPaint.setFlags(Paint.ANTI_ALIAS_FLAG);
+        linePaint.setAntiAlias(true);
+        linePaint.setStyle(Paint.Style.STROKE);
+        linePaint.setStrokeCap(Paint.Cap.ROUND);
+        linePaint.setStrokeWidth(2); //dp2px(density, DEFAULT_LINE_STROKE_WIDTH_DP));
+        pointPaint.setAntiAlias(true);
+        pointPaint.setStyle(Paint.Style.FILL);
+        pointCollections = new ArrayList<>();
+        mLastX = 0;
+    }
+
+    /**
+     * Calculate the pixel width for a given density
+     * @param density
+     * @param dp
+     * @return
+     */
+    public static int dp2px(float density, int dp) {
+        if (dp == 0) {
+            return 0;
+        }
+        return (int) (dp * density + 0.5f);
+    }
+
+    /**
+     * Specify the point collection to use for this graph
+     * @param _pointCollection
+     */
+    public void addPointCollection(LinePointCollection _pointCollection) {
+        pointCollections.add(_pointCollection);
+    }
+
+    /**
+     * Calculate the extremes of all point collections
+     * Used to autoscale graph
+     */
+    public void calculateGraphExtremes() {
+        runningMaxY = Float.MIN_VALUE;
+        runningMinY = Float.MAX_VALUE;
+        for (LinePointCollection pointCollection : pointCollections) {
+            if (pointCollection.getRunningMaxY() > runningMaxY)
+                runningMaxY = pointCollection.getRunningMaxY();
+            if (pointCollection.getRunningMinY() < runningMinY)
+                runningMinY = pointCollection.getRunningMinY();
+        }
+    }
+
+    /**
+     * Plot all of the point collections and invalidate the view to force a view refresh
+     */
+    public void plotPointCollection() {
+        calculateGraphExtremes();
+        // clear the canvas
+        mCanvas.drawColor(Color.WHITE);
+        for (LinePointCollection pointCollection : pointCollections) {
+            // space out graph on x based on number of points to show and the width of the graph
+            linePaint.setColor(pointCollection.getColor());
+            mLastValue = pointCollection.getDroppedPointY();
+            mLastX = 0;
+            for (LinePoint point : pointCollection.getPoints()) {
+                plotDataPoint(mCanvas, point, runningMaxY, runningMinY, pointCollection.getMaxCount(), 10);
+                drawPoint(mCanvas, point, 3);
+            }
+        }
+        invalidate();
+    }
+
+    /**
+     * Plot a single point on the graph
+     * @param canvas Canvas to paint to
+     * @param point Point to plot
+     * @param max The calculated max for the set
+     * @param min The calculated min for the set
+     * @param numberPointsAcross Number of points to plot horizontally on the graph
+     * @param margin The top and bottom pixel margin to use
+     */
+    private void plotDataPoint(Canvas canvas, LinePoint point, float max, float min, float numberPointsAcross, float margin) {
+        final Paint paint = linePaint;
+        float newX;
+        float v;
+        float stepX;
+
+        // scale the graph horizontally
+        stepX = mWidth / numberPointsAcross;
+        newX = mLastX + stepX;
+        // scale the graph vertically
+        v = max - point.y;
+        v = (v / (max - min)) * (mHeight - margin) + margin / 2;
+
+        point.rawX = newX;
+        point.rawY = v;
+
+        canvas.drawLine(mLastX, mLastValue, newX, v, paint);
+        mLastValue = v;
+        mLastX += stepX;
+    }
+
+    /**
+     * Draw the X,Y point on the graph using a circle
+     * @param canvas Canvas to use to when drawing
+     * @param point Point that contains the raw pixel X,Y point
+     * @param pointRadius The radius of the circular dot to draw
+     */
+    private void drawPoint(Canvas canvas, LinePoint point,
+                           float pointRadius) {
+        canvas.drawCircle(point.rawX, point.rawY, pointRadius, pointPaint);
+    }
+
+    /**
+     * Called by the view framework when the view is initially drawn or the size changes
+     * @param w New width of the view
+     * @param h New height of the view
+     * @param oldw Old width of the view
+     * @param oldh Old height of the view
+     */
+    @Override
+    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
+        mBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.RGB_565);
+        mCanvas.setBitmap(mBitmap);
+        mCanvas.drawColor(0xFFFFFFFF);
+        mYOffset = h;
+        mWidth = w;
+        mHeight = h;
+        super.onSizeChanged(w, h, oldw, oldh);
+    }
+
+    /**
+     * Called by the view when a draw is needed
+     * @param canvas Drawing canvas for this view
+     */
+    @Override
+    protected void onDraw(Canvas canvas) {
+        synchronized (this) {
+            if (mBitmap != null) {
+                canvas.drawBitmap(mBitmap, 0, 0, null);
+            }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/main/java/graphing/LinePoint.java	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,46 @@
+/*******************************************************************************
+ * Copyright (C) 2016 Maxim Integrated Products, Inc., All Rights Reserved.
+ * <p>
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ * <p>
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ * <p>
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+ * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ * <p>
+ * Except as contained in this notice, the name of Maxim Integrated
+ * Products, Inc. shall not be used except as stated in the Maxim Integrated
+ * Products, Inc. Branding Policy.
+ * <p>
+ * The mere transfer of this software does not imply any licenses
+ * of trade secrets, proprietary technology, copyrights, patents,
+ * trademarks, maskwork rights, or any other form of intellectual
+ * property whatsoever. Maxim Integrated Products, Inc. retains all
+ * ownership rights.
+ * ******************************************************************************
+ */
+package graphing;
+
+/**
+ * Container to hold the X,Y value to plot... also the raw pixel
+ * data when the point is actually rendered to the screen
+ */
+public class LinePoint {
+    /// define sensor x and y data
+    public float x;
+    public float y;
+    /// define raw X and Y of rendered point on the screen
+    public float rawX;
+    public float rawY;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/main/java/graphing/LinePointCollection.java	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,142 @@
+/*******************************************************************************
+ * Copyright (C) 2016 Maxim Integrated Products, Inc., All Rights Reserved.
+ * <p>
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ * <p>
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ * <p>
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+ * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ * <p>
+ * Except as contained in this notice, the name of Maxim Integrated
+ * Products, Inc. shall not be used except as stated in the Maxim Integrated
+ * Products, Inc. Branding Policy.
+ * <p>
+ * The mere transfer of this software does not imply any licenses
+ * of trade secrets, proprietary technology, copyrights, patents,
+ * trademarks, maskwork rights, or any other form of intellectual
+ * property whatsoever. Maxim Integrated Products, Inc. retains all
+ * ownership rights.
+ * ******************************************************************************
+ */
+package graphing;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Contains a list of points, the list will only hold a max number of
+ * points before the old value is deleted and new values are shifted in
+ */
+public class LinePointCollection {
+    /// list of points in this collection
+    List<LinePoint> points;
+    /// the list of points has a max count
+    int maxCount;
+    /// color used to render the points and connecting lines
+    int color;
+    /// the updated calculated max of all Y values in the list
+    float runningMaxY;
+    /// the updated calculated min of all Y values in the list
+    float runningMinY;
+
+    float pointDroppedOff;
+
+    /**
+     * Constructor used to specify the color of the line and tbe max number of points in this collection
+     * @param _color Color to use when rendering this collection
+     * @param _maxCount Max number of points held before deleting old points and "shifting" in new
+     */
+    public LinePointCollection(int _color, int _maxCount) {
+        color = _color;
+        maxCount = _maxCount;
+        points = new ArrayList<>();
+        pointDroppedOff = 0;
+    }
+
+    /**
+     * Accessor to get the list of points
+     * @return Return the list of points in this collection
+     */
+    public List<LinePoint> getPoints() {
+        return points;
+    }
+
+    public float getDroppedPointY() {
+        return pointDroppedOff;
+    }
+
+    /**
+     * Accessor to get the color of this collection
+     * @return Color that is used in this collection
+     */
+    public int getColor() {
+        return color;
+    }
+
+    /**
+     * Calculate the max and min Y extremes for the current cached points
+     */
+    private void calculateExtremes() {
+        runningMaxY = Float.MIN_VALUE;
+        runningMinY = Float.MAX_VALUE;
+        for (LinePoint point : points) {
+            if (point.y > runningMaxY) runningMaxY = point.y;
+            if (point.y < runningMinY) runningMinY = point.y;
+        }
+    }
+
+    /**
+     * Accessor to get the min Y value
+     * @return Smallest Y value in the list of points
+     */
+    public float getRunningMinY() {
+        return runningMinY;
+    }
+
+    /**
+     * Accessor to get the max Y value
+     * @return Largest Y Value in the list of points
+     */
+    public float getRunningMaxY() {
+        return runningMaxY;
+    }
+
+    /**
+     * Get the max number of points that will be contained in this collection
+     * @return Return the max count
+     */
+    public float getMaxCount() {
+        return maxCount;
+    }
+
+    /**
+     * Add a Y point value in this collection...
+     * note currently we only care about the Y value,
+     * the x running values are programically calculated
+     * @param y The Y value to use for this point
+     */
+    public void addpoint(float y) {
+        LinePoint point = new LinePoint();
+        point.x = 0;
+        point.y = y;
+        points.add(point);
+        if (points.size() > maxCount) {
+            // get the point removed for plotting first point
+            pointDroppedOff = points.get(0).rawY;
+            points.remove(0);
+        }
+        calculateExtremes();
+    }
+}
Binary file src/main/res/drawable-hdpi/accelerometer.png has changed
Binary file src/main/res/drawable-hdpi/accelerometer2.png has changed
Binary file src/main/res/drawable-hdpi/heart.png has changed
Binary file src/main/res/drawable-hdpi/ic_action_share.png has changed
Binary file src/main/res/drawable-hdpi/ic_bluetooth.png has changed
Binary file src/main/res/drawable-hdpi/ic_bluetooth_on.png has changed
Binary file src/main/res/drawable-hdpi/ic_device_ibeacon.png has changed
Binary file src/main/res/drawable-hdpi/ic_launcher.png has changed
Binary file src/main/res/drawable-hdpi/ic_settings_black_24dp.png has changed
Binary file src/main/res/drawable-hdpi/popup_blue.9.png has changed
Binary file src/main/res/drawable-hdpi/popup_green.9.png has changed
Binary file src/main/res/drawable-hdpi/popup_red.9.png has changed
Binary file src/main/res/drawable-hdpi/pressure.png has changed
Binary file src/main/res/drawable-hdpi/sliderscreen_max30001.png has changed
Binary file src/main/res/drawable-hdpi/sliderscreen_max30101.png has changed
Binary file src/main/res/drawable-hdpi/sliderscreen_max32620.png has changed
Binary file src/main/res/drawable-hdpi/sliderscreen_sensors.png has changed
Binary file src/main/res/drawable-hdpi/temperature.png has changed
Binary file src/main/res/drawable-hdpi/tile.9.png has changed
Binary file src/main/res/drawable-mdpi/ic_launcher.png has changed
Binary file src/main/res/drawable-xhdpi/ic_launcher.png has changed
Binary file src/main/res/drawable-xxhdpi/ic_launcher.png has changed
Binary file src/main/res/drawable-xxxhdpi/ic_launcher.png has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/main/res/layout/actionbar_indeterminate_progress.xml	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,23 @@
+<!--
+  Copyright 2013 Google Inc.
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+  -->
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+             android:layout_height="wrap_content"
+             android:layout_width="56dp"
+             android:minWidth="56dp">
+    <ProgressBar android:layout_width="32dp"
+                 android:layout_height="32dp"
+                 android:layout_gravity="center"/>
+</FrameLayout>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/main/res/layout/activity_sensor.xml	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,528 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:tools="http://schemas.android.com/tools"
+    android:id="@+id/activity_sensor1"
+    android:orientation="vertical" android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:weightSum="1"
+    tools:context="com.example.android.bluetoothlegatt.SensorActivity"
+    android:background="#d7d7d7">
+
+    <GridLayout
+        android:id="@+id/deviceInformation"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_alignParentTop="true"
+        android:columnCount="2"
+        android:useDefaultMargins="true"
+        android:layout_marginLeft="10dp"
+        android:layout_marginRight="10dp"
+        android:layout_marginTop="5dp"
+        android:background="#f4f4f4">
+
+        <TextView
+            style="@style/GridLayoutTitleTextView"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:textSize="10sp"
+            android:text="@string/label_device_address"/>
+
+        <TextView
+            android:id="@+id/device_address"
+            android:textSize="10sp"
+            style="@style/GridLayoutDataTextView"/>
+
+        <TextView
+            android:textSize="10sp"
+            style="@style/GridLayoutTitleTextView"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:text="@string/label_state"/>
+
+        <TextView
+            android:textSize="10sp"
+            android:id="@+id/connection_state"
+            style="@style/GridLayoutDataTextView"/>
+    </GridLayout>
+
+
+    <!-- Temperature Top (WSN Temperature) -->
+    <RelativeLayout
+        android:layout_width="match_parent"
+        android:layout_height="65dp"
+        android:id="@+id/relativeLayout1"
+        android:layout_marginLeft="10dp"
+        android:layout_marginRight="10dp"
+        android:layout_marginTop="5dp"
+        android:background="#f4f4f4">
+
+        <ImageView
+            android:layout_width="40dp"
+            android:layout_height="40dp"
+            android:id="@+id/imageView"
+            android:layout_marginTop="7dp"
+            android:background="@drawable/temperature"
+            android:layout_gravity="left"
+            android:layout_marginLeft="5dp" />
+
+        <LinearLayout
+            android:orientation="vertical"
+            android:layout_width="100dp"
+            android:layout_height="wrap_content"
+            android:layout_marginLeft="5dp"
+            android:layout_alignParentStart="false"
+            android:layout_toEndOf="@id/imageView"
+            android:layout_alignParentEnd="false"
+            android:id="@+id/layout1">
+            <TextView
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:textAppearance="?android:attr/textAppearanceLarge"
+                android:text="MAX30205 1"
+                android:textSize="15sp"
+                android:id="@+id/textView3"
+                android:textColor="#0a5dff" />
+            <TextView
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:textAppearance="?android:attr/textAppearanceLarge"
+                android:text="---- F"
+                android:textSize="22dp"
+                android:id="@+id/textTempTop"
+                android:textColor="#5e5e5e" />
+
+        </LinearLayout>
+
+        <view
+            android:layout_width="fill_parent"
+            android:layout_height="match_parent"
+            android:layout_gravity="right"
+            android:layout_marginRight="5dp"
+            class="graphing.LineGraphing"
+            android:id="@+id/lineGraphingTemperature1"
+            android:layout_toEndOf="@id/layout1" />
+
+        <TextView
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:textAppearance="?android:attr/textAppearanceLarge"
+            android:text="-- --"
+            android:textSize="10dp"
+            android:id="@+id/textTempTopRaw"
+            android:textColor="#5e5e5e"
+            android:layout_alignParentBottom="true"
+            android:layout_alignStart="@+id/layout1" />
+    </RelativeLayout>
+
+    <!-- Temperature Bottom (WSN Humidity) -->
+    <RelativeLayout
+        android:layout_width="match_parent"
+        android:layout_height="65dp"
+        android:id="@+id/relativeLayout2"
+        android:layout_marginLeft="10dp"
+        android:layout_marginRight="10dp"
+        android:layout_marginTop="5dp"
+        android:background="#f4f4f4">
+
+        <ImageView
+            android:layout_width="40dp"
+            android:layout_height="40dp"
+            android:id="@+id/imageView2"
+            android:layout_marginTop="7dp"
+            android:background="@drawable/temperature"
+            android:layout_gravity="left"
+            android:layout_marginLeft="5dp" />
+
+        <LinearLayout
+            android:orientation="vertical"
+            android:layout_width="100dp"
+            android:layout_height="wrap_content"
+            android:layout_marginLeft="5dp"
+            android:layout_alignParentStart="false"
+            android:layout_toEndOf="@id/imageView2"
+            android:layout_alignParentEnd="false"
+            android:id="@+id/layout2">
+            <TextView
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:textAppearance="?android:attr/textAppearanceLarge"
+                android:text="MAX30205 2"
+                android:textSize="15sp"
+                android:id="@+id/textView2"
+                android:textColor="#0a5dff" />
+            <TextView
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:textAppearance="?android:attr/textAppearanceLarge"
+                android:text="---- F"
+                android:textSize="22dp"
+                android:id="@+id/textTempBottom"
+                android:textColor="#5e5e5e" />
+        </LinearLayout>
+
+        <view
+            android:layout_width="fill_parent"
+            android:layout_height="match_parent"
+            android:layout_gravity="right"
+            android:layout_marginRight="5dp"
+            class="graphing.LineGraphing"
+            android:id="@+id/lineGraphingTemperature2"
+            android:layout_toEndOf="@id/layout2" />
+
+        <TextView
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:textAppearance="?android:attr/textAppearanceLarge"
+            android:text="-- --"
+            android:textSize="10dp"
+            android:id="@+id/textTempBottomRaw"
+            android:textColor="#5e5e5e"
+            android:layout_alignParentBottom="true"
+            android:layout_alignStart="@+id/layout2" />
+    </RelativeLayout>
+
+
+
+
+
+
+
+
+    <!-- LIS2DH (WSN Light) -->
+    <RelativeLayout
+        android:layout_width="match_parent"
+        android:layout_height="65dp"
+        android:layout_marginLeft="10dp"
+        android:layout_marginRight="10dp"
+        android:layout_marginTop="5dp"
+        android:id="@+id/relativeLayout3"
+        android:background="#f4f4f4">
+
+        <ImageView
+            android:layout_width="30dp"
+            android:layout_height="40dp"
+            android:id="@+id/imageView3"
+            android:background="@drawable/accelerometer2"
+            android:layout_gravity="left"
+            android:layout_marginLeft="10dp"
+            android:layout_marginTop="5dp"
+            android:layout_marginBottom="5dp" />
+
+        <LinearLayout
+            android:orientation="vertical"
+            android:layout_width="100dp"
+            android:layout_height="wrap_content"
+            android:layout_marginLeft="10dp"
+            android:layout_alignParentStart="false"
+            android:layout_toEndOf="@id/imageView3"
+            android:layout_alignParentEnd="false"
+            android:id="@+id/layout3">
+            <TextView
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:textAppearance="?android:attr/textAppearanceLarge"
+                android:text="LIS2DH"
+                android:textSize="17sp"
+                android:id="@+id/textView4"
+                android:textColor="#0a5dff" />
+            <TextView
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:textAppearance="?android:attr/textAppearanceLarge"
+                android:text="X: ---"
+                android:textSize="6dp"
+                android:id="@+id/textLIS2DH_X"
+                android:textColor="#5e5e5e" />
+            <TextView
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:textAppearance="?android:attr/textAppearanceLarge"
+                android:text="Y: ---"
+                android:textSize="6dp"
+                android:id="@+id/textLIS2DH_Y"
+                android:textColor="#5e5e5e" />
+            <TextView
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:textAppearance="?android:attr/textAppearanceLarge"
+                android:text="Z: ---"
+                android:textSize="6dp"
+                android:id="@+id/textLIS2DH_Z"
+                android:textColor="#5e5e5e" />
+        </LinearLayout>
+
+
+
+
+        <view
+            android:layout_width="fill_parent"
+            android:layout_height="match_parent"
+            android:layout_gravity="right"
+            android:layout_marginRight="5dp"
+            class="graphing.LineGraphing"
+            android:id="@+id/lineGraphingAccelerometer"
+            android:visibility="visible"
+            android:layout_toEndOf="@id/layout3"
+            />
+
+
+        <TextView
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:textAppearance="?android:attr/textAppearanceLarge"
+            android:text="  Mission Stopped"
+            android:id="@+id/textView7"
+            android:layout_centerVertical="true"
+            android:layout_alignEnd="@+id/lineGraphingAccelerometer"
+            android:textAlignment="center"
+            android:textColor="#bfbfbf"
+            android:layout_toEndOf="@+id/layout3"
+            android:visibility="invisible" />
+
+        <TextView
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:textAppearance="?android:attr/textAppearanceLarge"
+            android:text="-- --"
+            android:textSize="10dp"
+            android:id="@+id/textLIS2DHRaw"
+            android:textColor="#5e5e5e"
+            android:layout_alignParentBottom="true"
+            android:layout_alignStart="@+id/layout3" />
+
+
+    </RelativeLayout>
+
+
+    <!-- BMP280 (WSN Pressure) -->
+    <RelativeLayout
+        android:layout_width="match_parent"
+        android:layout_height="65dp"
+        android:layout_marginLeft="10dp"
+        android:layout_marginRight="10dp"
+        android:layout_marginTop="5dp"
+        android:id="@+id/relativeLayout4"
+        android:background="#f4f4f4">
+
+        <ImageView
+            android:layout_width="35dp"
+            android:layout_height="40dp"
+            android:layout_weight="1"
+            android:id="@+id/imageView4"
+            android:layout_marginTop="5dp"
+            android:background="@drawable/pressure"
+            android:layout_gravity="left"
+            android:layout_marginLeft="7dp"
+            android:layout_marginRight="3dp" />
+
+        <LinearLayout
+            android:orientation="vertical"
+            android:layout_width="100dp"
+            android:layout_height="wrap_content"
+            android:layout_weight="1"
+            android:layout_marginTop="0dp"
+            android:layout_alignParentStart="false"
+            android:layout_toEndOf="@id/imageView4"
+            android:layout_alignParentEnd="false"
+            android:layout_marginLeft="5dp"
+            android:id="@+id/layout4">
+            <TextView
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:textAppearance="?android:attr/textAppearanceLarge"
+                android:text="BMP280"
+                android:textSize="17sp"
+                android:id="@+id/textView"
+                android:textColor="#0a5dff" />
+            <TextView
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:textAppearance="?android:attr/textAppearanceLarge"
+                android:text="---- Pa"
+                android:textSize="15dp"
+                android:id="@+id/textPressure"
+                android:textColor="#5e5e5e" />
+            <TextView
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:textAppearance="?android:attr/textAppearanceLarge"
+                android:text="---- F"
+                android:textSize="22dp"
+                android:id="@+id/textTemperature"
+                android:textColor="#5e5e5e"
+                android:visibility="gone" />
+        </LinearLayout>
+
+        <view
+            android:layout_width="fill_parent"
+            android:layout_height="match_parent"
+            android:layout_gravity="right"
+            android:layout_marginRight="5dp"
+            class="graphing.LineGraphing"
+            android:id="@+id/lineGraphingPressure"
+            android:layout_toEndOf="@id/layout4" />
+
+        <TextView
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:textAppearance="?android:attr/textAppearanceLarge"
+            android:text="-- --"
+            android:textSize="10dp"
+            android:id="@+id/textPressureRaw"
+            android:textColor="#5e5e5e"
+            android:layout_alignParentBottom="true"
+            android:layout_alignStart="@+id/layout4" />
+    </RelativeLayout>
+
+
+
+    <!-- ECG Heartrate -->
+    <RelativeLayout
+        android:layout_width="match_parent"
+        android:layout_height="65dp"
+        android:layout_marginLeft="10dp"
+        android:layout_marginRight="10dp"
+        android:layout_marginTop="5dp"
+        android:id="@+id/relativeLayout5"
+        android:background="#f4f4f4">
+
+        <ImageView
+            android:layout_width="35dp"
+            android:layout_height="40dp"
+            android:layout_weight="1"
+            android:id="@+id/imageView5"
+            android:layout_marginTop="5dp"
+            android:background="@drawable/heart"
+            android:layout_gravity="left"
+            android:layout_marginLeft="7dp"
+            android:layout_marginRight="3dp" />
+
+        <LinearLayout
+            android:orientation="vertical"
+            android:layout_width="100dp"
+            android:layout_height="wrap_content"
+            android:layout_weight="1"
+            android:layout_marginTop="0dp"
+            android:layout_alignParentStart="false"
+            android:layout_toEndOf="@id/imageView5"
+            android:layout_alignParentEnd="false"
+            android:layout_marginLeft="5dp"
+            android:id="@+id/layout5">
+            <TextView
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:textAppearance="?android:attr/textAppearanceLarge"
+                android:text="ECG HeartRate"
+                android:textSize="12sp"
+                android:id="@+id/textView5"
+                android:textColor="#0a5dff" />
+            <TextView
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:textAppearance="?android:attr/textAppearanceLarge"
+                android:text="-- BPM"
+                android:textSize="16dp"
+                android:id="@+id/textHeartRate"
+                android:textColor="#5e5e5e" />
+        </LinearLayout>
+
+        <view
+            android:layout_width="fill_parent"
+            android:layout_height="match_parent"
+            android:layout_gravity="right"
+            android:layout_marginRight="5dp"
+            class="graphing.LineGraphing"
+            android:id="@+id/lineGraphingHeartrate"
+            android:layout_toEndOf="@id/layout5"
+            android:visibility="visible" />
+
+        <TextView
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:textAppearance="?android:attr/textAppearanceLarge"
+            android:text="-- --"
+            android:textSize="10dp"
+            android:id="@+id/textHeartRateRaw"
+            android:textColor="#5e5e5e"
+            android:layout_alignParentBottom="true"
+            android:layout_alignStart="@+id/layout5" />
+        <TextView
+            android:id="@+id/clickStartBtn"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:text="Start"
+            android:textSize="12sp"
+            android:onClick="onClick"
+            android:clickable="true"
+            android:layout_alignBottom="@+id/textHeartRateRaw"
+            android:layout_alignEnd="@+id/layout5"
+            android:background="#505050"
+            android:textColor="#ffffff"
+            android:paddingLeft="5dp"
+            android:paddingRight="5dp"
+            android:layout_marginBottom="1dp"
+            android:visibility="gone" />
+
+        <TextView
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:textAppearance="?android:attr/textAppearanceLarge"
+            android:text="  Mission Stopped"
+            android:id="@+id/textView8"
+            android:textAlignment="center"
+            android:textColor="#bfbfbf"
+            android:layout_alignBottom="@+id/imageView5"
+            android:layout_toEndOf="@+id/layout5"
+            android:visibility="invisible" />
+    </RelativeLayout>
+
+
+
+
+    <RelativeLayout
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_marginLeft="10dp"
+        android:layout_marginRight="10dp"
+        android:layout_marginTop="5dp"
+        android:id="@+id/relativeLayout6"
+        android:background="#f4f4f4"
+        android:visibility="gone">
+
+        <Button
+            style="?android:attr/buttonStyleSmall"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:text="test"
+            android:id="@+id/btnTest"
+            android:layout_alignParentTop="true"
+            android:layout_alignParentStart="true" />
+
+        <Button
+            style="?android:attr/buttonStyleSmall"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:text="Update"
+            android:id="@+id/btnUpdate"
+            android:layout_alignParentTop="true"
+            android:layout_toEndOf="@+id/btnTest" />
+
+        <Button
+            style="?android:attr/buttonStyleSmall"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:text="Subscribe"
+            android:id="@+id/btnSubscribe"
+            android:layout_alignParentTop="true"
+            android:layout_toEndOf="@+id/btnUpdate" />
+    </RelativeLayout>
+
+    <Button
+    style="?android:attr/buttonStyleSmall"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:text="Start Mission"
+    android:id="@+id/clickStartBtn2"
+    android:backgroundTint="#00b2a9" />
+
+</LinearLayout>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/main/res/layout/gatt_services_characteristics.xml	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,71 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2013 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+        android:orientation="vertical"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_margin="10dp">
+    <LinearLayout android:orientation="horizontal"
+                  android:layout_width="match_parent"
+                  android:layout_height="wrap_content"
+                  android:layout_margin="10dp">
+        <TextView android:layout_width="wrap_content"
+                  android:layout_height="wrap_content"
+                  android:text="@string/label_device_address"
+                  android:textSize="18sp"/>
+        <Space android:layout_width="5dp"
+               android:layout_height="wrap_content"/>
+        <TextView android:id="@+id/device_address"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:textSize="18sp"/>
+    </LinearLayout>
+    <LinearLayout android:orientation="horizontal"
+                  android:layout_width="match_parent"
+                  android:layout_height="wrap_content"
+                  android:layout_margin="10dp">
+        <TextView android:layout_width="wrap_content"
+                  android:layout_height="wrap_content"
+                  android:text="@string/label_state"
+                  android:textSize="18sp"/>
+        <Space android:layout_width="5dp"
+               android:layout_height="wrap_content"/>
+        <TextView android:id="@+id/connection_state"
+                  android:layout_width="match_parent"
+                  android:layout_height="wrap_content"
+                  android:text="@string/disconnected"
+                  android:textSize="18sp"/>
+    </LinearLayout>
+    <LinearLayout android:orientation="horizontal"
+                  android:layout_width="match_parent"
+                  android:layout_height="wrap_content"
+                  android:layout_margin="10dp">
+        <TextView android:layout_width="wrap_content"
+                  android:layout_height="wrap_content"
+                  android:text="@string/label_data"
+                  android:textSize="18sp"/>
+        <Space android:layout_width="5dp"
+               android:layout_height="wrap_content"/>
+        <TextView android:id="@+id/data_value"
+                  android:layout_width="match_parent"
+                  android:layout_height="wrap_content"
+                  android:text="@string/no_data"
+                  android:textSize="18sp"/>
+    </LinearLayout>
+    <ExpandableListView android:id="@+id/gatt_services_list"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"/>
+</LinearLayout>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/main/res/layout/listitem_device.xml	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2013 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+              android:orientation="vertical"
+              android:layout_width="match_parent"
+              android:layout_height="wrap_content">
+    <TextView android:id="@+id/device_name"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:textSize="24dp"/>
+    <TextView android:id="@+id/device_address"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:textSize="12dp"/>
+</LinearLayout>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/main/res/menu/gatt_services.xml	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2013 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<menu xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:id="@+id/menu_refresh"
+          android:checkable="false"
+          android:orderInCategory="1"
+          android:showAsAction="ifRoom"/>
+    <item android:id="@+id/menu_connect"
+          android:title="@string/menu_connect"
+          android:orderInCategory="100"
+          android:showAsAction="ifRoom|withText"/>
+    <item android:id="@+id/menu_disconnect"
+          android:title="@string/menu_disconnect"
+          android:orderInCategory="101"
+          android:showAsAction="ifRoom|withText"/>
+</menu>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/main/res/menu/main.xml	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2013 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<menu xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:id="@+id/menu_refresh"
+          android:checkable="false"
+          android:orderInCategory="1"
+          android:showAsAction="ifRoom"/>
+    <item android:id="@+id/menu_scan"
+          android:title="@string/menu_scan"
+          android:orderInCategory="100"
+          android:showAsAction="ifRoom|withText"/>
+    <item android:id="@+id/menu_stop"
+          android:title="@string/menu_stop"
+          android:orderInCategory="101"
+          android:showAsAction="ifRoom|withText"/>
+</menu>
Binary file src/main/res/mipmap-hdpi/ic_launcher.png has changed
Binary file src/main/res/mipmap-mdpi/ic_launcher.png has changed
Binary file src/main/res/mipmap-xhdpi/ic_launcher.png has changed
Binary file src/main/res/mipmap-xxhdpi/ic_launcher.png has changed
Binary file src/main/res/mipmap-xxxhdpi/ic_launcher.png has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/main/res/values-v21/styles.xml	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,9 @@
+<resources>
+
+    <style name="AppTheme.NoActionBar">
+        <item name="windowActionBar">false</item>
+        <item name="windowNoTitle">true</item>
+        <item name="android:windowDrawsSystemBarBackgrounds">true</item>
+        <item name="android:statusBarColor">@android:color/transparent</item>
+    </style>
+</resources>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/main/res/values-w820dp/dimens.xml	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,6 @@
+<resources>
+    <!-- Example customization of dimensions originally defined in res/values/dimens.xml
+         (such as screen margins) for screens with more than 820dp of available width. This
+         would include 7" and 10" devices in landscape (~960dp and ~1280dp respectively). -->
+    <dimen name="activity_horizontal_margin">64dp</dimen>
+</resources>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/main/res/values/colors.xml	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+    <color name="colorPrimary">#3F51B5</color>
+    <color name="colorPrimaryDark">#303F9F</color>
+    <color name="colorAccent">#FF4081</color>
+    <color name="light_gray">#66e0e0e0</color>
+</resources>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/main/res/values/dimens.xml	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,6 @@
+<resources>
+    <!-- Default screen margins, per the Android Design guidelines. -->
+    <dimen name="activity_horizontal_margin">16dp</dimen>
+    <dimen name="activity_vertical_margin">16dp</dimen>
+    <dimen name="fab_margin">16dp</dimen>
+</resources>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/main/res/values/strings.xml	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,85 @@
+<resources>
+    <string name="app_name">MAXREFDES100</string>
+    <string name="title_activity_main2">Main2Activity</string>
+
+
+    <string name="action_settings">Settings</string>
+    <string name="connected">Connected</string>
+    <string name="disconnected">Disconnected</string>
+    <string name="invalid_device_data">Invalid Device Data!</string>
+    <string name="no_data">No data</string>
+    <string name="not_supported">Not supported</string>
+    <string name="off">Off</string>
+    <string name="on">On</string>
+    <string name="supported">Supported</string>
+    <string name="unknown">unknown</string>
+    <string name="unknown_characteristic">Unknown characteristic</string>
+    <string name="unknown_device">Unknown device</string>
+    <string name="unknown_service">Unknown service</string>
+    <string name="no_known_services">No known services</string>
+
+    <!-- Formatters -->
+    <string name="formatter_meters">%sm</string>
+    <string name="formatter_db">%sdb</string>
+    <string name="formatter_item_count">Items: %s</string>
+
+    <!-- Menu items -->
+    <string name="menu_about">About</string>
+    <string name="menu_connect">Connect</string>
+    <string name="menu_disconnect">Disconnect</string>
+    <string name="menu_scan">Scan</string>
+    <string name="menu_stop">Stop</string>
+    <string name="menu_share">Share</string>
+
+    <!-- Export Email Strings -->
+    <string name="exporter_email_device_list_subject">Bluetooth LE Scan Results (%s)</string>
+    <string name="exporter_email_device_services_subject" formatted="false">Bluetooth LE Device GATT Results (%s, %s)</string>
+    <string name="exporter_email_device_list_body">Please find attached the scan results.</string>
+    <string name="exporter_email_device_list_picker_text">Please select your email client:</string>
+
+    <!-- Labels -->
+    <string name="about_dialog_text">This is a sample application using the Bluetooth LE Library.\n\nGithub: https://github.com/alt236/Bluetooth-LE-Library---Android\n\nCopyright: Alexandros Schillings</string>
+    <string name="header_device_info">Device Info</string>
+    <string name="header_ibeacon_data">iBeacon Data</string>
+    <string name="header_raw_ad_records">Raw Ad Records</string>
+    <string name="header_rssi_info">RSSI Info</string>
+    <string name="header_scan_record">Scan Record</string>
+    <string name="label_advertisement">Advertisement:</string>
+    <string name="label_as_array">As Array:</string>
+    <string name="label_as_string">As String:</string>
+    <string name="label_bluetooth_le_status">Bluetooth LE:</string>
+    <string name="label_bluetooth_status">Bluetooth:</string>
+    <string name="label_bonding_state">Bonding State:</string>
+    <string name="label_company_id">Company ID:</string>
+    <string name="label_data">Data:</string>
+    <string name="label_desc">Desc:</string>
+    <string name="label_device_address">Device address:</string>
+    <string name="label_device_class">Device Class:</string>
+    <string name="label_device_major_class">Major Class:</string>
+    <string name="label_device_services">Services:</string>
+    <string name="label_device_name">Device Name:</string>
+    <string name="label_distance">Distance:</string>
+    <string name="label_first_rssi">First RSSI:</string>
+    <string name="label_first_timestamp">First Timestamp:</string>
+    <string name="label_last_rssi">Last RSSI:</string>
+    <string name="label_last_timestamp">Last Timestamp:</string>
+    <string name="label_mac">MAC:</string>
+    <string name="label_major">Major:</string>
+    <string name="label_minor">Minor:</string>
+    <string name="label_rssi">RSSI:</string>
+    <string name="label_running_average_rssi">Running Average RSSI:</string>
+    <string name="label_state">State:</string>
+    <string name="label_tx_power">TX Power:</string>
+    <string name="label_uuid">UUID:</string>
+    <string name="label_updated">Updated:</string>
+    <string name="label_decriptor">Descriptor:</string>
+    <string name="title_activity_sensor">SensorActivity</string>
+
+    <string name="hello_world">Hello world!</string>
+    <string name="title_activity_graph_test">GraphTest</string>
+    <string name="title_activity_slider">hSensor</string>
+    <string name="title_activity_define_mission">DefineMissionActivity</string>
+    <string name="title_activity_test">test</string>
+
+
+</resources>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/main/res/values/styles.xml	Tue Apr 06 06:41:40 2021 +0000
@@ -0,0 +1,39 @@
+<resources>
+
+    <!-- Base application theme. -->
+    <style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
+        <!-- Customize your theme here. -->
+        <item name="colorPrimary">@color/colorPrimary</item>
+        <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
+        <item name="colorAccent">@color/colorAccent</item>
+    </style>
+
+    <style name="AppTheme.NoActionBar">
+        <item name="windowActionBar">false</item>
+        <item name="windowNoTitle">true</item>
+    </style>
+
+    <style name="AppTheme.AppBarOverlay" parent="ThemeOverlay.AppCompat.Dark.ActionBar" />
+
+    <style name="AppTheme.PopupOverlay" parent="ThemeOverlay.AppCompat.Light" />
+
+    <style name="GridLayoutDataTextView">
+        <item name="android:textSize">12sp</item>
+        <item name="android:layout_weight">1</item>
+        <item name="android:ellipsize">none</item>
+        <item name="android:singleLine">false</item>
+        <item name="android:scrollHorizontally">false</item>
+        <item name="android:maxLines">100</item>
+        <item name="android:inputType">textMultiLine</item>
+        <item name="android:layout_width">wrap_content</item>
+        <item name="android:layout_height">match_parent</item>
+    </style>
+    <style name="GridLayoutTitleTextView">
+        <item name="android:textSize">12sp</item>
+    </style>
+
+    <style name="GridLayoutDataTextViewMonospace" parent="@style/GridLayoutDataTextView">
+        <item name="android:typeface">monospace</item>
+    </style>
+
+</resources>