예제 #1
0
    def setupHDL(self, file_name = "", dir_name = ""):
        """
        Setup instance of myHDL object with word lengths and coefficients
        """

        # get a dict with the coefficients and fixpoint settings from fixpoint widget
        self.hdl_dict = self.fx_wdg_inst.get_hdl_dict()
        self.q_i = fx.Fixed(self.hdl_dict['QI']) # setup quantizer for input quantization
        self.q_i.setQobj({'frmt':'dec'})#, 'scale':'int'}) # use integer decimal format
        self.q_o = fx.Fixed(self.hdl_dict['QO']) # setup quantizer for output quantization


        b = [ int(x) for x in self.hdl_dict['QC']['b']] # convert np.int64 to python int
        a = [ int(x) for x in self.hdl_dict['QC']['a']] # convert np.int64 to python int

        # call setup method of filter widget - this is not implemented (yet)
        # self.fx_wdg_inst.setup_HDL(self.hdl_dict)
        
        if fb.fil[0]['ft'] == 'FIR':
            self.hdlfilter = FilterFIR()     # Standard DF1 filter - hdl_dict should be passed here
            self.hdlfilter.set_coefficients(coeff_b = b)  # Coefficients for the filter
        elif fb.fil[0]['ft'] == 'IIR':
            self.hdlfilter = FilterIIR()     # Standard DF1 filter - hdl_dict should be passed here
            self.hdlfilter.set_coefficients(coeff_b = b, coeff_a = a)  # Coefficients for the filter
        else:
            logger.error("Unknown filter type {0}".format(fb.fil[0]['ft']))            

        # pass wordlength for coeffs, input, output
        self.hdlfilter.set_word_format(
                (self.hdl_dict['QC']['W'], self.hdl_dict['QC']['WI'], self.hdl_dict['QC']['WF']),
                (self.hdl_dict['QI']['W'], self.hdl_dict['QI']['WI'], self.hdl_dict['QI']['WF']),
                (self.hdl_dict['QO']['W'], self.hdl_dict['QO']['WI'], self.hdl_dict['QO']['WF'])
                )
예제 #2
0
파일: iir_df1.py 프로젝트: rob0tsunny/pyFDA
    def update_hdl_filter(self):
        """
        Update the HDL filter object with new coefficients, quantization settings etc. when
        
        - it is constructed
        
        - filter design and hence coefficients change
        
        - quantization settings are updated in this widget
        """
        # setup input and output quantizers
        self.q_i = fx.Fixed(self.hdl_dict['QI']) # setup quantizer for input quantization
        self.q_i.setQobj({'frmt':'dec'})#, 'scale':'int'}) # use integer decimal format
        self.q_o = fx.Fixed(self.hdl_dict['QO']) # setup quantizer for output quantization

        b = [ int(x) for x in self.hdl_dict['QC']['b']] # convert np.int64 to python int
        a = [ int(x) for x in self.hdl_dict['QC']['a']] # convert np.int64 to python int

        # call setup method of filter widget - this is not implemented (yet)
        # self.fx_wdg_inst.setup_HDL(self.hdl_dict)
        
        self.hdlfilter.set_coefficients(coeff_b = b, coeff_a = a)  # Coefficients for the filter

        # pass wordlength for coeffs, input, output
        # TODO: directly pass the hdl_dict here:
        self.hdlfilter.set_word_format(
                (self.hdl_dict['QC']['W'], self.hdl_dict['QC']['WI'], self.hdl_dict['QC']['WF']),
                (self.hdl_dict['QI']['W'], self.hdl_dict['QI']['WI'], self.hdl_dict['QI']['WF']),
                (self.hdl_dict['QO']['W'], self.hdl_dict['QO']['WI'], self.hdl_dict['QO']['WF'])
                )
예제 #3
0
파일: hdl_specs.py 프로젝트: svolpe/pyFDA
    def setupHDL(self, filename = ""):
        """
        Setup instance of myHDL object with word lengths and coefficients
        """

        qI_i = int(self.ledQIInput.text())
        qF_i = int(self.ledQFInput.text())
        
        qI_o = int(self.ledQIOutput.text())
        qF_o = int(self.ledQFOutput.text())
        
        qQuant_o = self.cmbQuant_o.currentText()
        qOvfl_o = self.cmbOvfl_o.currentText()
        
        q_obj_o =  {'QI':qI_o, 'QF': qF_o, 'quant': qQuant_o, 'ovfl': qOvfl_o}
        myQ_o = fix.Fixed(q_obj_o) # instantiate fixed-point object


        self.W = (qI_i + qF_i + 1, 0) # Matlab format: (W,WF)
        
        #       get filter coefficients etc. from filter dict    
        coeffs = fb.fil[0]['ba']
        zpk =  fb.fil[0]['zpk']
        sos = fb.fil[0]['sos']

        # =============== adapted from C. Feltons SIIR example =============
        self.flt = SIIR(W = self.W, b = np.array(coeffs[0][0:3]), 
                          a = np.array(coeffs[1][0:3]))
