///////////////////////////////////////////////////////////////////////////// // zdelay.cc // // SIMLIB version: 2.18 // Date: 2004-01-25 // // Copyright (c) 1998-2004 Petr Peringer // // This library is licensed under GNU Library GPL. See the file COPYING. // // // This module contains implementation of discrete-time delay class // // classes: // ZDelay -- discrete-time delay blocks // ZDelayTimer -- clock generating class for ZDelay objects // SIMLIB_ZDelayTimer -- internal class // // TODO: add dividers //////////////////////////////////////////////////////////////////////////// // interface // #include "simlib.h" #include "zdelay.h" #include "internal.h" // we use standard C++ library (STL) #include // for ZDelay objects container implementation #include // for list of ZDelayTimers // using namespace std; // GNU C++ doesn't have namespaces yet :-( //////////////////////////////////////////////////////////////////////////// // implementation // SIMLIB_IMPLEMENTATION //////////////////////////////////////////////////////////////////////////// // SIMLIB_ZDelayTimer --- register of all ZDelayTimer objects // class SIMLIB_ZDelayTimer { typedef std::list container_t; // type of container we use static container_t *container; // list of delay objects -- singleton public: // interface static void Register(ZDelayTimer *p) { // called from ZDelayTimer constructor if( container == 0 ) Initialize(); container->push_back(p); } static void UnRegister(ZDelayTimer *p) { // called from ZDelayTimer destructor container->remove(p); if( container->size() == 0 ) Destroy(); } private: // implementation static void Initialize() { // initialize delay subsystem container = new container_t(); // create new list of delays // install hook in simulation control algorithm: INSTALL_HOOK( ZDelayTimerInit, SIMLIB_ZDelayTimer::InitAll ); } static void Destroy() { // should be called by ExitSimulation()? ###??? delete container; // remove list container = 0; // disable hook in simulation control algorithm INSTALL_HOOK( ZDelayTimerInit, 0 ); } // InitAll --- function to initialize all ZDelayTimer objects static void InitAll() { // called at Init() if( container == 0 ) return; // no delays ### container_t::iterator i; for( i=container->begin(); i!=container->end(); i++) // for each delay object (*i)->Init(); // set initial value } }; // SINGLETON: static member must be initializad SIMLIB_ZDelayTimer::container_t * SIMLIB_ZDelayTimer::container = 0; ///////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////// // ZDelayTimer --- discrete-time delay block timer implementation // // singleton -- default ZDelayTimer ZDelayTimer * ZDelay::default_clock = 0; ///////////////////////////////////////////////////////////////////////////// // ZDelayTimer::ZDelayContainer --- container for associated ZDelay blocks // class ZDelayTimer::ZDelayContainer { // implementation-defined container typedef std::set container_t; container_t c; public: ZDelayContainer(): c() {} typedef container_t::iterator iterator; iterator begin() { return c.begin(); } iterator end() { return c.end(); } void insert(ZDelay * p) { c.insert(p); } void erase(ZDelay * p) { c.erase(p); } void clear() { c.clear(); } }; // class ZDelayTimer::ZDelayContainer ///////////////////////////////////////////////////////////////////////////// // constructor --- init & insert into global register // ZDelayTimer::ZDelayTimer(double step, bool is_default) : dt(step), c(new ZDelayContainer) { // constructor body if(is_default) { ZDelay::default_clock = this; } SIMLIB_ZDelayTimer::Register(this); // register in list } ZDelayTimer::~ZDelayTimer() { if( ZDelay::default_clock == this) ZDelay::default_clock = 0; // default timer deleted // clear all items ZDelayContainer::iterator i=c->begin(); for( ; i!=c->end(); i++) // unregister all ZDelays (*i)->clock = 0; c->clear(); // remove all items delete c; SIMLIB_ZDelayTimer::UnRegister(this); // remove from list } ///////////////////////////////////////////////////////////////////////////// // ZDelayTimer::Init --- initialize all connected ZDelays and activate // void ZDelayTimer::Init() // called each Run() { ZDelayContainer::iterator i=c->begin(); for( ; i!=c->end(); i++) // init all assotiated ZDelays (*i)->Init(); Start(); } ///////////////////////////////////////////////////////////////////////////// // ZDelayTimer::Start --- activate // void ZDelayTimer::Start() // clock activation { Activate(); } ///////////////////////////////////////////////////////////////////////////// // ZDelayTimer::Stop --- passivate // void ZDelayTimer::Stop() // clock deactivation { Passivate(); } ///////////////////////////////////////////////////////////////////////////// // ZDelayTimer::Behavior --- sample all associated ZDelays, reschedule // void ZDelayTimer::Behavior() { ZDelayContainer::iterator i; for( i=c->begin(); i!=c->end(); i++) // evaluate all inputs (*i)->SampleIn(); for( i=c->begin(); i!=c->end(); i++) // store all new output values (*i)->SampleOut(); Activate( Time + dt ); } ///////////////////////////////////////////////////////////////////////////// // ZDelayTimer::Register --- add ZDelay to list // void ZDelayTimer::Register(ZDelay*p) { c->insert(p); p->clock = this; } ///////////////////////////////////////////////////////////////////////////// // ZDelayTimer::UnRegister --- remove ZDelay from list // void ZDelayTimer::UnRegister(ZDelay*p) { c->erase(p); p->clock = 0; } ///////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////// // ZDelay --- discrete-time delay block implementation // ///////////////////////////////////////////////////////////////////////////// // ZDelay constructor --- initialize and register delay block // ZDelay::ZDelay(Input i, ZDelayTimer *p, double ival) : aContiBlock1( i ), // input expression input_value( ival ), clock( p ), new_value( ival ), old_value( ival ), initval( ival ) // initial value of delay { // constructor body dprintf(("ZDelay::ZDelay%p(in=%p, timer=%p, ival=%g)", this, &i, p, ival)); if(clock==0) SIMLIB_internal_error(); // change ##############!!!!! clock->Register( this ); // register in timer Init(); // initialize -- important for dynamically created delays } ZDelay::ZDelay( Input i, double ival ) : aContiBlock1( i ), // input expression input_value( ival ), clock( default_clock ), new_value( ival ), old_value( ival ), initval( ival ) // initial value of delay { // constructor body dprintf(("ZDelay::ZDelay%p(in=%p, ival=%g)", this, &i, ival)); if(clock==0) SIMLIB_internal_error(); // change ##############!!!!! clock->Register( this ); // register in timer Init(); // initialize -- important for dynamically created delays } ///////////////////////////////////////////////////////////////////////////// // ZDelay destructor --- remove buffer and delay from list // ZDelay::~ZDelay() { dprintf(("ZDelay::~ZDelay%p()", this)); if(clock) clock->UnRegister( this ); // remove from delay list } ///////////////////////////////////////////////////////////////////////////// // ZDelay::Init --- initialize delay status // called automatically by Run() void ZDelay::Init() { dprintf(("ZDelay::Init()")); input_value = new_value = old_value = initval; } void ZDelay::Init(double iv) { // set initial value of ZDelay block initval = iv; Init(); } ///////////////////////////////////////////////////////////////////////////// // ZDelay::Sample --- sample input value // void ZDelay::SampleIn() { dprintf(("ZDelay::SampleIn()")); input_value = InputValue(); // store new input value } void ZDelay::SampleOut() { dprintf(("ZDelay::SampleOut()")); old_value = new_value; // set output value (delayed) new_value = input_value; // store new input value for delay } ///////////////////////////////////////////////////////////////////////////// // ZDelay::Value --- get delay output value // double ZDelay::Value() { dprintf(("ZDelay::Value()")); return old_value; // delayed value } // end