コード例 #1
0
ファイル: disc_dev.cs プロジェクト: kwanboy/mcs
 /* Use quick charge if specified. */
 double DSD_555_ASTBL_T_RC_CHARGE(discrete_555_desc info)
 {
     return((DSD_555_ASTBL__R1 + (((info.options & DISC_555_ASTABLE_HAS_FAST_CHARGE_DIODE) != 0) ? 0 : DSD_555_ASTBL__R2)) * DSD_555_ASTBL__C);
 }
コード例 #2
0
ファイル: disc_dev.cs プロジェクト: kwanboy/mcs
        //DISCRETE_CLASS_DESTRUCTOR(_name)                                    \
        //~discrete_dsd_555_astbl_node() { }


        // discrete_base_node

        //DISCRETE_RESET(dsd_555_astbl)
        public override void reset()
        {
            discrete_555_desc info = (discrete_555_desc)this.custom_data();  //DISCRETE_DECLARE_INFO(discrete_555_desc)

            m_use_ctrlv   = (this.input_is_node() >> 4) & 1;
            m_output_type = info.options & DISC_555_OUT_MASK;

            /* Use the defaults or supplied values. */
            m_v_out_high = (info.v_out_high == DEFAULT_555_HIGH) ? info.v_pos - 1.2 : info.v_out_high;

            /* setup v_charge or node */
            m_v_charge_node = m_device.node_output_ptr((int)info.v_charge);
            if (m_v_charge_node == null)
            {
                m_v_charge = (info.v_charge == DEFAULT_555_CHARGE) ? info.v_pos : info.v_charge;

                if ((info.options & DISC_555_ASTABLE_HAS_FAST_CHARGE_DIODE) != 0)
                {
                    m_v_charge -= 0.5;
                }
            }

            if ((DSD_555_ASTBL__CTRLV != -1) && m_use_ctrlv == 0)
            {
                /* Setup based on supplied Control Voltage static value */
                m_threshold = DSD_555_ASTBL__CTRLV;
                m_trigger   = DSD_555_ASTBL__CTRLV / 2.0;
            }
            else
            {
                /* Setup based on v_pos power source */
                m_threshold = info.v_pos * 2.0 / 3.0;
                m_trigger   = info.v_pos / 3.0;
            }

            /* optimization if none of the values are nodes */
            m_has_rc_nodes = 0;
            if ((this.input_is_node() & DSD_555_ASTBL_RC_MASK) != 0)
            {
                m_has_rc_nodes = 1;
            }
            else
            {
                m_t_rc_bleed     = DSD_555_ASTBL_T_RC_BLEED;
                m_exp_bleed      = RC_CHARGE_EXP(m_t_rc_bleed);
                m_t_rc_charge    = DSD_555_ASTBL_T_RC_CHARGE(info);
                m_exp_charge     = RC_CHARGE_EXP(m_t_rc_charge);
                m_t_rc_discharge = DSD_555_ASTBL_T_RC_DISCHARGE;
                m_exp_discharge  = RC_CHARGE_EXP(m_t_rc_discharge);
            }

            m_output_is_ac = info.options & DISC_555_OUT_AC;
            /* Calculate DC shift needed to make squarewave waveform AC */
            m_ac_shift = (m_output_is_ac != 0) ? -m_v_out_high / 2.0 : 0;

            m_flip_flop   = 1;
            m_cap_voltage = 0;

            /* Step to set the output */
            this.step();
        }