예제 #4
0
    def quant_coeffs(self, q_dict, coeffs):
        """
        Quantize the coefficients, scale and convert them to integer and return them
        as a list of integers
        
        This is called every time one of the coefficient subwidgets is edited or changed.
    
        Parameters:
        -----------
        None
    
        Returns:
        --------
        A list of integer coeffcients, quantized and scaled with the settings
        of the passed quantization dict
               
        """
        # Create coefficient quantizer instances using the quantization parameters dict
        # collected in `input_widgets/input_coeffs.py` (and stored in the central filter dict)
        Q_coeff = fix.Fixed(q_dict)
        Q_coeff.frmt = 'dec'  # always use decimal format for coefficients

        if coeffs is None:
            logger.error("Coeffs empty!")
        # quantize floating point coefficients and convert them to the
        # selected numeric format (hex, bin, dec ...) with the selected scale (WI.WF),
        # next convert array float -> array of fixp - > list of int (scaled by 2^WF)
        return list(Q_coeff.float2frmt(coeffs) * (1 << Q_coeff.WF))
예제 #5
0
파일: file_io.py 프로젝트: TheRittler/pyFDA
    def save_file_coe(self, file_name):
        """
        Save filter coefficients in Xilinx coefficient format, specifying
        the number base and the quantized coefficients
        """

        frmt = fb.fil[0]['q_coeff']['frmt'] # store old format
        fb.fil[0]['q_coeff']['frmt'] = 'dec' # 'hex'
        qc = fix_lib.Fixed(fb.fil[0]['q_coeff'])
        bq = qc.fix(fb.fil[0]['ba'][0]) # Quantize coefficients to integer format
        coe_width = qc.QF + qc.QI + 1 # quantized word length; Int. + Frac. + Sign bit
        if fb.fil[0]['q_coeff']['frmt'] == 'dec':
            coe_radix = 10
        else:
            coe_radix = 16

        fb.fil[0]['q_coeff']['frmt'] = frmt # restore old coefficient format

        info_str = (
            "; #############################################################################\n"
             ";\n; XILINX CORE Generator(tm) Distributed Arithmetic FIR filter coefficient (.COE) file\n"
             ";\n; Generated by pyFDA 0.1 (https://github.com/chipmuenk/pyfda)\n;\n; ")
        date_str = datetime.datetime.now().strftime("%d-%B-%Y %H:%M:%S")

        file_name.write(info_str + date_str + "\n;\n")
        filt_str = "; Filter order = %d, type: %s\n" %(fb.fil[0]["N"], fb.fil[0]['rt'])
        file_name.write(filt_str)
        file_name.write("; #############################################################################\n")
        file_name.write("Radix = %d;\n" %coe_radix)
        file_name.write("Coefficient_width = %d;\n" %coe_width)
        coeff_str = "CoefData = "
        for b in bq:
            coeff_str += str(b) + ",\n"
        file_name.write(coeff_str[:-2] + ";") # replace last "," by ";"
예제 #6
0
    def quant_coeffs(self):
        """
        Quantize all coefficients
        """
        # define + instantiate fixed-point object
        myQ = fix.Fixed({
            'QI': int(self.ledQuantI.text()),
            'QF': int(self.ledQuantF.text()),
            'quant': self.cmbQQuant.currentText(),
            'ovfl': self.cmbQOvfl.currentText(),
            'frmt': self.cmbQFormat.currentText()
        })

        num_rows, num_cols = self.tblCoeff.rowCount(),\
                                        self.tblCoeff.columnCount()
        for col in range(num_cols):
            for row in range(num_rows):
                item = self.tblCoeff.item(row, col)
                if item:
                    item.setText(str(myQ.fix(simple_eval(item.text()))))
                else:
                    self.tblCoeff.setItem(row, col,
                                          QtGui.QTableWidgetItem("0.0"))

        self.tblCoeff.resizeColumnsToContents()
        self.tblCoeff.resizeRowsToContents()
예제 #7
0
def build_coeff_dict(frmt=None):
    """
    Read and quantize the coefficients and return them as a dictionary.
    
    This is called every time one of the coefficient subwidgets is edited or changed.

    Parameters:
    -----------
    frmt: string

    One of the following options: 'dec' (default), 'hex', 'bin', 'csd'

    Returns:
    --------
    A dictionary with the followig keys and values:

        - WI: integer

        - WF: integer

        - scale: float

        - frmt: string

        - f_fix: np.array

        - a_fix: np.array

    """
    bf = fb.fil[0]['ba'][0]  # get coefficients from
    af = fb.fil[0]['ba'][1]  # filter dict in float form
    # Create a coefficient quantizer instance using the quantization parameters dict
    # collected in `input_widgets/input_coeffs.py` (and stored in the central filter dict)
    Q_coeff = fix.Fixed(fb.fil[0]["q_coeff"])
    #Q_coeff.setQobj(fb.fil[0]['q_coeff']) # alternative: explicitly call setter
    if not frmt:
        Q_coeff.frmt = 'dec'  # use decimal format for coefficients by default
    else:
        Q_coeff.frmt = frmt  # use the function argument

    # quantize floating point coefficients and convert them to the
    # selected numeric format (hex, bin, dec ...) with the selected scale (WI.WF)
    c_dict = {}
    # convert list of float -> dec (np.int64).
    # item() converts np.int64 -> int
    c_dict.update({'b': [b.item() for b in Q_coeff.float2frmt(bf)]
                   })  # convert float -> fixp and
    c_dict.update({'a': [a.item() for a in Q_coeff.float2frmt(af)]
                   })  # format it as bin, hex, ...
    c_dict.update({'WF':
                   Q_coeff.WF})  # read parameters from quantizer instance
    c_dict.update({'WI': Q_coeff.WI})  # and pass them to the coefficient dict
    c_dict.update({'W': Q_coeff.W})
    c_dict.update({'scale': Q_coeff.scale})  # for later use
    c_dict.update({'frmt': Q_coeff.frmt})

    return c_dict
