Beispiel #1
0
        //DISCRETE_CLASS_DESTRUCTOR(_name)
        //~discrete_dst_sallen_key_node() { }


        // discrete_base_node

        //DISCRETE_RESET(dst_sallen_key)
        public override void reset()
        {
            discrete_op_amp_filt_info info = (discrete_op_amp_filt_info)custom_data();  //DISCRETE_DECLARE_INFO(discrete_op_amp_filt_info);

            double freq = 0;
            double q    = 0;

            switch ((int)DST_SALLEN_KEY__TYPE)
            {
            case DISC_SALLEN_KEY_LOW_PASS:
                freq = 1.0 / (2.0 * M_PI * std.sqrt(info.c1 * info.c2 * info.r1 * info.r2));
                q    = std.sqrt(info.c1 * info.c2 * info.r1 * info.r2) / (info.c2 * (info.r1 + info.r2));
                break;

            default:
                fatalerror("Unknown sallen key filter type\n");
                break;
            }

            calculate_filter2_coefficients(this, freq, 1.0 / q, DISC_FILTER_LOWPASS, ref m_fc);
            set_output(0, 0);
        }
Beispiel #2
0
        //DISCRETE_STEP(dst_op_amp_filt)
        public void step()
        {
            //DISCRETE_DECLARE_INFO(discrete_op_amp_filt_info)
            discrete_op_amp_filt_info info = (discrete_op_amp_filt_info)custom_data();


            double v_out = 0;

            double i;
            double v = 0;

            if (DST_OP_AMP_FILT__ENABLE() != 0)
            {
                if (m_is_norton != 0)
                {
                    v = DST_OP_AMP_FILT__INP1() - OP_AMP_NORTON_VBE;
                    if (v < 0)
                    {
                        v = 0;
                    }
                }
                else
                {
                    /* Millman the input voltages. */
                    i = m_iFixed;
                    switch (m_type)
                    {
                    case DISC_OP_AMP_FILTER_IS_LOW_PASS_1_A:
                        i += (DST_OP_AMP_FILT__INP1() - DST_OP_AMP_FILT__INP2()) / info.r1;
                        if (info.r2 != 0)
                        {
                            i += (m_vP - DST_OP_AMP_FILT__INP2()) / info.r2;
                        }
                        if (info.r3 != 0)
                        {
                            i += (m_vN - DST_OP_AMP_FILT__INP2()) / info.r3;
                        }
                        break;

                    default:
                        i += (DST_OP_AMP_FILT__INP1() - m_vRef) / info.r1;
                        if (info.r2 != 0)
                        {
                            i += (DST_OP_AMP_FILT__INP2() - m_vRef) / info.r2;
                        }
                        break;
                    }
                    v = i * m_rTotal;
                }

                switch (m_type)
                {
                case DISC_OP_AMP_FILTER_IS_LOW_PASS_1:
                    m_vC1 += (v - m_vC1) * m_exponentC1;
                    v_out  = m_vC1 * m_gain + info.vRef;
                    break;

                case DISC_OP_AMP_FILTER_IS_LOW_PASS_1_A:
                    m_vC1 += (v - m_vC1) * m_exponentC1;
                    v_out  = m_vC1 * m_gain + DST_OP_AMP_FILT__INP2();
                    break;

                case DISC_OP_AMP_FILTER_IS_HIGH_PASS_1:
                    v_out  = (v - m_vC1) * m_gain + info.vRef;
                    m_vC1 += (v - m_vC1) * m_exponentC1;
                    break;

                case DISC_OP_AMP_FILTER_IS_BAND_PASS_1:
                    v_out  = (v - m_vC2);
                    m_vC2 += (v - m_vC2) * m_exponentC2;
                    m_vC1 += (v_out - m_vC1) * m_exponentC1;
                    v_out  = m_vC1 * m_gain + info.vRef;
                    break;

                case DISC_OP_AMP_FILTER_IS_BAND_PASS_0 | DISC_OP_AMP_IS_NORTON:
                    m_vC1 += (v - m_vC1) * m_exponentC1;
                    m_vC2 += (m_vC1 - m_vC2) * m_exponentC2;
                    v      = m_vC2;
                    v_out  = v - m_vC3;
                    m_vC3 += (v - m_vC3) * m_exponentC3;
                    i      = v_out / m_rTotal;
                    v_out  = (m_iFixed - i) * info.rF;
                    break;

                case DISC_OP_AMP_FILTER_IS_HIGH_PASS_0 | DISC_OP_AMP_IS_NORTON:
                    v_out  = v - m_vC1;
                    m_vC1 += (v - m_vC1) * m_exponentC1;
                    i      = v_out / m_rTotal;
                    v_out  = (m_iFixed - i) * info.rF;
                    break;

                case DISC_OP_AMP_FILTER_IS_BAND_PASS_1M:
                case DISC_OP_AMP_FILTER_IS_BAND_PASS_1M | DISC_OP_AMP_IS_NORTON:
                    v_out = -m_fc.a1 * m_fc.y1 - m_fc.a2 * m_fc.y2 +
                            m_fc.b0 * v + m_fc.b1 * m_fc.x1 + m_fc.b2 * m_fc.x2 +
                            m_vRef;
                    m_fc.x2 = m_fc.x1;
                    m_fc.x1 = v;
                    m_fc.y2 = m_fc.y1;
                    break;
                }

                /* Clip the output to the voltage rails.
                 * This way we get the original distortion in all it's glory.
                 */
                if (v_out > m_vP)
                {
                    v_out = m_vP;
                }
                if (v_out < m_vN)
                {
                    v_out = m_vN;
                }
                m_fc.y1 = v_out - m_vRef;
                set_output(0, v_out);
            }
            else
            {
                set_output(0, 0);
            }
        }
