public AxopatchInterop.AxopatchData ReadTelegraphData(IDictionary<string, IInputData> data)
        {
            if (!data.ContainsKey(AxopatchDevice.GAIN_TELEGRAPH_STREAM_NAME))
                throw new ArgumentException("Data does not contain gain telegraph");

            if (!data.ContainsKey(AxopatchDevice.MODE_TELEGRAPH_STREAM_NAME))
                throw new ArgumentException("Data does not contain mode telegraph");

            var telegraph = new AxopatchInterop.AxopatchData();

            var gain = ReadVoltage(data[AxopatchDevice.GAIN_TELEGRAPH_STREAM_NAME]);
            try
            {
                telegraph.Gain = _voltageToGain[Math.Round(gain * 2) / 2];
            }
            catch (KeyNotFoundException)
            {
                throw new ArgumentException("Unknown gain telegraph");
            }

            var mode = ReadVoltage(data[AxopatchDevice.MODE_TELEGRAPH_STREAM_NAME]);
            try
            {
                telegraph.OperatingMode = _voltageToMode[Math.Round(mode * 2) / 2];
            }
            catch (KeyNotFoundException)
            {
                throw new ArgumentException("Unknown mode telegraph");
            }

            switch (telegraph.OperatingMode)
            {
                case AxopatchInterop.OperatingMode.IClampFast:
                case AxopatchInterop.OperatingMode.IClampNormal:
                    telegraph.ExternalCommandSensitivity = 2e-9/Beta;
                    telegraph.ExternalCommandSensitivityUnits = AxopatchInterop.ExternalCommandSensitivityUnits.A_V;
                    break;
                case AxopatchInterop.OperatingMode.VClamp:
                    telegraph.ExternalCommandSensitivity = 0.02;
                    telegraph.ExternalCommandSensitivityUnits = AxopatchInterop.ExternalCommandSensitivityUnits.V_V;
                    break;
                case AxopatchInterop.OperatingMode.I0:
                case AxopatchInterop.OperatingMode.Track:
                    telegraph.ExternalCommandSensitivityUnits = AxopatchInterop.ExternalCommandSensitivityUnits.OFF;
                    break;
            }

            return telegraph;
        }
        public void ShouldConvertInputUnitsInIClamp(
            [Values(
                AxopatchInterop.OperatingMode.I0, 
                AxopatchInterop.OperatingMode.IClampFast,
                AxopatchInterop.OperatingMode.IClampNormal)] AxopatchInterop.OperatingMode operatingMode,
            [Values(1, 2, 10)] double gain)
        {
            var data = new AxopatchInterop.AxopatchData()
                {
                    OperatingMode = operatingMode,
                    Gain = gain
                };

            var cmd = new Measurement(20, -3, "V");

            var expected = new Measurement(1000 * cmd.QuantityInBaseUnits/(decimal) gain, -3, "V");

            var actual = AxopatchDevice.ConvertInput(cmd, data);

            Assert.That(actual, Is.EqualTo(expected));
        }
        public void ShouldUseBackgroundForMode()
        {
            const string VClampUnits = "V";
            const string IClampUnits = "A";

            Measurement VClampBackground = new Measurement(2, -3, VClampUnits);
            Measurement IClampBackground = new Measurement(-10, -3, IClampUnits);

            var c = new Controller();
            var p = new FakeAxopatch();

            var bg = new Dictionary<AxopatchInterop.OperatingMode, IMeasurement>()
                         {
                             {AxopatchInterop.OperatingMode.VClamp, VClampBackground},
                             {AxopatchInterop.OperatingMode.IClampNormal, IClampBackground},
                         };

            var patch = new AxopatchDevice(p, c, bg);
            patch.BindStream(new DAQOutputStream("stream"));

            var data = new AxopatchInterop.AxopatchData()
            {
                OperatingMode = AxopatchInterop.OperatingMode.VClamp,
                ExternalCommandSensitivity = 2.5,
                ExternalCommandSensitivityUnits = AxopatchInterop.ExternalCommandSensitivityUnits.V_V
            };

            p.Data = data;

            Assert.That(patch.OutputBackground, Is.EqualTo(AxopatchDevice.ConvertOutput(VClampBackground, patch.CurrentDeviceParameters)));

            data = new AxopatchInterop.AxopatchData()
            {
                OperatingMode = AxopatchInterop.OperatingMode.IClampNormal,
                ExternalCommandSensitivity = 1.5,
                ExternalCommandSensitivityUnits = AxopatchInterop.ExternalCommandSensitivityUnits.A_V
            };

            p.Data = data;

            Assert.That(patch.OutputBackground, Is.EqualTo(AxopatchDevice.ConvertOutput(IClampBackground, patch.CurrentDeviceParameters)));
        }
        public void ShouldConvertOutputUnitsInVClamp(
            [Values(
                AxopatchInterop.OperatingMode.VClamp,
                AxopatchInterop.OperatingMode.Track)] AxopatchInterop.OperatingMode operatingMode)
        {
            var data = new AxopatchInterop.AxopatchData()
            {
                OperatingMode = operatingMode,
                ExternalCommandSensitivity = 2.5,
                ExternalCommandSensitivityUnits = AxopatchInterop.ExternalCommandSensitivityUnits.V_V
            };

            var cmd = new Measurement(20, -3, "V");

            var expected = operatingMode == AxopatchInterop.OperatingMode.Track ?
                new Measurement(0, "V") :
                new Measurement(cmd.Quantity / (decimal)data.ExternalCommandSensitivity,
                                           cmd.Exponent, "V");

            var actual = AxopatchDevice.ConvertOutput(cmd, data);

            Assert.That(actual, Is.EqualTo(expected));
        }
        public void ShouldConvertOutputUnitsInIClamp(
            [Values(
                AxopatchInterop.OperatingMode.I0, 
                AxopatchInterop.OperatingMode.IClampFast, 
                AxopatchInterop.OperatingMode.IClampNormal)] AxopatchInterop.OperatingMode operatingMode)
        {
            var c = new Controller();
            var p = new Axopatch200B();

            var patchDevice = new AxopatchDevice(p, c, null);

            var data = new AxopatchInterop.AxopatchData()
                {
                    OperatingMode = operatingMode,
                    ExternalCommandSensitivity = 2.5,
                    ExternalCommandSensitivityUnits = AxopatchInterop.ExternalCommandSensitivityUnits.A_V
                };

            var cmd = new Measurement(20, -12, "A");

            var expected = operatingMode == AxopatchInterop.OperatingMode.I0 ?
                new Measurement(0, "V") :
                new Measurement(cmd.Quantity / (decimal)data.ExternalCommandSensitivity,
                                           cmd.Exponent, "V");

            var actual = AxopatchDevice.ConvertOutput(cmd, data);

            Assert.That(actual, Is.EqualTo(expected));
        }
        public override void PushInputData(IDAQInputStream stream, IInputData inData)
        {
            if (inData.Data.Count == 0)
                return;

            _queues[stream].Add(inData);
            if (_queues.Values.Any(dataList => dataList.Count == 0))
                return;

            try
            {
                IDictionary<string, IInputData> data = new Dictionary<string, IInputData>();
                foreach (var dataList in _queues)
                {
                    string streamName = Streams.FirstOrDefault(x => x.Value == dataList.Key).Key;
                    data.Add(streamName, dataList.Value[0]);
                    dataList.Value.RemoveAt(0);
                }

                var deviceParameters = Axopatch.ReadTelegraphData(data);
                DeviceParameters = deviceParameters;

                IInputData scaledData = data[SCALED_OUTPUT_STREAM_NAME];
                IInputData convertedData = scaledData.DataWithConversion(m => ConvertInput(m, deviceParameters));

                var config = MergeDeviceParametersIntoConfiguration(Configuration, deviceParameters);

                this.Controller.PushInputData(this, convertedData.DataWithExternalDeviceConfiguration(this, config));
            }
            catch (Exception ex)
            {
                log.DebugFormat("Error pushing data to controller: {0} ({1})", ex.Message, ex);
                throw;
            }
        }