예제 #8
0
    def setupHDL(self, file_name="", dir_name=""):
        """
        Setup instance of myHDL object with word lengths and coefficients
        """
        self.qI_i = safe_eval(self.ledWIInput.text(),
                              return_type='int',
                              sign='pos')
        self.qF_i = safe_eval(self.ledWFInput.text(),
                              return_type='int',
                              sign='pos')
        self.ledWIInput.setText(qstr(self.qI_i))
        self.ledWFInput.setText(qstr(self.qF_i))

        self.qI_o = safe_eval(self.ledWIOutput.text(),
                              return_type='int',
                              sign='pos')
        self.qF_o = safe_eval(self.ledWFOutput.text(),
                              return_type='int',
                              sign='pos')
        self.ledWIOutput.setText(qstr(self.qI_o))
        self.ledWFOutput.setText(qstr(self.qF_o))

        qQuant_o = self.cmbQuant_o.currentText()
        qOvfl_o = self.cmbOvfl_o.currentText()

        q_obj_o = {
            'WI': self.qI_o,
            'WF': self.qF_o,
            'quant': qQuant_o,
            'ovfl': qOvfl_o
        }
        myQ_o = fix.Fixed(q_obj_o)  # instantiate fixed-point object

        self.W = (self.qI_i + self.qF_i + 1, self.qF_i
                  )  # Matlab format: (W,WF)

        # @todo: always use sos?  The filter object is setup to always
        # @todo: generate a second order filter
        # get filter coefficients etc. from filter dict
        coeffs = fb.fil[0]['ba']
        zpk = fb.fil[0]['zpk']
        sos = fb.fil[0]['sos']

        logger.info("W = {0}".format(self.W))
        logger.info('b = {0}'.format(coeffs[0][0:3]))
        logger.info('a = {0}'.format(coeffs[1][0:3]))

        # =============== adapted from C. Felton's SIIR example =============
        self.flt = FilterIIR(
            b=np.array(coeffs[0][0:3]),
            a=np.array(coeffs[1][0:3]),
            #sos = sos, doesn't work yet
            word_format=(self.W[0], 0, self.W[1]))

        self.flt.hdl_name = file_name
        self.flt.hdl_directory = dir_name
예제 #9
0
    def update_fxqc_dict(self):
        """
        Update the fxqc dictionary before simulation / HDL generation starts.
        """
        if self.fx_wdg_found:
            # get a dict with the coefficients and fixpoint settings from fixpoint widget
            if hasattr(self.fx_wdg_inst, "ui2dict"):
                self.fxqc_dict.update(self.fx_wdg_inst.ui2dict())

            self.q_i = fx.Fixed(
                self.fxqc_dict['QI'])  # setup quantizer for input quantization
            self.q_i.setQobj({
                'frmt': 'dec'
            })  #, 'scale':'int'}) # always use integer decimal format
            self.q_o = fx.Fixed(self.fxqc_dict['QO']
                                )  # setup quantizer for output quantization
            # TODO:  is the output quantizer really needed? Isn't it part of the migen implementation?
        else:
            logger.error("No fixpoint widget found!")
예제 #10
0
    def update_fxqc_dict(self):
        """
        Update the fxqc dictionary before simulation / HDL generation starts. It
        is NOT updated each time one of the relevant widgets changes ("lazy update").
         This avoids having to connect and disconnect all sorts of signals and slots.
        """
        if self.fx_wdg_found:
            # get a dict with the coefficients and fixpoint settings from fixpoint widget
            if hasattr(self.fx_wdg_inst, "ui2dict"):
                self.fxqc_dict.update(self.fx_wdg_inst.ui2dict())

            # update the fxqc_dict with the settings of the input quantizer
            self.fxqc_dict.update({
                'QI': {
                    'WI': self.wdg_w_input.WI,
                    'WF': self.wdg_w_input.WF,
                    'W': self.wdg_w_input.W,
                    'ovfl': self.wdg_q_input.ovfl,
                    'quant': self.wdg_q_input.quant
                }
            })
            # output quantization parameters
            self.fxqc_dict.update({
                'QO': {
                    'WI': self.wdg_w_output.WI,
                    'WF': self.wdg_w_output.WF,
                    'W': self.wdg_w_output.W,
                    'ovfl': self.wdg_q_output.ovfl,
                    'quant': self.wdg_q_output.quant
                }
            })

            self.q_i = fx.Fixed(
                self.fxqc_dict['QI'])  # setup quantizer for input quantization
            self.q_i.setQobj({
                'frmt': 'dec'
            })  #, 'scale':'int'}) # always use integer decimal format
            self.q_o = fx.Fixed(self.fxqc_dict['QO']
                                )  # setup quantizer for output quantization
        else:
            logger.error("No fixpoint widget found!")