Beispiel #3
0
        //DISCRETE_CLASS_DESTRUCTOR(_name)
        //~discrete_dst_op_amp_filt_node() { }


        // discrete_base_node

        //DISCRETE_RESET(dst_op_amp_filt)
        public override void reset()
        {
            discrete_op_amp_filt_info info = (discrete_op_amp_filt_info)custom_data();  //DISCRETE_DECLARE_INFO(discrete_op_amp_filt_info)

            /* Convert the passed filter type into an int for easy use. */
            m_type      = (int)DST_OP_AMP_FILT__TYPE() & DISC_OP_AMP_FILTER_TYPE_MASK;
            m_is_norton = (int)DST_OP_AMP_FILT__TYPE() & DISC_OP_AMP_IS_NORTON;

            if (m_is_norton != 0)
            {
                m_vRef   = 0;
                m_rTotal = info.r1;
                if (m_type == (DISC_OP_AMP_FILTER_IS_BAND_PASS_0 | DISC_OP_AMP_IS_NORTON))
                {
                    m_rTotal += info.r2 + info.r3;
                }

                /* Setup the current to the + input. */
                m_iFixed = (info.vP - OP_AMP_NORTON_VBE) / info.r4;

                /* Set the output max. */
                m_vP = info.vP - OP_AMP_NORTON_VBE;
                m_vN = info.vN;
            }
            else
            {
                m_vRef = info.vRef;
                /* Set the output max. */
                m_vP = info.vP - OP_AMP_VP_RAIL_OFFSET;
                m_vN = info.vN;

                /* Work out the input resistance.  It is all input and bias resistors in parallel. */
                m_rTotal = 1.0 / info.r1;          /* There has to be an R1.  Otherwise the table is wrong. */
                if (info.r2 != 0)
                {
                    m_rTotal += 1.0 / info.r2;
                }
                if (info.r3 != 0)
                {
                    m_rTotal += 1.0 / info.r3;
                }
                m_rTotal = 1.0 / m_rTotal;

                m_iFixed = 0;

                m_rRatio = info.rF / (m_rTotal + info.rF);
                m_gain   = -info.rF / m_rTotal;
            }

            switch (m_type)
            {
            case DISC_OP_AMP_FILTER_IS_LOW_PASS_1:
            case DISC_OP_AMP_FILTER_IS_LOW_PASS_1_A:
                m_exponentC1 = RC_CHARGE_EXP(info.rF * info.c1);
                m_exponentC2 = 0;
                break;

            case DISC_OP_AMP_FILTER_IS_HIGH_PASS_1:
                m_exponentC1 = RC_CHARGE_EXP(m_rTotal * info.c1);
                m_exponentC2 = 0;
                break;

            case DISC_OP_AMP_FILTER_IS_BAND_PASS_1:
                m_exponentC1 = RC_CHARGE_EXP(info.rF * info.c1);
                m_exponentC2 = RC_CHARGE_EXP(m_rTotal * info.c2);
                break;

            case DISC_OP_AMP_FILTER_IS_BAND_PASS_1M | DISC_OP_AMP_IS_NORTON:
                if (info.r2 == 0)
                {
                    m_rTotal = info.r1;
                }
                else
                {
                    m_rTotal = RES_2_PARALLEL(info.r1, info.r2);
                }

                goto case DISC_OP_AMP_FILTER_IS_BAND_PASS_1M;      //[[fallthrough]];

            case DISC_OP_AMP_FILTER_IS_BAND_PASS_1M:
            {
                double fc   = 1.0 / (2 * M_PI * std.sqrt(m_rTotal * info.rF * info.c1 * info.c2));
                double d    = (info.c1 + info.c2) / std.sqrt(info.rF / m_rTotal * info.c1 * info.c2);
                double gain = -info.rF / m_rTotal * info.c2 / (info.c1 + info.c2);

                calculate_filter2_coefficients(this, fc, d, DISC_FILTER_BANDPASS, ref m_fc);
                m_fc.b0 *= gain;
                m_fc.b1 *= gain;
                m_fc.b2 *= gain;

                if (m_is_norton != 0)
                {
                    m_vRef = (info.vP - OP_AMP_NORTON_VBE) / info.r3 * info.rF;
                }
                else
                {
                    m_vRef = info.vRef;
                }

                break;
            }

            case DISC_OP_AMP_FILTER_IS_BAND_PASS_0 | DISC_OP_AMP_IS_NORTON:
                m_exponentC1 = RC_CHARGE_EXP(RES_2_PARALLEL(info.r1, info.r2 + info.r3 + info.r4) * info.c1);
                m_exponentC2 = RC_CHARGE_EXP(RES_2_PARALLEL(info.r1 + info.r2, info.r3 + info.r4) * info.c2);
                m_exponentC3 = RC_CHARGE_EXP((info.r1 + info.r2 + info.r3 + info.r4) * info.c3);
                break;

            case DISC_OP_AMP_FILTER_IS_HIGH_PASS_0 | DISC_OP_AMP_IS_NORTON:
                m_exponentC1 = RC_CHARGE_EXP(info.r1 * info.c1);
                break;
            }

            /* At startup there is no charge on the caps and output is 0V in relation to vRef. */
            m_vC1  = 0;
            m_vC1b = 0;
            m_vC2  = 0;
            m_vC3  = 0;

            set_output(0, info.vRef);
        }