File indexing completed on 2024-05-05 05:46:11

0001 /***************************************************************************
0002  *   Copyright (C) 2003-2005 by David Saxton                               *
0003  *   david@bluehaze.org                                                    *
0004  *                                                                         *
0005  *   This program is free software; you can redistribute it and/or modify  *
0006  *   it under the terms of the GNU General Public License as published by  *
0007  *   the Free Software Foundation; either version 2 of the License, or     *
0008  *   (at your option) any later version.                                   *
0009  ***************************************************************************/
0010 
0011 #ifndef LOGIC_H
0012 #define LOGIC_H
0013 
0014 #include "element.h"
0015 
0016 #include <QList>
0017 #include <QPointer>
0018 
0019 class Component;
0020 class Pin;
0021 class Simulator;
0022 
0023 typedef QList<QPointer<Pin>> PinList;
0024 
0025 class LogicConfig
0026 {
0027 public:
0028     LogicConfig();
0029 
0030     float risingTrigger;  ///< Trigger on rising edge
0031     float fallingTrigger; ///< Trigger on falling edge
0032     float output;         ///< Output voltage
0033     float highImpedance;  ///< Output impedance when high
0034     float lowImpedance;   ///< Output impedance when low
0035 };
0036 
0037 class CallbackClass
0038 {
0039 };
0040 typedef void (CallbackClass::*CallbackPtr)(bool isHigh);
0041 
0042 // BEGIN Callback2Ptr
0043 
0044 typedef void * Callback2Obj;
0045 typedef void (*Callback2Ptr)(Callback2Obj objV, bool isHigh);
0046 
0047 // END Callback2Ptr
0048 
0049 /**
0050 Use this class for Logic Inputs - this will have infinite impedance.
0051 Use isHigh() will return whether the voltage level at the pin
0052 is high than the predetermined voltage threshold, and setHigh() will make the
0053 output high/low, also according to the predetermined logic type / voltages.
0054 
0055 @short Boolean Logic input
0056 */
0057 class LogicIn : public Element
0058 {
0059 public:
0060     LogicIn(LogicConfig config);
0061     ~LogicIn() override;
0062 
0063     Type type() const override
0064     {
0065         return Element_LogicIn;
0066     }
0067     void setElementSet(ElementSet *c) override;
0068 
0069     /**
0070      * Set logic values from the LogicConfig.
0071      */
0072     virtual void setLogic(LogicConfig config);
0073     /**
0074      * Check if the input state has changed, to see if we need to callback.
0075      */
0076     void check();
0077     /**
0078      * Returns whether the pin is 'high', as defined for the logic type
0079      * Note: this is defined as the voltage on the pin, as opposed to what the
0080      * state was set to (the two are not necessarily the same).
0081      */
0082     bool isHigh() const
0083     {
0084         return m_bLastState;
0085     }
0086     /**
0087      * When the logic state on this LogicIn changes, the function passed in this
0088      * function will be called. At most one Callback can be added per LogicIn.
0089      */
0090 //     void setCallback(CallbackClass *object, CallbackPtr func);
0091 
0092     void setCallback2(Callback2Ptr fun, Callback2Obj obj);
0093 
0094     /**
0095      * Reads the LogicConfig values in from KTLConfig, and returns them in a
0096      * nice object form.
0097      */
0098     static LogicConfig getConfig();
0099     /**
0100      * If this belongs to a logic chain, then this will be called from the chain.
0101      */
0102     void setLastState(bool state)
0103     {
0104         m_bLastState = state;
0105     }
0106     /**
0107      * Returns a pointer to the next LogicIn in the chain.
0108      */
0109     LogicIn *nextLogic() const
0110     {
0111         return m_pNextLogic;
0112     }
0113     /**
0114      * Sets the next LogicIn in the chain.
0115      */
0116     void setNextLogic(LogicIn *next)
0117     {
0118         m_pNextLogic = next;
0119     }
0120     /**
0121      * Calls the callback function, if there is one.
0122      */
0123     void callCallback()
0124     {
0125 //         if (m_pCallbackFunction)
0126 //             (m_pCallbackObject->*m_pCallbackFunction)(m_bLastState);
0127         if (m_pCallback2Func)
0128             m_pCallback2Func(m_pCallback2Obj, m_bLastState);
0129     }
0130 
0131 protected:
0132     void updateCurrents() override;
0133     void add_initial_dc() override;
0134 
0135     // 2022.06.13 - fix this crap NO FUNCTION POINTERS
0136     // v1 callbacks, deprecated
0137 //     CallbackPtr m_pCallbackFunction;
0138 //     CallbackClass *m_pCallbackObject;
0139     // v2 callbacks, a bit less hacky than v1
0140     Callback2Ptr m_pCallback2Func;
0141     Callback2Obj m_pCallback2Obj;
0142 
0143     bool m_bLastState;
0144     LogicIn *m_pNextLogic;
0145     LogicConfig m_config;
0146 };
0147 
0148 /**
0149 @short Logic output/input
0150 */
0151 class LogicOut : public LogicIn
0152 {
0153 public:
0154     LogicOut(LogicConfig config, bool _high);
0155     ~LogicOut() override;
0156 
0157     void setLogic(LogicConfig config) override;
0158     void setElementSet(ElementSet *c) override;
0159     Type type() const override
0160     {
0161         return Element_LogicOut;
0162     }
0163 
0164     /**
0165      * Call this function to override the logic-high output impedance as set by
0166      * the user. Once set, the impedance will not be changed by the user
0167      * updating the config; only by subsequent calls to this function.
0168      */
0169     void setOutputHighConductance(double g);
0170     /**
0171      * Call this function to override the logic-low output impedance as set by
0172      * the user. Once set, the impedance will not be changed by the user
0173      * updating the config; only by subsequent calls to this function.
0174      */
0175     void setOutputLowConductance(double g);
0176     /**
0177      * Call this function to override the logic out voltage as set by the
0178      * user. Once set, the impedance will not be changed by the user
0179      * updating the config; only by subsequent calls to this function.
0180      */
0181     void setOutputHighVoltage(double v);
0182     /**
0183      * Returns the voltage that this will output when high.
0184      */
0185     double outputHighVoltage() const
0186     {
0187         return m_vHigh;
0188     }
0189     /**
0190      * Sets the pin to be high/low
0191      */
0192     void setHigh(bool high);
0193     /**
0194      * @returns the state that this is outputting (regardless of voltage level on logic)
0195      */
0196     bool outputState() const
0197     {
0198         return b_state;
0199     }
0200     /**
0201      * Set whether or not this LogicOut is the head of a LogicChain (controls
0202      * itself and a bunch of LogicIns).
0203      */
0204     void setUseLogicChain(bool use);
0205     /**
0206      * When a LogicOut configured as the start of a LogicChain changes start, it
0207      * appends a pointer to itself to the list of change LogicOut, starting from
0208      * the Simulator. This functions enables appending the next changed LogicOut
0209      * to this one.
0210      */
0211     void setNextChanged(LogicOut *logicOut, unsigned char chain)
0212     {
0213         m_pNextChanged[chain] = logicOut;
0214     }
0215     /**
0216      * To avoid a pointer to this LogicOut being added twice in one
0217      * iteration due to the state changing twice, this LogicOut sets an
0218      * added flag to true after adding it to the list of changed. The flag
0219      * must be reset to false with this function (done by Simulator).
0220      */
0221     void setCanAddChanged(bool canAdd)
0222     {
0223         m_bCanAddChanged = canAdd;
0224     }
0225     /**
0226      * Returns the next LogicOut that has changed, when configured as the start
0227      * of a LogicChain.
0228      * @see setNextChanged
0229      */
0230     LogicOut *nextChanged(unsigned char chain) const
0231     {
0232         return m_pNextChanged[chain];
0233     }
0234     PinList pinList;
0235     PinList::iterator pinListBegin;
0236     PinList::iterator pinListEnd;
0237 
0238 protected:
0239     void configChanged();
0240     void updateCurrents() override;
0241     void add_initial_dc() override;
0242 
0243     // Pre-initalized levels from config
0244     double m_gHigh;
0245     double m_gLow;
0246     double m_vHigh;
0247 
0248     // Whether to use the user-defined logic values
0249     bool m_bOutputHighConductanceConst;
0250     bool m_bOutputLowConductanceConst;
0251     bool m_bOutputHighVoltageConst;
0252 
0253     double m_g_out;
0254     double m_v_out;
0255     double m_old_g_out;
0256     double m_old_v_out;
0257     bool b_state;
0258     bool m_bCanAddChanged;
0259     LogicOut *m_pNextChanged[2];
0260     Simulator *m_pSimulator;
0261     bool m_bUseLogicChain;
0262 };
0263 
0264 #endif