예제 #11
0
def build_coeff_dict(frmt=None):
    """
    Read and quantize the coefficients and return them as a dictionary

    Parameters:
    -----------
    frmt: string

    One of the following options: 'dec' (default), 'hex', 'bin', 'csd'

    Returns:
    --------
    A dictionary with the followig keys and values:

        - WI: integer

        - WF: integer

        - scale:

        - frmt:

        - f_fix: np.array

        - a_fix: np.array

    """
    b = fb.fil[0]['ba'][0]
    a = fb.fil[0]['ba'][1]
    # update the coefficient quantizer object
    Q_coeff = fix.Fixed(fb.fil[0]["q_coeff"])
    #Q_coeff.setQobj(fb.fil[0]['q_coeff'])
    if not frmt:
        Q_coeff.frmt = 'dec' # use decimal format for coefficients by default
    else:
        Q_coeff.frmt = frmt # use the function argument

    # quantize floating point coefficients and converts them to the
    # selected numeric format (hex, bin, dec ...)
    c_dict = {}
    c_dict.update({'b':list(Q_coeff.float2frmt(b))})
    c_dict.update({'a':list(Q_coeff.float2frmt(a))})
    c_dict.update({'WF':Q_coeff.WF})
    c_dict.update({'WI':Q_coeff.WI})
    c_dict.update({'scale':Q_coeff.scale})
    c_dict.update({'frmt':Q_coeff.frmt})

    return c_dict
예제 #12
0
def export_coe_microsemi(f):
    """
    Save FIR filter coefficients in Actel coefficient format as file '\*.txt'.
    Coefficients have to be in integer format, the last line has to be empty.
    For (anti)aymmetric filter only one half of the coefficients must be
    specified?
    """
    qc = fix_lib.Fixed(fb.fil[0]['q_coeff']) # instantiate fixpoint object
    qc.setQobj({'frmt':'dec'}) # select decimal format in all other cases
    # Quantize coefficients to decimal integer format, returning an array of strings
    bq = qc.float2frmt(fb.fil[0]['ba'][0])

    coeff_str = "coefficient_set_1\n"
    for b in bq:
        coeff_str += str(b) + "\n"

    f.write(coeff_str)
예제 #13
0
def export_coe_xilinx(f):
    """
    Save FIR filter coefficients in Xilinx coefficient format as file '\*.coe', specifying
    the number base and the quantized coefficients (decimal or hex integer).
    """
    qc = fix_lib.Fixed(fb.fil[0]['q_coeff'])  # instantiate fixpoint object

    if qc.frmt == 'hex':  # select hex format
        coe_radix = 16
    else:
        qc.setQobj({'frmt': 'dec'})  # select decimal format in all other cases
        coe_radix = 10

    # Quantize coefficients to decimal / hex integer format, returning an array of strings
    bq = qc.float2frmt(fb.fil[0]['ba'][0])

    date_frmt = "%d-%B-%Y %H:%M:%S"  # select date format

    xil_str = (
        "; #############################################################################\n"
        ";\n; XILINX CORE Generator(tm) Distributed Arithmetic FIR filter coefficient (.COE) file\n"
        ";\n; Generated by pyFDA 0.1 (https://github.com/chipmuenk/pyfda)\n;\n"
    )

    xil_str += "; Designed:\t{0}\n".format(
        datetime.datetime.fromtimestamp(int(
            fb.fil[0]['timestamp'])).strftime(date_frmt))
    xil_str += "; Saved:\t{0}\n;\n".format(
        datetime.datetime.now().strftime(date_frmt))
    xil_str += "; Filter order = {0}, type: {1}\n".format(
        fb.fil[0]["N"], fb.fil[0]['rt'])
    xil_str += "; Params:\t f_S = {0}\n".format(fb.fil[0]["f_S"])
    xil_str += "; #############################################################################\n"
    xil_str += "Radix = {0};\n".format(coe_radix)
    xil_str += "Coefficient_width = {0};\n".format(
        qc.W)  # quantized wordlength
    coeff_str = "CoefData = "
    for b in bq:
        coeff_str += str(b) + ",\n"
    xil_str += coeff_str[:-2] + ";"  # replace last "," by ";"

    f.write(unicode_23(xil_str))  # convert to unicode for Python 2
