void PyRun::trigger(const Eref& e, double input) { if (!runcompiled_){ return; } if (mode_ == 1){ return; } PyObject * value = PyDict_GetItemString(locals_, inputvar_.c_str()); if (value){ Py_DECREF(value); } value = PyFloat_FromDouble(input); if (!value && PyErr_Occurred()){ PyErr_Print(); } if (PyDict_SetItemString(locals_, inputvar_.c_str(), value)){ PyErr_Print(); } PyEval_EvalCode(runcompiled_, globals_, locals_); if (PyErr_Occurred()){ PyErr_Print (); } value = PyDict_GetItemString(locals_, outputvar_.c_str()); if (value){ double output = PyFloat_AsDouble(value); if (PyErr_Occurred()){ PyErr_Print (); } else { outputOut()->send(e, output); } } }
void DiffAmp::reinit(const Eref& e, ProcPtr p) { // What is the right thing to do?? Should we actually do a process step?? output_ = 0.0; plus_ = 0.0; minus_ = 0.0; outputOut()->send(e, output_); }
void PulseGen::reinit(const Eref& e, ProcPtr p) { trigTime_ = -1; prevInput_ = 0; output_ = baseLevel_; input_ = 0; outputOut()->send(e, output_); }
void RC::process(const Eref& e, const ProcPtr proc ) { double sum_inject_prev = inject_ + msg_inject_; double sum_inject = inject_ + msg_inject_; double dVin = (sum_inject - sum_inject_prev) * resistance_; double Vin = sum_inject * resistance_; state_ = Vin + dVin - dVin / dt_tau_ + (state_ - Vin + dVin / dt_tau_) * exp_; sum_inject_prev = sum_inject; msg_inject_ = 0.0; outputOut()->send(e, state_); }
void RC::reinit(const Eref& e, const ProcPtr proc) { dt_tau_ = proc->dt / (resistance_ * capacitance_); state_ = v0_; if (dt_tau_ > 1e-15){ exp_ = exp(-dt_tau_); } else {// use approximation exp_ = 1 - dt_tau_; } msg_inject_ = 0.0; outputOut()->send(e, state_); }
void PyRun::run(const Eref&e, string statement) { PyRun_SimpleString(statement.c_str()); PyObject * value = PyDict_GetItemString(locals_, outputvar_.c_str()); if (value){ double output = PyFloat_AsDouble(value); if (PyErr_Occurred()){ PyErr_Print (); } else { outputOut()->send(e, output); } } }
void DiffAmp::process(const Eref& e, ProcPtr p) { double output = gain_ * (plus_ - minus_); plus_ = 0.0; minus_ = 0.0; if ( output > saturation_ ) { output = saturation_; } if ( output < -saturation_ ) { output = -saturation_; } output_ = output; outputOut()->send(e, output_); }
void PIDController::reinit(const Eref& e, ProcPtr proc ) { if ( tau_i_ <= 0.0 ){ tau_i_ = proc->dt; } if ( tau_d_ < 0.0 ){ tau_d_ = proc->dt / 4; } sensed_ = 0.0; output_ = 0; error_ = 0; e_previous_ = error_; e_integral_ = 0; e_derivative_ = 0; outputOut()->send(e, output_); }
void PIDController::process(const Eref& e, ProcPtr proc ) { double dt = proc->dt; e_previous_ = error_; error_ = command_ - sensed_; e_integral_ += 0.5 * (error_ + e_previous_) * dt; e_derivative_ = (error_ - e_previous_) / dt; output_ = gain_ * (error_ + e_integral_ / tau_i_ + e_derivative_ * tau_d_); if (output_ > saturation_){ output_ = saturation_; e_integral_ -= 0.5 * (error_ + e_previous_) * dt; } else if (output_ < -saturation_){ output_ = -saturation_; e_integral_ -= 0.5 * (error_ + e_previous_) * dt; } outputOut()->send(e, output_); }
void PyRun::process(const Eref & e, ProcPtr p) { // PyRun_String(runstr_.c_str(), 0, globals_, locals_); // PyRun_SimpleString(runstr_.c_str()); if (!runcompiled_ || mode_ == 2){ return; } PyEval_EvalCode(runcompiled_, globals_, locals_); if (PyErr_Occurred()){ PyErr_Print (); } PyObject * value = PyDict_GetItemString(locals_, outputvar_.c_str()); if (value){ double output = PyFloat_AsDouble(value); if (PyErr_Occurred()){ PyErr_Print (); } else { outputOut()->send(e, output); } } }
const Cinfo* DiffAmp::initCinfo() { static ValueFinfo<DiffAmp, double> gain( "gain", "Gain of the amplifier. The output of the amplifier is the difference" " between the totals in plus and minus inputs multiplied by the" " gain. Defaults to 1" , &DiffAmp::setGain, &DiffAmp::getGain); static ValueFinfo<DiffAmp, double > saturation( "saturation", "Saturation is the bound on the output. If output goes beyond the +/-" "saturation range, it is truncated to the closer of +saturation and" " -saturation. Defaults to the maximum double precision floating point" " number representable on the system." , &DiffAmp::setSaturation, &DiffAmp::getSaturation); static ReadOnlyValueFinfo<DiffAmp, double> output( "outputValue", "Output of the amplifier, i.e. gain * (plus - minus)." , &DiffAmp::getOutput); /////////////////////////////////////////////////////////////// // Dest messages /////////////////////////////////////////////////////////////// static DestFinfo gainIn( "gainIn", "Destination message to control gain dynamically.", new OpFunc1<DiffAmp, double> (&DiffAmp::setGain)); static DestFinfo plusIn( "plusIn", "Positive input terminal of the amplifier. All the messages connected" " here are summed up to get total positive input.", new OpFunc1<DiffAmp, double> (&DiffAmp::plusFunc)); static DestFinfo minusIn( "minusIn", "Negative input terminal of the amplifier. All the messages connected" " here are summed up to get total positive input.", new OpFunc1<DiffAmp, double> (&DiffAmp::minusFunc)); /////////////////////////////////////////////////////////////////// // Shared messages /////////////////////////////////////////////////////////////////// static DestFinfo process( "process", "Handles process call, updates internal time stamp.", new ProcOpFunc< DiffAmp >( &DiffAmp::process ) ); static DestFinfo reinit( "reinit", "Handles reinit call.", new ProcOpFunc< DiffAmp >( &DiffAmp::reinit ) ); static Finfo* processShared[] = { &process, &reinit }; static SharedFinfo proc( "proc", "This is a shared message to receive Process messages " "from the scheduler objects." "The first entry in the shared msg is a MsgDest " "for the Process operation. It has a single argument, " "ProcInfo, which holds lots of information about current " "time, thread, dt and so on. The second entry is a MsgDest " "for the Reinit operation. It also uses ProcInfo. ", processShared, sizeof( processShared ) / sizeof( Finfo* ) ); static Finfo * diffAmpFinfos[] = { &gain, &saturation, &output, &gainIn, &plusIn, &minusIn, outputOut(), &proc }; static string doc[] = { "Name", "DiffAmp", "Author", "Subhasis Ray, 2008, NCBS", "Description", "A difference amplifier. " "Output is the difference between the total plus inputs and the total " "minus inputs multiplied by gain. Gain can be set statically as a field" " or can be a destination message and thus dynamically determined by the" " output of another object. Same as GENESIS diffamp object." }; static Dinfo<DiffAmp> dinfo; static Cinfo diffAmpCinfo( "DiffAmp", Neutral::initCinfo(), diffAmpFinfos, sizeof(diffAmpFinfos)/sizeof(Finfo*), &dinfo, doc, sizeof(doc)/sizeof(string) ); return &diffAmpCinfo; }
void PulseGen::process(const Eref& e, ProcPtr p ) { double currentTime = p->currTime; double period = width_[0] + delay_[0]; double phase = 0.0; for (unsigned int ii = 1; ii < width_.size() && (width_[ii] > 0.0 || delay_[ii] > 0.0); ++ii){ double incr = delay_[ii] + width_[ii] - width_[ii-1]; if (incr > 0){ period += incr; } } switch (trigMode_){ case PulseGen::FREE_RUN: phase = fmod(currentTime, period); break; case PulseGen::EXT_TRIG: if (input_ == 0){ if (trigTime_ < 0){ phase = period; }else{ phase = currentTime - trigTime_; } } else { if (prevInput_ == 0){ trigTime_ = currentTime; } phase = currentTime - trigTime_; } prevInput_ = input_; break; case PulseGen::EXT_GATE: if(input_ == 0) { phase = period; /* output = baselevel */ } else { /* gate high */ if(prevInput_ == 0) { /* low -> high */ trigTime_ = currentTime; } phase = fmod(currentTime - trigTime_, period); } prevInput_ = input_; break; default: cerr << "ERROR: PulseGen::newProcessFunc( const Conn* , ProcInfo ) - invalid triggerMode - " << trigMode_ << endl; } if (phase >= period){ // we have crossed all pulses output_ = baseLevel_; return; } // go through all pulse positions to check which pulse/interpulse // are we are in and set the output level accordingly for (unsigned int ii = 0; ii < width_.size(); ++ii){ if (phase < delay_[ii]){ // we are in the baseline area - before ii-th pulse output_ = baseLevel_; break; } else if (phase < delay_[ii] + width_[ii]){ // we are inside th ii-th pulse output_ = level_[ii]; break; } phase -= delay_[ii]; } outputOut()->send(e, output_); }
const Cinfo * PyRun::initCinfo() { static ValueFinfo< PyRun, string > runstring( "runString", "String to be executed at each time step.", &PyRun::setRunString, &PyRun::getRunString); static ValueFinfo< PyRun, string > initstring( "initString", "String to be executed at initialization (reinit).", &PyRun::setInitString, &PyRun::getInitString); static ValueFinfo< PyRun, string > inputvar( "inputVar", "Name of local variable in which input balue is to be stored. Default" " is `input_` (to avoid conflict with Python's builtin function" " `input`).", &PyRun::setInputVar, &PyRun::getInputVar); static ValueFinfo< PyRun, string > outputvar( "outputVar", "Name of local variable for storing output. Default is `output`", &PyRun::setOutputVar, &PyRun::getOutputVar); static ValueFinfo< PyRun, int > mode( "mode", "Flag to indicate whether runString should be executed for both trigger and process, or one of them", &PyRun::setMode, &PyRun::getMode); // static ValueFinfo< PyRun, PyObject* > globals( // "globals", // "Global environment dict", // &PyRun::setGlobals, // &PyRun::getGlobals); // static ValueFinfo< PyRun, PyObject* > locals( // "locals", // "Local environment dict", // &PyRun::setLocals, // &PyRun::getLocals); static DestFinfo trigger( "trigger", "Executes the current runString whenever a message arrives. It stores" " the incoming value in local variable named" " `input_`, which can be used in the" " `runString` (the underscore is added to avoid conflict with Python's" " builtin function `input`). If debug is True, it prints the input" " value.", new EpFunc1< PyRun, double >(&PyRun::trigger)); static DestFinfo run( "run", "Runs a specified string. Does not modify existing run or init strings.", new EpFunc1< PyRun, string >(&PyRun::run)); static DestFinfo process( "process", "Handles process call. Runs the current runString.", new ProcOpFunc< PyRun >(&PyRun::process)); static DestFinfo reinit( "reinit", "Handles reinit call. Runs the current initString.", new ProcOpFunc< PyRun >( &PyRun::reinit )); static Finfo * processShared[] = { &process, &reinit }; static SharedFinfo proc( "proc", "This is a shared message to receive Process messages " "from the scheduler objects." "The first entry in the shared msg is a MsgDest " "for the Process operation. It has a single argument, " "ProcInfo, which holds lots of information about current " "time, thread, dt and so on. The second entry is a MsgDest " "for the Reinit operation. It also uses ProcInfo. ", processShared, sizeof( processShared ) / sizeof( Finfo* )); static Finfo * pyRunFinfos[] = { &runstring, &initstring, &mode, &inputvar, &outputvar, &trigger, outputOut(), // &locals, // &globals, &run, &proc, }; static string doc[] = { "Name", "PyRun", "Author", "Subhasis Ray", "Description", "Runs Python statements from inside MOOSE."}; static Dinfo< PyRun > dinfo; static Cinfo pyRunCinfo( "PyRun", Neutral::initCinfo(), pyRunFinfos, sizeof(pyRunFinfos) / sizeof(Finfo*), &dinfo, doc, sizeof(doc) / sizeof(string)); return &pyRunCinfo; }
const Cinfo* RC::initCinfo() { static DestFinfo process("process", "Handles process call.", new ProcOpFunc<RC>(&RC::process)); static DestFinfo reinit( "reinit", "Handle reinitialization", new ProcOpFunc<RC>( &RC::reinit )); static Finfo* processShared[] = { &process, &reinit }; static SharedFinfo proc("proc", "This is a shared message to receive Process messages " "from the scheduler objects." "The first entry in the shared msg is a MsgDest " "for the Process operation. It has a single argument, " "ProcInfo, which holds lots of information about current " "time, thread, dt and so on. The second entry is a MsgDest " "for the Reinit operation. It also uses ProcInfo. ", processShared, sizeof( processShared ) / sizeof( Finfo* )); static ValueFinfo<RC, double> V0( "V0", "Initial value of 'state'", &RC::setV0, &RC::getV0 ); static ValueFinfo<RC, double> R( "R", "Series resistance of the RC circuit.", &RC::setResistance, &RC::getResistance); static ValueFinfo<RC, double> C( "C", "Parallel capacitance of the RC circuit.", &RC::setCapacitance, &RC::getCapacitance); static ReadOnlyValueFinfo<RC, double> state("state", "Output value of the RC circuit. This is the voltage across the" " capacitor.", &RC::getState); static ValueFinfo<RC, double> inject( "inject", "Input value to the RC circuit.This is handled as an input current to" " the circuit.", &RC::setInject, &RC::getInject ); static DestFinfo injectIn( "injectIn", "Receives input to the RC circuit. All incoming messages are summed up" " to give the total input current." , new OpFunc1<RC, double>(&RC::setInjectMsg)); static Finfo* rcFinfos[] = { &V0, &R, &C, &state, &inject, outputOut(), &injectIn, &proc, }; static string doc[] = { "Name", "RC", "Author", "Subhasis Ray, 2008, NCBS", "Description", "RC circuit: a series resistance R shunted by a capacitance C." }; static Dinfo<RC> dinfo; static Cinfo rcCinfo("RC", Neutral::initCinfo(), rcFinfos, sizeof( rcFinfos ) / sizeof( Finfo* ), &dinfo, doc, sizeof(doc)/sizeof(string) ); return &rcCinfo; }
const Cinfo* PIDController::initCinfo() { static DestFinfo process( "process", "Handle process calls.", new ProcOpFunc<PIDController>( &PIDController::process)); static DestFinfo reinit( "reinit", "Reinitialize the object.", new ProcOpFunc<PIDController>( &PIDController::reinit )); static Finfo* processShared[] = { &process, &reinit }; static ValueFinfo<PIDController, double> gain( "gain", "This is the proportional gain (Kp). This tuning parameter scales the" " proportional term. Larger gain usually results in faster response, but" " too much will lead to instability and oscillation.", &PIDController::setGain, &PIDController::getGain); static ValueFinfo<PIDController, double> saturation("saturation", "Bound on the permissible range of output. Defaults to maximum double" " value.", &PIDController::setSaturation, &PIDController::getSaturation); static ValueFinfo<PIDController, double> command("command", "The command (desired) value of the sensed parameter. In control theory" " this is commonly known as setpoint(SP).", &PIDController::setCommand, &PIDController::getCommand); static ReadOnlyValueFinfo<PIDController, double> sensed( "sensed", "Sensed (measured) value. This is commonly known as process variable" "(PV) in control theory.", &PIDController::getSensed); static ValueFinfo<PIDController, double> tauI( "tauI", "The integration time constant, typically = dt. This is actually" " proportional gain divided by integral gain (Kp/Ki)). Larger Ki" " (smaller tauI) usually leads to fast elimination of steady state" " errors at the cost of larger overshoot.", &PIDController::setTauI, &PIDController::getTauI); static ValueFinfo<PIDController, double> tauD( "tauD", "The differentiation time constant, typically = dt / 4. This is" " derivative gain (Kd) times proportional gain (Kp). Larger Kd (tauD)" " decreases overshoot at the cost of slowing down transient response" " and may lead to instability.", &PIDController::setTauD, &PIDController::getTauD); static ReadOnlyValueFinfo<PIDController, double> outputValue( "outputValue", "Output of the PIDController. This is given by:" " gain * ( error + INTEGRAL[ error dt ] / tau_i + tau_d * d(error)/dt )\n" "Where gain = proportional gain (Kp), tau_i = integral gain (Kp/Ki) and" " tau_d = derivative gain (Kd/Kp). In control theory this is also known" " as the manipulated variable (MV)", &PIDController::getOutput); static ReadOnlyValueFinfo<PIDController, double> error( "error", "The error term, which is the difference between command and sensed" " value.", &PIDController::getError); static ReadOnlyValueFinfo<PIDController, double> integral( "integral", "The integral term. It is calculated as INTEGRAL(error dt) =" " previous_integral + dt * (error + e_previous)/2.", &PIDController::getEIntegral ); static ReadOnlyValueFinfo<PIDController, double> derivative( "derivative", "The derivative term. This is (error - e_previous)/dt.", &PIDController::getEDerivative ); static ReadOnlyValueFinfo<PIDController, double> e_previous( "e_previous", "The error term for previous step.", &PIDController::getEPrevious); static DestFinfo commandIn( "commandIn", "Command (desired value) input. This is known as setpoint (SP) in" " control theory." , new OpFunc1<PIDController, double>( &PIDController::setCommand )); static DestFinfo sensedIn( "sensedIn", "Sensed parameter - this is the one to be tuned. This is known as" " process variable (PV) in control theory. This comes from the process" " we are trying to control.", new OpFunc1<PIDController, double>( &PIDController::setSensed )); static DestFinfo gainDest( "gainDest", "Destination message to control the PIDController gain dynamically.", new OpFunc1<PIDController, double>(&PIDController::setGain)); static SharedFinfo proc( "proc", "This is a shared message to receive Process messages " "from the scheduler objects." "The first entry in the shared msg is a MsgDest " "for the Process operation. It has a single argument, " "ProcInfo, which holds lots of information about current " "time, thread, dt and so on. The second entry is a MsgDest " "for the Reinit operation. It also uses ProcInfo. ", processShared, sizeof( processShared ) / sizeof( Finfo* ) ); static Finfo* pidFinfos[] = { &gain, &saturation, &command, &sensed, &tauI, &tauD, &outputValue, &error, &integral, &derivative, &e_previous, outputOut(), &commandIn, &sensedIn, &gainDest, &proc }; static string doc[] = { "Name", "PIDController", "Author", "Subhasis Ray", "Description", "PID feedback controller." "PID stands for Proportional-Integral-Derivative. It is used to" " feedback control dynamical systems. It tries to create a feedback" " output such that the sensed (measured) parameter is held at command" " value. Refer to wikipedia (http://wikipedia.org) for details on PID" " Controller." }; static Dinfo<PIDController> dinfo; static Cinfo pidCinfo( "PIDController", Neutral::initCinfo(), pidFinfos, sizeof( pidFinfos ) / sizeof( Finfo* ), &dinfo, doc, sizeof(doc)/sizeof(string)); return &pidCinfo; }
const Cinfo* Ex::initCinfo() { // Value field def static ValueFinfo< Ex, int > n( "n", "Integer element.", &Ex::setN, &Ex::getN ); static ValueFinfo< Ex, double > x( "x", "Double element.", &Ex::setX, &Ex::getX ); // Lookup field def static LookupValueFinfo< Ex, unsigned int, double > values( "value", "Vector of values", &Ex::setVal, &Ex::getVal ); // Dest field def static DestFinfo handleX( "handleX", "Sets value of x_", new OpFunc1< Ex, double >(&Ex::handleX) ); static DestFinfo handleN( "handleN", "Sets value of n_", new OpFunc1< Ex, int >(&Ex::handleN) ); static DestFinfo handleValues( "handleValues", "Handle a vector of values", new OpFunc2< Ex, unsigned int, double >(&Ex::setVal) ); // Shared field def static DestFinfo process( "process", "Handles process call", new ProcOpFunc< Ex >(&Ex::process) ); static DestFinfo reinit( "reinit", "Handles reinit call", new ProcOpFunc< Ex >(&Ex::reinit) ); static Finfo* processShared[] = { &process, &reinit }; static SharedFinfo proc( "proc", "Handles 'reinit' and 'process' calls from a clock.", processShared, sizeof(processShared) / sizeof(Finfo*) ); static Finfo* exFinfos[] = { &n, &x, &values, &handleX, &handleN, &handleValues, outputOut(), &proc }; static Dinfo< Ex > exDinfo; static string doc[] = { "Name", "Ex", "Author", "Viktor Toth", "Description", "Example Moose class.", }; static Cinfo exCinfo( "Ex", Neutral::initCinfo(), exFinfos, sizeof(exFinfos) / sizeof(Finfo*), &exDinfo, doc, sizeof(doc) / sizeof(string) ); return &exCinfo; }
const Cinfo* PulseGen::initCinfo() { /////////////////////////////////////////////////////// // Field definitions /////////////////////////////////////////////////////// static ReadOnlyValueFinfo< PulseGen, double > output("outputValue", "Output amplitude", &PulseGen::getOutput); static ValueFinfo< PulseGen, double > baseLevel("baseLevel", "Basal level of the stimulus", &PulseGen::setBaseLevel, &PulseGen::getBaseLevel); static ValueFinfo< PulseGen, double > firstLevel("firstLevel", "Amplitude of the first pulse in a sequence", &PulseGen::setFirstLevel, &PulseGen::getFirstLevel); static ValueFinfo< PulseGen, double > firstWidth("firstWidth", "Width of the first pulse in a sequence", &PulseGen::setFirstWidth, &PulseGen::getFirstWidth); static ValueFinfo< PulseGen, double > firstDelay("firstDelay", "Delay to start of the first pulse in a sequence", &PulseGen::setFirstDelay, &PulseGen::getFirstDelay); static ValueFinfo< PulseGen, double > secondLevel("secondLevel", "Amplitude of the second pulse in a sequence", &PulseGen::setSecondLevel, &PulseGen::getSecondLevel); static ValueFinfo< PulseGen, double > secondWidth("secondWidth", "Width of the second pulse in a sequence", &PulseGen::setSecondWidth, &PulseGen::getSecondWidth); static ValueFinfo< PulseGen, double > secondDelay("secondDelay", "Delay to start of of the second pulse in a sequence", &PulseGen::setSecondDelay, &PulseGen::getSecondDelay); static ValueFinfo< PulseGen, unsigned int > count("count", "Number of pulses in a sequence", &PulseGen::setCount, &PulseGen::getCount); static ValueFinfo< PulseGen, unsigned int > trigMode("trigMode", "Trigger mode for pulses in the sequence.\n" " 0 : free-running mode where it keeps looping its output\n" " 1 : external trigger, where it is triggered by an external input (and" " stops after creating the first train of pulses)\n" " 2 : external gate mode, where it keeps generating the pulses in a" " loop as long as the input is high.", &PulseGen::setTrigMode, &PulseGen::getTrigMode); static LookupValueFinfo < PulseGen, unsigned int, double > level("level", "Level of the pulse at specified index", &PulseGen::setLevel, &PulseGen::getLevel); static LookupValueFinfo < PulseGen, unsigned int, double > width("width", "Width of the pulse at specified index", &PulseGen::setWidth, &PulseGen::getWidth); static LookupValueFinfo < PulseGen, unsigned int, double > delay("delay", "Delay of the pulse at specified index", &PulseGen::setDelay, &PulseGen::getDelay); /////////////////////////////////////////////////////////////// // Dest messages /////////////////////////////////////////////////////////////// static DestFinfo levelIn("levelIn", "Handle level value coming from other objects", new OpFunc2< PulseGen, unsigned int, double >(&PulseGen::setLevel)); static DestFinfo widthIn("widthIn", "Handle width value coming from other objects", new OpFunc2< PulseGen, unsigned int, double >(&PulseGen::setWidth)); static DestFinfo delayIn("delayIn", "Handle delay value coming from other objects", new OpFunc2< PulseGen, unsigned int, double >(&PulseGen::setDelay)); static DestFinfo input("input", "Handle incoming input that determines gating/triggering onset. " "Note that although this is a double field, the underlying field is" " integer. So fractional part of input will be truncated", new OpFunc1< PulseGen, double >(&PulseGen::input)); /////////////////////////////////////////////////////////////////// // Shared messages /////////////////////////////////////////////////////////////////// static DestFinfo process( "process", "Handles process call, updates internal time stamp.", new ProcOpFunc< PulseGen >( &PulseGen::process ) ); static DestFinfo reinit( "reinit", "Handles reinit call.", new ProcOpFunc< PulseGen >( &PulseGen::reinit ) ); static Finfo* processShared[] = { &process, &reinit }; static SharedFinfo proc( "proc", "This is a shared message to receive Process messages " "from the scheduler objects." "The first entry in the shared msg is a MsgDest " "for the Process operation. It has a single argument, " "ProcInfo, which holds lots of information about current " "time, thread, dt and so on. The second entry is a MsgDest " "for the Reinit operation. It also uses ProcInfo. ", processShared, sizeof( processShared ) / sizeof( Finfo* ) ); static Finfo* pulseGenFinfos[] = { &output, &baseLevel, &firstLevel, &firstWidth, &firstDelay, &secondLevel, &secondWidth, &secondDelay, &count, &trigMode, &level, &width, &delay, &input, outputOut(), &levelIn, &widthIn, &delayIn, &proc, }; static string doc[] = { "Name", "PulseGen", "Author", "Subhasis Ray", "Description", "PulseGen: general purpose pulse generator. This can generate any " "number of pulses with specified level and duration.", }; static Dinfo<PulseGen> dinfo; static Cinfo pulseGenCinfo("PulseGen", Neutral::initCinfo(), pulseGenFinfos, sizeof(pulseGenFinfos)/sizeof(Finfo*), &dinfo, doc, sizeof(doc)/sizeof(string)); return & pulseGenCinfo; }