Пример #1
0
        private void UpdateSimulation(bool Rebuild)
        {
            int id = Interlocked.Increment(ref update);

            new Task(() =>
            {
                ComputerAlgebra.Expression h = (ComputerAlgebra.Expression) 1 / (stream.SampleRate * Oversample);
                Circuit.TransientSolution s  = Circuit.TransientSolution.Solve(circuit.Analyze(), h, Rebuild ? (ILog)Log : new NullLog());
                lock (sync)
                {
                    if (id > clock)
                    {
                        if (Rebuild)
                        {
                            simulation = new Circuit.Simulation(s)
                            {
                                Log        = Log,
                                Input      = inputs.Keys,
                                Output     = probes.Select(i => i.V).Concat(OutputChannels.Select(i => i.Signal)),
                                Oversample = Oversample,
                                Iterations = Iterations,
                            };
                        }
                        else
                        {
                            simulation.Solution = s;
                            clock = id;
                        }
                    }
                }
            }).Start(scheduler);
        }
Пример #2
0
        private void RebuildSolution()
        {
            lock (sync)
            {
                simulation = null;
                ProgressDialog.RunAsync(this, "Building circuit solution...", () =>
                {
                    try
                    {
                        ComputerAlgebra.Expression h       = (ComputerAlgebra.Expression) 1 / (stream.SampleRate * Oversample);
                        Circuit.TransientSolution solution = Circuit.TransientSolution.Solve(circuit.Analyze(), h, Log);

                        simulation = new Circuit.Simulation(solution)
                        {
                            Log        = Log,
                            Input      = inputs.Keys,
                            Output     = probes.Select(i => i.V).Concat(OutputChannels.Select(i => i.Signal)),
                            Oversample = Oversample,
                            Iterations = Iterations,
                        };
                    }
                    catch (Exception Ex)
                    {
                        Log.WriteException(Ex);
                    }
                });
            }
        }
Пример #3
0
        private void BindSignal_Click(object sender, RoutedEventArgs e)
        {
            OutputChannel ch = (OutputChannel)((FrameworkElement)sender).Tag;

            SchematicTool tool = Schematic.Tool;

            Schematic.Tool = new FindRelevantTool(Schematic)
            {
                Relevant = (x) => x is Circuit.Symbol && ((Circuit.Symbol)x).Component is Circuit.TwoTerminal,
                Clicked  = (x) =>
                {
                    if (x.Any())
                    {
                        ComputerAlgebra.Expression init = (Keyboard.Modifiers & ModifierKeys.Control) != 0 ? ch.Signal : 0;
                        ch.Signal = x.OfType <Circuit.Symbol>()
                                    .Select(i => i.Component)
                                    .OfType <Circuit.TwoTerminal>()
                                    .Aggregate(init, (sum, c) => sum + c.V);
                    }
                    Schematic.Tool = tool;
                }
            };
        }