コード例 #3
0
ファイル: disc_dev.cs プロジェクト: kwanboy/mcs
        //DISCRETE_STEP(dsd_555_astbl)
        public void step()
        {
            discrete_555_desc info = (discrete_555_desc)this.custom_data();  //DISCRETE_DECLARE_INFO(discrete_555_desc)

            int     count_f = 0;
            int     count_r = 0;
            double  dt;                         /* change in time */
            double  x_time = 0;                 /* time since change happened */
            double  v_cap = m_cap_voltage;      /* Current voltage on capacitor, before dt */
            double  v_cap_next = 0;             /* Voltage on capacitor, after dt */
            double  v_charge, exponent = 0;
            uint8_t flip_flop       = (uint8_t)m_flip_flop;
            uint8_t update_exponent = 0;
            double  v_out           = 0.0;

            /* put commonly used stuff in local variables for speed */
            double threshold = m_threshold;
            double trigger   = m_trigger;

            if (DSD_555_ASTBL__RESET)
            {
                /* We are in RESET */
                set_output(0, 0);
                m_flip_flop   = 1;
                m_cap_voltage = 0;
                return;
            }

            /* Check: if the Control Voltage node is connected. */
            if (m_use_ctrlv != 0)
            {
                /* If CV is less then .25V, the circuit will oscillate way out of range.
                 * So we will just ignore it when it happens. */
                if (DSD_555_ASTBL__CTRLV < .25)
                {
                    return;
                }
                /* If it is a node then calculate thresholds based on Control Voltage */
                threshold = DSD_555_ASTBL__CTRLV;
                trigger   = DSD_555_ASTBL__CTRLV / 2.0;
                /* Since the thresholds may have changed we need to update the FF */
                if (v_cap >= threshold)
                {
                    flip_flop = 0;
                    count_f++;
                }
                else
                if (v_cap <= trigger)
                {
                    flip_flop = 1;
                    count_r++;
                }
            }

            /* get the v_charge and update each step if it is a node */
            if (m_v_charge_node != null)
            {
                v_charge = m_v_charge_node[0];  // v_charge = *m_v_charge_node;
                if ((info.options & DISC_555_ASTABLE_HAS_FAST_CHARGE_DIODE) != 0)
                {
                    v_charge -= 0.5;
                }
            }
            else
            {
                v_charge = m_v_charge;
            }


            /* Calculate future capacitor voltage.
             * ref@ http://www.physics.rutgers.edu/ugrad/205/capacitance.html
             * The formulas from the ref pages have been modified to reflect that we are stepping the change.
             * dt = time of sample (1/sample frequency)
             * VC = Voltage across capacitor
             * VC' = Future voltage across capacitor
             * Vc = Voltage change
             * Vr = is the voltage across the resistor.  For charging it is Vcc - VC.  Discharging it is VC - 0.
             * R = R1+R2 (for charging)  R = R2 for discharging.
             * Vc = Vr*(1-exp(-dt/(R*C)))
             * VC' = VC + Vc (for charging) VC' = VC - Vc for discharging.
             *
             * We will also need to calculate the amount of time we overshoot the thresholds
             * dt = amount of time we overshot
             * Vc = voltage change overshoot
             * dt = R*C(log(1/(1-(Vc/Vr))))
             */

            dt = this.sample_time();

            /* Sometimes a switching network is used to setup the capacitance.
             * These may select no capacitor, causing oscillation to stop.
             */
            if (DSD_555_ASTBL__C == 0)
            {
                flip_flop = 1;
                /* The voltage goes high because the cap circuit is open. */
                v_cap_next    = v_charge;
                v_cap         = v_charge;
                m_cap_voltage = 0;
            }
            else
            {
                /* Update charge contstants and exponents if nodes changed */
                if (m_has_rc_nodes != 0 && (DSD_555_ASTBL__R1 != m_last_r1 || DSD_555_ASTBL__C != m_last_c || DSD_555_ASTBL__R2 != m_last_r2))
                {
                    m_t_rc_bleed     = DSD_555_ASTBL_T_RC_BLEED;
                    m_t_rc_charge    = DSD_555_ASTBL_T_RC_CHARGE(info);
                    m_t_rc_discharge = DSD_555_ASTBL_T_RC_DISCHARGE;
                    m_exp_bleed      = RC_CHARGE_EXP(m_t_rc_bleed);
                    m_exp_charge     = RC_CHARGE_EXP(m_t_rc_charge);
                    m_exp_discharge  = RC_CHARGE_EXP(m_t_rc_discharge);
                    m_last_r1        = DSD_555_ASTBL__R1;
                    m_last_r2        = DSD_555_ASTBL__R2;
                    m_last_c         = DSD_555_ASTBL__C;
                }
                /* Keep looping until all toggling in time sample is used up. */
                do
                {
                    if (flip_flop != 0)
                    {
                        if (DSD_555_ASTBL__R1 == 0)
                        {
                            /* Oscillation disabled because there is no longer any charge resistor. */
                            /* Bleed the cap due to circuit losses. */
                            if (update_exponent != 0)
                            {
                                exponent = RC_CHARGE_EXP_DT(m_t_rc_bleed, dt);
                            }
                            else
                            {
                                exponent = m_exp_bleed;
                            }
                            v_cap_next = v_cap - (v_cap * exponent);
                            dt         = 0;
                        }
                        else
                        {
                            /* Charging */
                            if (update_exponent != 0)
                            {
                                exponent = RC_CHARGE_EXP_DT(m_t_rc_charge, dt);
                            }
                            else
                            {
                                exponent = m_exp_charge;
                            }
                            v_cap_next = v_cap + ((v_charge - v_cap) * exponent);
                            dt         = 0;

                            /* has it charged past upper limit? */
                            if (v_cap_next >= threshold)
                            {
                                /* calculate the overshoot time */
                                dt         = m_t_rc_charge * Math.Log(1.0 / (1.0 - ((v_cap_next - threshold) / (v_charge - v_cap))));
                                x_time     = dt;
                                v_cap_next = threshold;
                                flip_flop  = 0;
                                count_f++;
                                update_exponent = 1;
                            }
                        }
                    }
                    else
                    {
                        /* Discharging */
                        if (DSD_555_ASTBL__R2 != 0)
                        {
                            if (update_exponent != 0)
                            {
                                exponent = RC_CHARGE_EXP_DT(m_t_rc_discharge, dt);
                            }
                            else
                            {
                                exponent = m_exp_discharge;
                            }
                            v_cap_next = v_cap - (v_cap * exponent);
                            dt         = 0;
                        }
                        else
                        {
                            /* no discharge resistor so we immediately discharge */
                            v_cap_next = trigger;
                        }

                        /* has it discharged past lower limit? */
                        if (v_cap_next <= trigger)
                        {
                            /* calculate the overshoot time */
                            if (v_cap_next < trigger)
                            {
                                dt = m_t_rc_discharge * Math.Log(1.0 / (1.0 - ((trigger - v_cap_next) / v_cap)));
                            }
                            x_time     = dt;
                            v_cap_next = trigger;
                            flip_flop  = 1;
                            count_r++;
                            update_exponent = 1;
                        }
                    }
                    v_cap = v_cap_next;
                } while (dt != 0);

                m_cap_voltage = v_cap;
            }

            /* Convert last switch time to a ratio */
            x_time = x_time / this.sample_time();

            switch (m_output_type)
            {
            case DISC_555_OUT_SQW:
                if (count_f + count_r >= 2)
                {
                    /* force at least 1 toggle */
                    v_out = m_flip_flop != 0 ? 0 : m_v_out_high;
                }
                else
                {
                    v_out = flip_flop * m_v_out_high;
                }
                v_out += m_ac_shift;
                break;

            case DISC_555_OUT_CAP:
                v_out = v_cap;
                /* Fake it to AC if needed */
                if (m_output_is_ac != 0)
                {
                    v_out -= threshold * 3.0 / 4.0;
                }
                break;

            case DISC_555_OUT_ENERGY:
                if (x_time == 0)
                {
                    x_time = 1.0;
                }
                v_out  = m_v_out_high * (flip_flop != 0 ? x_time : (1.0 - x_time));
                v_out += m_ac_shift;
                break;

            case DISC_555_OUT_LOGIC_X:
                v_out = flip_flop + x_time;
                break;

            case DISC_555_OUT_COUNT_F_X:
                v_out = count_f != 0 ? count_f + x_time : count_f;
                break;

            case DISC_555_OUT_COUNT_R_X:
                v_out = count_r != 0 ? count_r + x_time : count_r;
                break;

            case DISC_555_OUT_COUNT_F:
                v_out = count_f;
                break;

            case DISC_555_OUT_COUNT_R:
                v_out = count_r;
                break;
            }
            set_output(0, v_out);
            m_flip_flop = flip_flop;
        }