예제 #14
0
    def setUp(self):
        q_obj = {
            'WI': 0,
            'WF': 3,
            'ovfl': 'sat',
            'quant': 'round',
            'frmt': 'dec',
            'scale': 1
        }
        self.myQ = fix_lib.Fixed(
            q_obj)  # instantiate fixpoint object with settings above

        self.y_list = [-1.1, -1.0, -0.5, 0, 0.5, 0.9, 0.99, 1.0, 1.1]
        self.y_list_cmplx = [
            -1.1j + 0.1, -1.0 - 0.3j, -0.5 - 0.5j, 0j, 0.5j, 0.9, 0.99 + 0.3j,
            1j, 1.1
        ]
        # list with various invalid strings
        self.y_list_validate = [
            '1.1.1', 'xxx', '123', '1.23', '', 1.23j + 3.21, '3.21 + 1.23 j'
        ]
예제 #15
0
    def _construct_UI(self):
        """
        Intitialize the widget, consisting of:
        - top chkbox row
        - coefficient table
        - two bottom rows with action buttons
        """

        # handle to central clipboard instance
        self.clipboard = fb.clipboard

        # ---------------------------------------------------------------------
        #   Coefficient table widget
        # ---------------------------------------------------------------------
        self.tblCoeff = QTableWidget(self)
        self.tblCoeff.setAlternatingRowColors(True)
        self.tblCoeff.horizontalHeader().setHighlightSections(True) # highlight when selected
        self.tblCoeff.horizontalHeader().setFont(self.ui.bfont)

#        self.tblCoeff.QItemSelectionModel.Clear
        self.tblCoeff.setDragEnabled(True)
#        self.tblCoeff.setDragDropMode(QAbstractItemView.InternalMove) # doesn't work like intended
        self.tblCoeff.setItemDelegate(ItemDelegate(self))

        # ============== Main UI Layout =====================================
        layVMain = QVBoxLayout()
        layVMain.setAlignment(Qt.AlignTop) # this affects only the first widget (intended here)
        layVMain.addWidget(self.ui)
        layVMain.addWidget(self.tblCoeff)

        layVMain.setContentsMargins(*params['wdg_margins'])

        self.setLayout(layVMain)

        self.myQ = fix.Fixed(fb.fil[0]["q_coeff"]) # initialize fixpoint object
        self.load_dict() # initialize + refresh table with default values from filter dict
        # TODO: this needs to be optimized - self._refresh is being called in both routines
        self._set_number_format()

        # ============== Signals & Slots ================================
        # wdg.textChanged() is emitted when contents of widget changes
        # wdg.textEdited() is only emitted for user changes
        # wdg.editingFinished() is only emitted for user changes
        self.ui.butEnable.clicked.connect(self._refresh_table)
        self.ui.spnDigits.editingFinished.connect(self._refresh_table)

        self.ui.cmbQFrmt.currentIndexChanged.connect(self._set_number_format)
        self.ui.butFromTable.clicked.connect(self._copy_from_table)
        self.ui.butToTable.clicked.connect(self._copy_to_table)

        self.ui.cmbFilterType.currentIndexChanged.connect(self._filter_type)

        self.ui.butDelCells.clicked.connect(self._delete_cells)
        self.ui.butAddCells.clicked.connect(self._add_cells)
        self.ui.butLoad.clicked.connect(self.load_dict)
        self.ui.butSave.clicked.connect(self._save_dict)
        self.ui.butClear.clicked.connect(self._clear_table)
        self.ui.ledEps.editingFinished.connect(self._set_eps)
        self.ui.butSetZero.clicked.connect(self._set_coeffs_zero)

        # refresh table after storing new settings
        self.ui.cmbFormat.currentIndexChanged.connect(self._refresh_table)
        self.ui.cmbQOvfl.currentIndexChanged.connect(self._refresh_table)
        self.ui.cmbQuant.currentIndexChanged.connect(self._refresh_table)
        self.ui.ledWF.editingFinished.connect(self._WIWF_changed)
        self.ui.ledWI.editingFinished.connect(self._WIWF_changed)
        self.ui.ledW.editingFinished.connect(self._W_changed)

        self.ui.ledScale.editingFinished.connect(self._set_scale)

        self.ui.butQuant.clicked.connect(self.quant_coeffs)