Пример #4
0
        public LiveSimulation(Circuit.Schematic Simulate, Audio.Device Device, Audio.Channel[] Inputs, Audio.Channel[] Outputs)
        {
            try
            {
                InitializeComponent();

                // Make a clone of the schematic so we can mess with it.
                Circuit.Schematic clone = Circuit.Schematic.Deserialize(Simulate.Serialize(), Log);
                clone.Elements.ItemAdded   += OnElementAdded;
                clone.Elements.ItemRemoved += OnElementRemoved;
                Schematic = new SimulationSchematic(clone);
                Schematic.SelectionChanged += OnProbeSelected;

                // Build the circuit from the schematic.
                circuit = Schematic.Schematic.Build(Log);

                // Create the input and output controls.
                IEnumerable <Circuit.Component> components = circuit.Components;

                // Create audio input channels.
                for (int i = 0; i < Inputs.Length; ++i)
                {
                    InputChannels.Add(new InputChannel(i)
                    {
                        Name = Inputs[i].Name
                    });
                }

                ComputerAlgebra.Expression speakers = 0;

                foreach (Circuit.Component i in components)
                {
                    Circuit.Symbol S = i.Tag as Circuit.Symbol;
                    if (S == null)
                    {
                        continue;
                    }

                    SymbolControl tag = (SymbolControl)S.Tag;
                    if (tag == null)
                    {
                        continue;
                    }

                    // Create potentiometers.
                    Circuit.IPotControl c = i as Circuit.IPotControl;
                    if (c != null)
                    {
                        PotControl pot = new PotControl()
                        {
                            Width      = 80,
                            Height     = 80,
                            Opacity    = 0.5,
                            FontSize   = 15,
                            FontWeight = FontWeights.Bold,
                        };
                        Schematic.Overlays.Children.Add(pot);
                        Canvas.SetLeft(pot, Canvas.GetLeft(tag) - pot.Width / 2 + tag.Width / 2);
                        Canvas.SetTop(pot, Canvas.GetTop(tag) - pot.Height / 2 + tag.Height / 2);

                        pot.Value         = c.PotValue;
                        pot.ValueChanged += x => { c.PotValue = x; UpdateSimulation(false); };

                        pot.MouseEnter += (o, e) => pot.Opacity = 0.95;
                        pot.MouseLeave += (o, e) => pot.Opacity = 0.5;
                    }

                    // Create Buttons.
                    Circuit.IButtonControl b = i as Circuit.IButtonControl;
                    if (b != null)
                    {
                        Button button = new Button()
                        {
                            Width      = tag.Width,
                            Height     = tag.Height,
                            Opacity    = 0.5,
                            Background = Brushes.White,
                        };
                        Schematic.Overlays.Children.Add(button);
                        Canvas.SetLeft(button, Canvas.GetLeft(tag));
                        Canvas.SetTop(button, Canvas.GetTop(tag));

                        button.Click += (o, e) =>
                        {
                            // Click all the buttons in the group.
                            foreach (Circuit.IButtonControl j in components.OfType <Circuit.IButtonControl>().Where(x => x.Group == b.Group))
                            {
                                j.Click();
                            }
                            UpdateSimulation(true);
                        };

                        button.MouseEnter += (o, e) => button.Opacity = 0.95;
                        button.MouseLeave += (o, e) => button.Opacity = 0.5;
                    }

                    Circuit.Speaker output = i as Circuit.Speaker;
                    if (output != null)
                    {
                        speakers += output.V;
                    }

                    // Create input controls.
                    Circuit.Input input = i as Circuit.Input;
                    if (input != null)
                    {
                        tag.ShowText = false;

                        ComboBox combo = new ComboBox()
                        {
                            Width             = 80,
                            Height            = 24,
                            Opacity           = 0.5,
                            IsEditable        = true,
                            SelectedValuePath = "Tag",
                        };

                        foreach (InputChannel j in InputChannels)
                        {
                            combo.Items.Add(new ComboBoxItem()
                            {
                                Tag     = j,
                                Content = j.Name
                            });
                        }

                        Schematic.Overlays.Children.Add(combo);
                        Canvas.SetLeft(combo, Canvas.GetLeft(tag) - combo.Width / 2 + tag.Width / 2);
                        Canvas.SetTop(combo, Canvas.GetTop(tag) - combo.Height / 2 + tag.Height / 2);

                        ComputerAlgebra.Expression V = Circuit.Component.DependentVariable(input.Name, Circuit.Component.t);
                        inputs[V] = new SignalChannel(0);

                        combo.SelectionChanged += (o, e) =>
                        {
                            if (combo.SelectedItem != null)
                            {
                                ComboBoxItem it = (ComboBoxItem)combo.SelectedItem;
                                inputs[V] = new InputChannel(((InputChannel)it.Tag).Index);
                            }
                        };

                        combo.AddHandler(TextBox.KeyDownEvent, new KeyEventHandler((o, e) =>
                        {
                            try
                            {
                                inputs[V] = new SignalChannel(Circuit.Quantity.Parse(combo.Text, Circuit.Units.V));
                            }
                            catch (Exception)
                            {
                                // If there is an error in the expression, zero out the signal.
                                inputs[V] = new SignalChannel(0);
                            }
                        }));

                        if (combo.Items.Count > 0)
                        {
                            combo.SelectedItem = combo.Items[0];
                        }
                        else
                        {
                            combo.Text = "0 V";
                        }

                        combo.MouseEnter += (o, e) => combo.Opacity = 0.95;
                        combo.MouseLeave += (o, e) => combo.Opacity = 0.5;
                    }
                }

                // Create audio output channels.
                for (int i = 0; i < Outputs.Length; ++i)
                {
                    OutputChannel c = new OutputChannel(i)
                    {
                        Name = Outputs[i].Name, Signal = speakers
                    };
                    c.PropertyChanged += (o, e) => { if (e.PropertyName == "Signal")
                                                     {
                                                         RebuildSolution();
                                                     }
                    };
                    OutputChannels.Add(c);
                }


                // Begin audio processing.
                if (Inputs.Any() || Outputs.Any())
                {
                    stream = Device.Open(ProcessSamples, Inputs, Outputs);
                }
                else
                {
                    stream = new NullStream(ProcessSamples);
                }

                ContentRendered += (o, e) => RebuildSolution();

                Closed += (s, e) => stream.Stop();

                statusTime = new System.Timers.Timer()
                {
                    Interval  = 1000,
                    AutoReset = true,
                    Enabled   = true,
                };
                statusTime.Elapsed += StatusTime_Elapsed;
                statusTime.Start();
            }
            catch (Exception Ex)
            {
                MessageBox.Show(Ex.Message, "Error", MessageBoxButton.OK, MessageBoxImage.Error);
            }
        }
