From 826625f3fb7183927926bb3c6cbd65f265f21896 Mon Sep 17 00:00:00 2001
From: Simon Bjurek <simbj106@student.liu.se>
Date: Tue, 4 Feb 2025 09:08:11 +0000
Subject: [PATCH] Add direct form iir sfg gen

---
 b_asic/gui_utils/plot_window.py |   6 +-
 b_asic/sfg_generators.py        | 116 ++++++++++++++++++++++++++++++++
 2 files changed, 119 insertions(+), 3 deletions(-)

diff --git a/b_asic/gui_utils/plot_window.py b/b_asic/gui_utils/plot_window.py
index 5322debf..96c3bec5 100644
--- a/b_asic/gui_utils/plot_window.py
+++ b/b_asic/gui_utils/plot_window.py
@@ -6,8 +6,8 @@ from typing import Dict, List, Mapping, Optional, Sequence  # , Union
 
 # from numpy import (array, real, imag, real_if_close, absolute, angle)
 import numpy as np
-from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
-from matplotlib.backends.backend_qt5agg import NavigationToolbar2QT as NavigationToolbar
+from matplotlib.backends.backend_qtagg import FigureCanvasQTAgg as FigureCanvas
+from matplotlib.backends.backend_qtagg import NavigationToolbar2QT as NavigationToolbar
 from matplotlib.figure import Figure
 from matplotlib.ticker import MaxNLocator
 from qtpy.QtCore import Qt
@@ -251,7 +251,7 @@ def start_simulation_dialog(
         The name of the SFG.
     """
     if not QApplication.instance():
-        QApplication.setAttribute(Qt.AA_EnableHighDpiScaling)
+        # QApplication.setAttribute(Qt.AA_EnableHighDpiScaling)
         app = QApplication(sys.argv)
     else:
         app = QApplication.instance()
diff --git a/b_asic/sfg_generators.py b/b_asic/sfg_generators.py
index cdfb93b4..2b693af3 100644
--- a/b_asic/sfg_generators.py
+++ b/b_asic/sfg_generators.py
@@ -255,3 +255,119 @@ def transposed_direct_form_fir(
     output <<= tmp_add
 
     return SFG([input_op], [output], name=Name(name))
+
+
+def direct_form_1_iir(
+    b: Sequence[complex],
+    a: Sequence[complex],
+    name: Optional[str] = None,
+    mult_properties: Optional[Union[Dict[str, int], Dict[str, Dict[str, int]]]] = None,
+    add_properties: Optional[Union[Dict[str, int], Dict[str, Dict[str, int]]]] = None,
+) -> SFG:
+    """Generates a direct-form IIR filter of type I with coefficients a and b."""
+    if len(a) != len(b):
+        raise ValueError("size of coefficient lists a and b are not the same")
+    if name is None:
+        name = "Direct-form I IIR filter"
+    if mult_properties is None:
+        mult_properties = {}
+    if add_properties is None:
+        add_properties = {}
+
+    # construct the feed-forward part
+    input_op = Input()
+    muls = [ConstantMultiplication(b[0], input_op, **mult_properties)]
+    delays = []
+    prev_delay = input_op
+    for i, coeff in enumerate(b[1:]):
+        prev_delay = Delay(prev_delay)
+        delays.append(prev_delay)
+        if i < len(b) - 1:
+            muls.append(ConstantMultiplication(coeff, prev_delay, **mult_properties))
+
+    op_a = muls[-1]
+    for i in range(len(muls) - 1):
+        op_a = Addition(op_a, muls[-i - 2], **add_properties)
+
+    # construct the feedback part
+    tmp_add = Addition(op_a, None, **add_properties)
+    muls = []
+    output = Output()
+    output <<= tmp_add
+
+    delays = []
+    prev_delay = tmp_add
+    for i, coeff in enumerate(a[1:]):
+        prev_delay = Delay(prev_delay)
+        delays.append(prev_delay)
+        if i < len(a) - 1:
+            muls.append(ConstantMultiplication(-coeff, prev_delay, **mult_properties))
+
+    op_a = muls[-1]
+    for i in range(len(muls) - 1):
+        op_a = Addition(op_a, muls[-i - 2], **add_properties)
+
+    tmp_add.input(1).connect(op_a)
+
+    return SFG([input_op], [output], name=Name(name))
+
+
+def direct_form_2_iir(
+    b: Sequence[complex],
+    a: Sequence[complex],
+    name: Optional[str] = None,
+    mult_properties: Optional[Union[Dict[str, int], Dict[str, Dict[str, int]]]] = None,
+    add_properties: Optional[Union[Dict[str, int], Dict[str, Dict[str, int]]]] = None,
+) -> SFG:
+    """Generates a direct-form IIR filter of type II with coefficients a and b."""
+    if len(a) != len(b):
+        raise ValueError("size of coefficient lists a and b are not the same")
+    if name is None:
+        name = "Direct-form II IIR filter"
+    if mult_properties is None:
+        mult_properties = {}
+    if add_properties is None:
+        add_properties = {}
+
+    # construct the repeated part of the SFG
+    left_adds = []
+    right_adds = []
+    left_muls = []
+    right_muls = []
+    delays = [Delay()]
+    op_a_left = None
+    op_a_right = None
+    for i in range(len(a) - 1):
+        a_coeff = a[-i - 1]
+        b_coeff = b[-i - 1]
+        if len(left_muls) != 0:  # not first iteration
+            new_delay = Delay()
+            delays[-1] <<= new_delay
+            delays.append(new_delay)
+        left_muls.append(
+            ConstantMultiplication(-a_coeff, delays[-1], **mult_properties)
+        )
+        right_muls.append(
+            ConstantMultiplication(b_coeff, delays[-1], **mult_properties)
+        )
+        if len(left_muls) > 1:  # not first iteration
+            left_adds.append(Addition(op_a_left, left_muls[-1], **add_properties))
+            right_adds.append(Addition(op_a_right, right_muls[-1], **add_properties))
+            op_a_left = left_adds[-1]
+            op_a_right = right_adds[-1]
+        else:
+            op_a_left = left_muls[-1]
+            op_a_right = right_muls[-1]
+
+    # finalize the SFG
+    input_op = Input()
+    if left_adds:
+        left_adds.append(Addition(input_op, left_adds[-1], **add_properties))
+    else:
+        left_adds.append(Addition(input_op, left_muls[-1], **add_properties))
+    delays[-1] <<= left_adds[-1]
+    mul = ConstantMultiplication(b[0], left_adds[-1], **mult_properties)
+    add = Addition(mul, right_adds[-1], **add_properties)
+    output = Output()
+    output <<= add
+    return SFG([input_op], [output], name=Name(name))
-- 
GitLab