예제 #16
0
    def _construct_UI(self):
        """
        Intitialize the widget, consisting of:
        - top chkbox row
        - coefficient table
        - two bottom rows with action buttons
        """
        self.bfont = QFont()
        self.bfont.setBold(True)
        self.bifont = QFont()
        self.bifont.setBold(True)
        self.bifont.setItalic(True)
        #        q_icon_size = QSize(20, 20) # optional, size is derived from butEnable

        #==============================================================================
        #          #Which Button holds the longest Text?
        #         MaxTextlen = 0
        #         longestText = ""
        #         ButLength = 0
        #         butTexts = ["Add", "Delete", "Save", "Load", "Clear", "Set Zero", "< Q >"]
        #
        #         # Find the longest text + padding for subsequent bounding box calculation
        #         for item in butTexts:
        #             if len(item) > MaxTextlen:
        #                 MaxTextlen = len(item)
        #                 longestText = item + "mm" # this is the longest text + padding for
        #
        #         #Calculate the length for the buttons based on the longest ButtonText
        #         #ButLength = butAddRow.fontMetrics().boundingRect(longestText).width()
        #        butDelCell.setText(butTexts[1])
        #        butDelCell.setMaximumWidth(ButLength)
        #
        #==============================================================================
        # ---------------------------------------------
        # UI Elements for controlling the display
        # ---------------------------------------------
        self.butEnable = QPushButton(self)
        self.butEnable.setIcon(QIcon(':/circle-check.svg'))
        q_icon_size = self.butEnable.iconSize(
        )  # <- uncomment this for manual sizing
        self.butEnable.setIconSize(q_icon_size)
        self.butEnable.setCheckable(True)
        self.butEnable.setChecked(True)
        self.butEnable.setToolTip(
            "<span>Show filter coefficients as an editable table."
            "For high order systems, this might be slow.</span>")

        self.cmbFormat = QComboBox(self)
        #        self.cmbFormat.addItem('Float')
        qFormat = ['Float', 'Dec', 'Hex', 'Bin', 'CSD']
        self.cmbFormat.addItems(qFormat)
        self.cmbFormat.insertSeparator(1)
        self.cmbFormat.setCurrentIndex(0)  # 'float'
        self.cmbFormat.setToolTip('Set the display format.')
        self.cmbFormat.setSizeAdjustPolicy(QComboBox.AdjustToContents)

        self.lblRound = QLabel("Digits = ", self)
        self.spnRound = QSpinBox(self)
        self.spnRound.setRange(0, 16)
        self.spnRound.setValue(params['FMT_ba'])
        self.spnRound.setToolTip("Display <i>d</i> digits.")

        self.chkRadixPoint = QCheckBox("Radix point", self)
        self.chkRadixPoint.setToolTip(
            "<span>Show and use radix point (= decimal"
            " point for base 10) for fixpoint formats (still disabled).</span>"
        )
        self.chkRadixPoint.setChecked(False)
        self.chkRadixPoint.setCheckable(True)

        layHDisplay = QHBoxLayout()
        layHDisplay.setAlignment(Qt.AlignLeft)
        layHDisplay.addWidget(self.butEnable)
        layHDisplay.addWidget(self.cmbFormat)
        layHDisplay.addWidget(self.lblRound)
        layHDisplay.addWidget(self.spnRound)
        layHDisplay.addWidget(self.chkRadixPoint)
        layHDisplay.addStretch()

        # ---------------------------------------------
        # UI Elements for loading / storing
        # ---------------------------------------------
        self.cmbFilterType = QComboBox(self)
        self.cmbFilterType.setObjectName("comboFilterType")
        self.cmbFilterType.setToolTip(
            "Select between IIR and FIR filte for manual entry.")
        self.cmbFilterType.addItems(["FIR", "IIR"])
        self.cmbFilterType.setSizeAdjustPolicy(QComboBox.AdjustToContents)

        self.tblCoeff = QTableWidget(self)
        self.tblCoeff.setAlternatingRowColors(True)
        self.tblCoeff.horizontalHeader().setHighlightSections(
            True)  # highlight when selected
        self.tblCoeff.horizontalHeader().setFont(self.bfont)

        #        self.tblCoeff.QItemSelectionModel.Clear
        self.tblCoeff.setDragEnabled(True)
        #        self.tblCoeff.setDragDropMode(QAbstractItemView.InternalMove) # doesn't work like intended
        self.tblCoeff.setItemDelegate(ItemDelegate(self))

        butAddCells = QPushButton(self)
        butAddCells.setIcon(QIcon(':/plus.svg'))
        butAddCells.setIconSize(q_icon_size)
        butAddCells.setToolTip(
            "<SPAN>Select cells to insert a new cell above each selected cell. "
            "Use &lt;SHIFT&gt; or &lt;CTRL&gt; to select multiple cells. "
            "When nothing is selected, add a row at the end.</SPAN>")

        butDelCells = QPushButton(self)
        butDelCells.setIcon(QIcon(':/minus.svg'))
        butDelCells.setIconSize(q_icon_size)
        butDelCells.setToolTip(
            "<SPAN>Delete selected cell(s) from the table. "
            "Use &lt;SHIFT&gt; or &lt;CTRL&gt; to select multiple cells. "
            "When nothing is selected, delete the last row.</SPAN>")

        butQuant = QPushButton(self)
        butQuant.setToolTip(
            "<span>Quantize selected coefficients with specified settings. "
            "When nothing is selected, quantize the whole table.</span>")
        #        butQuant.setText("Q!")
        butQuant.setIcon(QIcon(':/quantize.svg'))
        butQuant.setIconSize(q_icon_size)

        self.butSave = QPushButton(self)
        self.butSave.setIcon(QIcon(':/upload.svg'))
        self.butSave.setIconSize(q_icon_size)
        self.butSave.setToolTip(
            "<span>Save coefficients and update all plots. "
            "No modifications are saved before!</span>")

        butLoad = QPushButton(self)
        butLoad.setIcon(QIcon(':/download.svg'))
        butLoad.setIconSize(q_icon_size)
        butLoad.setToolTip("Reload coefficients.")

        butClear = QPushButton(self)
        butClear.setIcon(QIcon(':/trash.svg'))
        butClear.setIconSize(q_icon_size)
        butClear.setToolTip("Clear all entries.")

        self.butClipboard = QPushButton(self)
        self.butClipboard.setIcon(QIcon(':/clipboard.svg'))
        self.butClipboard.setIconSize(q_icon_size)
        self.butClipboard.setToolTip(
            "<span>Copy table to clipboard, selected items are copied as "
            "displayed. When nothing is selected, the whole table "
            "is copied with full precision in decimal format. </span>")

        layHButtonsCoeffs1 = QHBoxLayout()
        layHButtonsCoeffs1.addWidget(butAddCells)
        layHButtonsCoeffs1.addWidget(butDelCells)
        layHButtonsCoeffs1.addWidget(butQuant)
        layHButtonsCoeffs1.addWidget(butClear)
        layHButtonsCoeffs1.addWidget(self.butSave)
        layHButtonsCoeffs1.addWidget(butLoad)
        layHButtonsCoeffs1.addWidget(self.butClipboard)
        layHButtonsCoeffs1.addWidget(self.cmbFilterType)
        layHButtonsCoeffs1.addStretch()
        #---------------------------------------------------------

        butSetZero = QPushButton("= 0", self)
        butSetZero.setToolTip(
            "<span>Set selected coefficients = 0 with a magnitude &lt; &epsilon;. "
            "When nothing is selected, test the whole table.</span>")
        butSetZero.setIconSize(q_icon_size)

        self.lblEps = QLabel(self)
        self.lblEps.setText("for b, a <")

        self.ledSetEps = QLineEdit(self)
        self.ledSetEps.setToolTip("Specify eps value.")
        self.ledSetEps.setText(str(1e-6))

        self.lblWIWF = QLabel("W = ")
        self.lblWIWF.setFont(self.bifont)
        self.lblQOvfl = QLabel("Ovfl.:")
        self.lblQuant = QLabel("Quant.:")

        self.ledW = QLineEdit(self)
        self.ledW.setToolTip("Specify wordlength.")
        self.ledW.setText("16")
        self.ledW.setMaxLength(2)  # maximum of 2 digits
        self.ledW.setFixedWidth(30)  # width of lineedit in points(?)

        self.ledWI = QLineEdit(self)
        self.ledWI.setToolTip("Specify number of integer bits.")
        self.ledWI.setText("0")
        self.ledWI.setMaxLength(2)  # maximum of 2 digits
        self.ledWI.setFixedWidth(30)  # width of lineedit in points(?)

        self.lblDot = QLabel(self)
        self.lblDot.setText(".")

        self.ledWF = QLineEdit(self)
        self.ledWF.setToolTip("Specify number of fractional bits.")
        self.ledWF.setText("15")
        self.ledWF.setMaxLength(2)  # maximum of 2 digits
        #        self.ledWF.setFixedWidth(30) # width of lineedit in points(?)
        self.ledWF.setMaximumWidth(30)

        self.lblScale = QLabel("Scale = ", self)
        self.ledScale = QLineEdit(self)
        self.ledScale.setToolTip(
            "Set the scale for converting float to fixpoint representation.")
        self.ledScale.setText(str(1))

        self.lblLSBtxt = QLabel(self)
        self.lblLSBtxt.setText("LSB =")
        self.lblLSBtxt.setFont(self.bifont)
        self.lblLSB = QLabel(self)

        self.lblMSBtxt = QLabel(self)
        self.lblMSBtxt.setText("MSB =")
        self.lblMSBtxt.setFont(self.bifont)
        self.lblMSB = QLabel(self)

        self.cmbQQuant = QComboBox(self)
        qQuant = ['none', 'round', 'fix', 'floor']
        self.cmbQQuant.addItems(qQuant)
        self.cmbQQuant.setCurrentIndex(1)  # 'round'
        self.cmbQQuant.setToolTip("Select the kind of quantization.")

        self.cmbQOvfl = QComboBox(self)
        qOvfl = ['none', 'wrap', 'sat']
        self.cmbQOvfl.addItems(qOvfl)
        self.cmbQOvfl.setCurrentIndex(2)  # 'sat'
        self.cmbQOvfl.setToolTip("Select overflow behaviour.")

        # ComboBox size is adjusted automatically to fit the longest element
        self.cmbQQuant.setSizeAdjustPolicy(QComboBox.AdjustToContents)
        self.cmbQOvfl.setSizeAdjustPolicy(QComboBox.AdjustToContents)

        self.clipboard = QApplication.clipboard()

        # ============== UI Layout =====================================

        layHButtonsCoeffs2 = QHBoxLayout()
        layHButtonsCoeffs2.addWidget(butSetZero)
        layHButtonsCoeffs2.addWidget(self.lblEps)
        layHButtonsCoeffs2.addWidget(self.ledSetEps)
        layHButtonsCoeffs2.addStretch()

        layHCoeffs_W = QHBoxLayout()
        layHCoeffs_W.addWidget(self.lblWIWF)
        layHCoeffs_W.addWidget(self.ledW)
        layHCoeffs_W.addWidget(self.ledWI)
        layHCoeffs_W.addWidget(self.lblDot)
        layHCoeffs_W.addWidget(self.ledWF)
        layHCoeffs_W.addWidget(self.lblScale)
        layHCoeffs_W.addWidget(self.ledScale)

        layHCoeffs_W.addStretch()

        layHCoeffsQOpt = QHBoxLayout()
        layHCoeffsQOpt.addWidget(self.lblQOvfl)
        layHCoeffsQOpt.addWidget(self.cmbQOvfl)
        layHCoeffsQOpt.addWidget(self.lblQuant)
        layHCoeffsQOpt.addWidget(self.cmbQQuant)
        layHCoeffsQOpt.addStretch()

        layHCoeffs_MSB_LSB = QHBoxLayout()

        layHCoeffs_MSB_LSB.addWidget(self.lblMSBtxt)
        layHCoeffs_MSB_LSB.addWidget(self.lblMSB)
        layHCoeffs_MSB_LSB.addStretch()
        layHCoeffs_MSB_LSB.addWidget(self.lblLSBtxt)
        layHCoeffs_MSB_LSB.addWidget(self.lblLSB)
        layHCoeffs_MSB_LSB.addStretch()

        layVButtonsQ = QVBoxLayout()
        layVButtonsQ.addLayout(layHCoeffs_W)
        layVButtonsQ.addLayout(layHCoeffsQOpt)
        layVButtonsQ.addLayout(layHCoeffs_MSB_LSB)
        layVButtonsQ.setContentsMargins(0, 5, 0, 0)

        # This frame encompasses the Quantization Settings
        self.frmQSettings = QFrame(self)
        self.frmQSettings.setLayout(layVButtonsQ)

        layVBtns = QVBoxLayout()
        layVBtns.addLayout(layHDisplay)
        layVBtns.addLayout(layHButtonsCoeffs1)
        layVBtns.addLayout(layHButtonsCoeffs2)
        layVBtns.addWidget(self.frmQSettings)

        # This frame encompasses all the buttons
        frmMain = QFrame(self)
        frmMain.setLayout(layVBtns)

        layVMain = QVBoxLayout()
        layVMain.setAlignment(
            Qt.AlignTop)  # this affects only the first widget (intended here)
        layVMain.addWidget(frmMain)
        layVMain.addWidget(self.tblCoeff)
        layVMain.setContentsMargins(*params['wdg_margins'])
        #        layVMain.addStretch(1)
        self.setLayout(layVMain)

        # ============== Signals & Slots ================================
        #        self.tblCoeff.itemActivated.connect(self.save_coeffs) # nothing happens
        # this works but fires multiple times _and_ fires every time cell is
        # changed by program as well!
        #        self.tblCoeff.itemChanged.connect(self.save_coeffs)
        #        self.tblCoeff.selectionModel().currentChanged.connect(self.save_coeffs)
        self.butEnable.clicked.connect(self._refresh_table)
        self.spnRound.editingFinished.connect(self._refresh_table)
        self.chkRadixPoint.clicked.connect(self._radix_point)
        self.butClipboard.clicked.connect(self._copy_to_clipboard)

        self.cmbFilterType.currentIndexChanged.connect(self._filter_type)

        butDelCells.clicked.connect(self._delete_cells)
        butAddCells.clicked.connect(self._add_cells)
        butLoad.clicked.connect(self.load_dict)
        self.butSave.clicked.connect(self._save_entries)
        butClear.clicked.connect(self._clear_table)
        butSetZero.clicked.connect(self._set_coeffs_zero)

        # refresh table after storing new settings
        self.cmbFormat.currentIndexChanged.connect(self._refresh_table)
        self.cmbQOvfl.currentIndexChanged.connect(self._refresh_table)
        self.cmbQQuant.currentIndexChanged.connect(self._refresh_table)
        self.ledWF.editingFinished.connect(self._WIWF_changed)
        self.ledWI.editingFinished.connect(self._WIWF_changed)
        self.ledW.editingFinished.connect(self._W_changed)

        self.ledScale.editingFinished.connect(self._refresh_table)

        butQuant.clicked.connect(self.quant_coeffs)

        self.myQ = fix.Fixed(
            fb.fil[0]["q_coeff"])  # initialize fixpoint object
        self.load_dict(
        )  # initialize + refresh table with default values from filter dict
        # TODO: this needs to be optimized - self._refresh is being called in both routines
        self._radix_point()