Пример #5
0
 public SignalChannel(ComputerAlgebra.Expression Signal)
 {
     signal = Signal.Compile <Func <double, double> >(Circuit.Component.t);
 }
Пример #6
0
        public LiveSimulation(Schematic Simulate, Audio.Device Device, Audio.Channel[] Inputs, Audio.Channel[] Outputs)
        {
            try
            {
                InitializeComponent();

                // Make a clone of the schematic so we can mess with it.
                var clone = Circuit.Schematic.Deserialize(Simulate.Serialize(), Log);
                clone.Elements.ItemAdded   += OnElementAdded;
                clone.Elements.ItemRemoved += OnElementRemoved;
                Schematic = new SimulationSchematic(clone);
                Schematic.SelectionChanged += OnProbeSelected;

                // Build the circuit from the schematic.
                circuit = Schematic.Schematic.Build(Log);

                // Create the input and output controls.
                IEnumerable <Circuit.Component> components = circuit.Components;

                // Create audio input channels.
                for (int i = 0; i < Inputs.Length; ++i)
                {
                    InputChannels.Add(new InputChannel(i)
                    {
                        Name = Inputs[i].Name
                    });
                }

                ComputerAlgebra.Expression speakers = 0;

                foreach (Circuit.Component i in components)
                {
                    Symbol S = i.Tag as Symbol;
                    if (S == null)
                    {
                        continue;
                    }

                    SymbolControl tag = (SymbolControl)S.Tag;
                    if (tag == null)
                    {
                        continue;
                    }

                    // Create potentiometers.
                    if (i is IPotControl potentiometer)
                    {
                        var potControl = new PotControl()
                        {
                            Width      = 80,
                            Height     = 80,
                            Opacity    = 0.5,
                            FontSize   = 15,
                            FontWeight = FontWeights.Bold,
                        };
                        Schematic.Overlays.Children.Add(potControl);
                        Canvas.SetLeft(potControl, Canvas.GetLeft(tag) - potControl.Width / 2 + tag.Width / 2);
                        Canvas.SetTop(potControl, Canvas.GetTop(tag) - potControl.Height / 2 + tag.Height / 2);

                        var binding = new Binding
                        {
                            Source = potentiometer,
                            Path   = new PropertyPath("(0)", typeof(IPotControl).GetProperty(nameof(IPotControl.PotValue))),
                            Mode   = BindingMode.TwoWay,
                            NotifyOnSourceUpdated = true
                        };

                        potControl.SetBinding(PotControl.ValueProperty, binding);

                        potControl.AddHandler(Binding.SourceUpdatedEvent, new RoutedEventHandler((o, args) =>
                        {
                            if (!string.IsNullOrEmpty(potentiometer.Group))
                            {
                                foreach (var p in components.OfType <IPotControl>().Where(p => p != potentiometer && p.Group == potentiometer.Group))
                                {
                                    p.PotValue = (o as PotControl).Value;
                                }
                            }
                            UpdateSimulation(false);
                        }));

                        potControl.MouseEnter += (o, e) => potControl.Opacity = 0.95;
                        potControl.MouseLeave += (o, e) => potControl.Opacity = 0.5;
                    }

                    // Create Buttons.
                    if (i is IButtonControl b)
                    {
                        Button button = new Button()
                        {
                            Width      = tag.Width,
                            Height     = tag.Height,
                            Opacity    = 0.5,
                            Background = Brushes.White,
                        };
                        Schematic.Overlays.Children.Add(button);
                        Canvas.SetLeft(button, Canvas.GetLeft(tag));
                        Canvas.SetTop(button, Canvas.GetTop(tag));

                        button.Click += (o, e) =>
                        {
                            b.Click();
                            // Click all the buttons in the group.
                            if (!string.IsNullOrEmpty(b.Group))
                            {
                                foreach (var j in components.OfType <IButtonControl>().Where(x => x != b && x.Group == b.Group))
                                {
                                    j.Click();
                                }
                            }
                            UpdateSimulation(true);
                        };

                        button.MouseEnter += (o, e) => button.Opacity = 0.95;
                        button.MouseLeave += (o, e) => button.Opacity = 0.5;
                    }

                    if (i is Speaker output)
                    {
                        speakers += output.Out;
                    }

                    // Create input controls.
                    if (i is Input input)
                    {
                        tag.ShowText = false;

                        ComboBox combo = new ComboBox()
                        {
                            Width             = 80,
                            Height            = 24,
                            Opacity           = 0.5,
                            IsEditable        = true,
                            SelectedValuePath = "Tag",
                        };

                        foreach (InputChannel j in InputChannels)
                        {
                            combo.Items.Add(new ComboBoxItem()
                            {
                                Tag     = j,
                                Content = j.Name
                            });
                        }

                        Schematic.Overlays.Children.Add(combo);
                        Canvas.SetLeft(combo, Canvas.GetLeft(tag) - combo.Width / 2 + tag.Width / 2);
                        Canvas.SetTop(combo, Canvas.GetTop(tag) - combo.Height / 2 + tag.Height / 2);

                        ComputerAlgebra.Expression In = input.In;
                        inputs[In] = new SignalChannel(0);

                        combo.SelectionChanged += (o, e) =>
                        {
                            if (combo.SelectedItem != null)
                            {
                                ComboBoxItem it = (ComboBoxItem)combo.SelectedItem;
                                inputs[In] = new InputChannel(((InputChannel)it.Tag).Index);
                            }
                        };

                        combo.AddHandler(TextBox.KeyDownEvent, new KeyEventHandler((o, e) =>
                        {
                            try
                            {
                                inputs[In] = new SignalChannel(ComputerAlgebra.Expression.Parse(combo.Text));
                            }
                            catch (Exception)
                            {
                                // If there is an error in the expression, zero out the signal.
                                inputs[In] = new SignalChannel(0);
                            }
                        }));

                        if (combo.Items.Count > 0)
                        {
                            combo.SelectedItem = combo.Items[0];
                        }
                        else
                        {
                            combo.Text = "0 V";
                        }

                        combo.MouseEnter += (o, e) => combo.Opacity = 0.95;
                        combo.MouseLeave += (o, e) => combo.Opacity = 0.5;
                    }
                }

                // Create audio output channels.
                for (int i = 0; i < Outputs.Length; ++i)
                {
                    OutputChannel c = new OutputChannel(i)
                    {
                        Name = Outputs[i].Name, Signal = speakers
                    };
                    c.PropertyChanged += (o, e) => { if (e.PropertyName == "Signal")
                                                     {
                                                         RebuildSolution();
                                                     }
                    };
                    OutputChannels.Add(c);
                }


                // Begin audio processing.
                if (Inputs.Any() || Outputs.Any())
                {
                    stream = Device.Open(ProcessSamples, Inputs, Outputs);
                }
                else
                {
                    stream = new NullStream(ProcessSamples);
                }

                ContentRendered += (o, e) => RebuildSolution();

                Closed += (s, e) => stream.Stop();

                timer = new System.Timers.Timer()
                {
                    Interval  = 100,
                    AutoReset = true,
                    Enabled   = true,
                };
                timer.Elapsed += timer_Elapsed;
                timer.Start();
            }
            catch (Exception Ex)
            {
                MessageBox.Show(Ex.Message, "Error", MessageBoxButton.OK, MessageBoxImage.Error);
            }
        }