MOOSE - Multiscale Object Oriented Simulation Environment
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
PulseGen.cpp
Go to the documentation of this file.
1 // PulseGen.cpp ---
2 //
3 // Filename: PulseGen.cpp
4 // Description:
5 // Author: Subhasis Ray
6 // Maintainer:
7 // Created: Mon Feb 20 01:41:12 2012 (+0530)
8 // Version:
9 // Last-Updated: Mon May 27 11:49:31 2013 (+0530)
10 // By: subha
11 // Update #: 170
12 // URL:
13 // Keywords:
14 // Compatibility:
15 //
16 //
17 
18 // Commentary:
19 //
20 //
21 //
22 //
23 
24 // Change log:
25 //
26 // 2012-02-20 01:41:16 (+0530) - Subha - started porting from old
27 // moose.
28 //
29 
30 // Code:
31 
32 #include "header.h"
33 #include "PulseGen.h"
34 
36 {
37  static SrcFinfo1< double > outputOut( "output",
38  "Current output level.");
39  return &outputOut;
40 }
41 
43 {
45  // Field definitions
48  "Output amplitude",
50  static ValueFinfo< PulseGen, double > baseLevel("baseLevel",
51  "Basal level of the stimulus",
54  static ValueFinfo< PulseGen, double > firstLevel("firstLevel",
55  "Amplitude of the first pulse in a sequence",
58  static ValueFinfo< PulseGen, double > firstWidth("firstWidth",
59  "Width of the first pulse in a sequence",
62  static ValueFinfo< PulseGen, double > firstDelay("firstDelay",
63  "Delay to start of the first pulse in a sequence",
66  static ValueFinfo< PulseGen, double > secondLevel("secondLevel",
67  "Amplitude of the second pulse in a sequence",
70  static ValueFinfo< PulseGen, double > secondWidth("secondWidth",
71  "Width of the second pulse in a sequence",
74  static ValueFinfo< PulseGen, double > secondDelay("secondDelay",
75  "Delay to start of of the second pulse in a sequence",
78  static ValueFinfo< PulseGen, unsigned int > count("count",
79  "Number of pulses in a sequence",
82  static ValueFinfo< PulseGen, unsigned int > trigMode("trigMode",
83  "Trigger mode for pulses in the sequence.\n"
84  " 0 : free-running mode where it keeps looping its output\n"
85  " 1 : external trigger, where it is triggered by an external input (and"
86  " stops after creating the first train of pulses)\n"
87  " 2 : external gate mode, where it keeps generating the pulses in a"
88  " loop as long as the input is high.",
92  "Level of the pulse at specified index",
96  "Width of the pulse at specified index",
100  "Delay of the pulse at specified index",
104  // Dest messages
106  static DestFinfo levelIn("levelIn",
107  "Handle level value coming from other objects",
109  static DestFinfo widthIn("widthIn",
110  "Handle width value coming from other objects",
112  static DestFinfo delayIn("delayIn",
113  "Handle delay value coming from other objects",
115 
116  static DestFinfo input("input",
117  "Handle incoming input that determines gating/triggering onset. "
118  "Note that although this is a double field, the underlying field is"
119  " integer. So fractional part of input will be truncated",
122  // Shared messages
124  static DestFinfo process( "process",
125  "Handles process call, updates internal time stamp.",
127  static DestFinfo reinit( "reinit",
128  "Handles reinit call.",
130  static Finfo* processShared[] =
131  {
132  &process, &reinit
133  };
134 
135  static SharedFinfo proc( "proc",
136  "This is a shared message to receive Process messages "
137  "from the scheduler objects."
138  "The first entry in the shared msg is a MsgDest "
139  "for the Process operation. It has a single argument, "
140  "ProcInfo, which holds lots of information about current "
141  "time, thread, dt and so on. The second entry is a MsgDest "
142  "for the Reinit operation. It also uses ProcInfo. ",
143  processShared, sizeof( processShared ) / sizeof( Finfo* )
144  );
145 
146  static Finfo* pulseGenFinfos[] = {
147  &output,
148  &baseLevel,
149  &firstLevel,
150  &firstWidth,
151  &firstDelay,
152  &secondLevel,
153  &secondWidth,
154  &secondDelay,
155  &count,
156  &trigMode,
157  &level,
158  &width,
159  &delay,
160  &input,
161  outputOut(),
162  &levelIn,
163  &widthIn,
164  &delayIn,
165  &proc,
166  };
167  static string doc[] =
168  {
169  "Name", "PulseGen",
170  "Author", "Subhasis Ray",
171  "Description", "PulseGen: general purpose pulse generator. This can generate any "
172  "number of pulses with specified level and duration.",
173  };
174  static Dinfo<PulseGen> dinfo;
175  static Cinfo pulseGenCinfo("PulseGen",
177  pulseGenFinfos,
178  sizeof(pulseGenFinfos)/sizeof(Finfo*),
179  &dinfo,
180  doc,
181  sizeof(doc)/sizeof(string));
182  return & pulseGenCinfo;
183 
184 }
185 
187 
189 {
190  level_.reserve(2);
191  width_.reserve(2);
192  delay_.reserve(2);
193  level_.resize(2);
194  width_.resize(2);
195  delay_.resize(2);
196  level_.assign(2, 0.0);
197  delay_.assign(2, 0.0);
198  width_.assign(2, 0.0);
199  output_ = 0.0;
200  baseLevel_ = 0.0;
201  trigTime_ = -1;
202  trigMode_ = 0;
203  prevInput_ = 0;
204 }
205 
207 
208 {
209  ;
210 }
211 
212 void PulseGen::setFirstLevel( double level)
213 {
214  level_[0] = level;
215 }
216 
218 {
219  return level_[0];
220 }
221 
222 void PulseGen::setFirstWidth(double width)
223 {
224  width_[0] = width;
225 }
226 
228 {
229  return width_[0];
230 }
231 void PulseGen::setFirstDelay( double delay)
232 {
233  delay_[0] = delay;
234 }
236 {
237  return delay_[0];
238 }
239 
240 void PulseGen::setSecondLevel( double level)
241 {
242  if (level_.size() >= 2){
243  level_[1] = level;
244  }
245 }
246 
248 {
249  if (level_.size() >= 2){
250  return level_[1];
251  } else {
252  return 0.0;
253  }
254 }
255 
256 void PulseGen::setSecondWidth(double width)
257 {
258  if (width_.size() >= 2){
259  width_[1] = width;
260  }
261 }
262 
264 {
265  if (width_.size() >= 2){
266  return width_[1];
267  } else {
268  return 0.0;
269  }
270 }
271 void PulseGen::setSecondDelay( double delay)
272 {
273  if (delay_.size() >= 2){
274  delay_[1] = delay;
275  }
276 }
278 {
279  if (delay_.size() >= 2){
280  return delay_[1];
281  }
282  return 0.0;
283 }
284 
285 void PulseGen::setBaseLevel( double level)
286 {
287  baseLevel_ = level;
288 }
290 {
291  return baseLevel_;
292 }
293 void PulseGen::setTrigMode(unsigned int mode)
294 {
295  trigMode_ = mode;
296 }
297 unsigned int PulseGen::getTrigMode() const
298 {
299  return trigMode_;
300 }
301 double PulseGen::getOutput() const
302 {
303  return output_;
304 }
305 
307 {
308  return prevInput_;
309 }
310 
311 void PulseGen::setCount(unsigned int count)
312 {
313  if (count <= 0){
314  cout << "WARNING: invalid pulse count specified." << endl;
315  return;
316  }
317  // we want to keep it compact - reserve will ensure we do not
318  // overallocate in resize call
319  level_.reserve(count);
320  delay_.reserve(count);
321  width_.reserve(count);
322  level_.resize(count, 0.0);
323  delay_.resize(count, 0.0);
324  width_.resize(count, 0.0);
325 }
326 
327 unsigned int PulseGen::getCount() const
328 {
329  return level_.size();
330 }
331 
332 double PulseGen::getLevel(unsigned int index) const
333 {
334  if (index < level_.size()){
335  return level_[index];
336  } else {
337  cout << "WARNING: PulseGen::getLevel - invalid index." << endl;
338  return 0.0;
339  }
340 }
341 
342 void PulseGen::setLevel( unsigned int index, double level)
343 {
344  if (index < level_.size()){
345  level_[index] = level;
346  } else {
347  cout << "WARNING: PulseGen::setLevel - invalid index. First set the number of pulses by setting 'count' field." << endl;
348  }
349 }
350 
351 double PulseGen::getWidth(unsigned int index) const
352 {
353  if (index < width_.size()){
354  return width_[index];
355  } else {
356  cout << "WARNING: PulseGen::getWidth - invalid index." << endl;
357  return 0.0;
358  }
359 }
360 void PulseGen::setWidth(unsigned int index, double width)
361 {
362  if ( index < width_.size()){
363  width_[index] = width;
364  } else {
365  cout << "WARNING: PulseGen::setWidth - invalid index. First set the number of pulses by setting 'count' field." << endl;
366  }
367 }
368 double PulseGen::getDelay(unsigned int index) const
369 {
370  if ( index < delay_.size()){
371  return delay_[index];
372  } else {
373  cout << "WARNING: PulseGen::getDelay - invalid index." << endl;
374  return 0.0;
375  }
376 }
377 
378 void PulseGen::setDelay(unsigned int index, double delay)
379 {
380  if ( index < delay_.size() ){
381  delay_[index] = delay;
382  } else {
383  cout << "WARNING: PulseGen::setDelay - invalid index. First set the number of pulses by setting 'count' field." << endl;
384  }
385 }
386 
387 
389 // Message dest functions.
391 
392 void PulseGen::input( double value)
393 {
394  input_ = value;
395 }
396 
397 
398 void PulseGen::process(const Eref& e, ProcPtr p )
399 {
400  double currentTime = p->currTime;
401  double period = width_[0] + delay_[0];
402  double phase = 0.0;
403  for (unsigned int ii = 1; ii < width_.size() && (width_[ii] > 0.0 || delay_[ii] > 0.0); ++ii){
404  double incr = delay_[ii] + width_[ii] - width_[ii-1];
405  if (incr > 0){
406  period += incr;
407  }
408  }
409  switch (trigMode_){
410  case PulseGen::FREE_RUN:
411  phase = fmod(currentTime, period);
412  break;
413  case PulseGen::EXT_TRIG:
414  if (input_ == 0){
415  if (trigTime_ < 0){
416  phase = period;
417  }else{
418  phase = currentTime - trigTime_;
419  }
420  } else {
421  if (prevInput_ == 0){
422  trigTime_ = currentTime;
423  }
424  phase = currentTime - trigTime_;
425  }
426  prevInput_ = input_;
427  break;
428  case PulseGen::EXT_GATE:
429  if(input_ == 0)
430  {
431  phase = period; /* output = baselevel */
432  }
433  else
434  { /* gate high */
435  if(prevInput_ == 0)
436  { /* low -> high */
437  trigTime_ = currentTime;
438  }
439  phase = fmod(currentTime - trigTime_, period);
440  }
441  prevInput_ = input_;
442  break;
443  default:
444  cerr << "ERROR: PulseGen::newProcessFunc( const Conn* , ProcInfo ) - invalid triggerMode - " << trigMode_ << endl;
445  }
446  if (phase >= period){ // we have crossed all pulses
448  return;
449  }
450  // go through all pulse positions to check which pulse/interpulse
451  // are we are in and set the output level accordingly
452  for (unsigned int ii = 0; ii < width_.size(); ++ii){
453  if (phase < delay_[ii]){ // we are in the baseline area - before ii-th pulse
455  break;
456  } else if (phase < delay_[ii] + width_[ii]){ // we are inside th ii-th pulse
457  output_ = level_[ii];
458  break;
459  }
460  phase -= delay_[ii];
461  }
462  outputOut()->send(e, output_);
463 }
464 
465 
466 void PulseGen::reinit(const Eref& e, ProcPtr p)
467 {
468  trigTime_ = -1;
469  prevInput_ = 0;
471  input_ = 0;
472  outputOut()->send(e, output_);
473 }
474 
475 //
476 // PulseGen.cpp ends here
uint32_t value
Definition: moosemodule.h:42
double getWidth(unsigned int index) const
Definition: PulseGen.cpp:351
vector< double > delay_
Definition: PulseGen.h:123
double trigTime_
Definition: PulseGen.h:129
int prevInput_
Definition: PulseGen.h:133
double currTime
Definition: ProcInfo.h:19
double output_
Definition: PulseGen.h:127
Definition: Dinfo.h:60
static const Cinfo * initCinfo()
Definition: PulseGen.cpp:42
static const int EXT_GATE
Definition: PulseGen.h:68
void setWidth(unsigned int pulseNo, double width)
Definition: PulseGen.cpp:360
void setLevel(unsigned int pulseNo, double level)
Definition: PulseGen.cpp:342
double getSecondWidth() const
Definition: PulseGen.cpp:263
void reinit(const Eref &e, ProcPtr p)
Definition: PulseGen.cpp:466
void setCount(unsigned int count)
Definition: PulseGen.cpp:311
double getFirstWidth() const
Definition: PulseGen.cpp:227
int getPreviousInput() const
Definition: PulseGen.cpp:306
double baseLevel_
Definition: PulseGen.h:128
void setDelay(unsigned int pulseNo, double delay)
Definition: PulseGen.cpp:378
void setSecondWidth(double value)
Definition: PulseGen.cpp:256
unsigned int trigMode_
Definition: PulseGen.h:130
Definition: OpFunc.h:40
double getBaseLevel() const
Definition: PulseGen.cpp:289
static SrcFinfo1< double > * output()
Definition: Arith.cpp:14
double getSecondDelay() const
Definition: PulseGen.cpp:277
void setSecondDelay(double value)
Definition: PulseGen.cpp:271
unsigned int getCount() const
Definition: PulseGen.cpp:327
double getFirstLevel() const
Definition: PulseGen.cpp:217
void setTrigMode(unsigned int value)
Definition: PulseGen.cpp:293
void setFirstWidth(double value)
Definition: PulseGen.cpp:222
Definition: OpFunc.h:27
Definition: Eref.h:26
void setFirstLevel(double value)
Definition: PulseGen.cpp:212
static const int FREE_RUN
Definition: PulseGen.h:47
int input_
Definition: PulseGen.h:134
unsigned int getTrigMode() const
Definition: PulseGen.cpp:297
double getLevel(unsigned int index) const
Definition: PulseGen.cpp:332
void input(double input)
Definition: PulseGen.cpp:392
vector< double > level_
Definition: PulseGen.h:124
static const Cinfo * initCinfo()
Definition: Neutral.cpp:16
static const int EXT_TRIG
Definition: PulseGen.h:63
void process(const Eref &e, ProcPtr p)
Definition: PulseGen.cpp:398
double getFirstDelay() const
Definition: PulseGen.cpp:235
void setBaseLevel(double value)
Definition: PulseGen.cpp:285
double getOutput() const
Definition: PulseGen.cpp:301
Definition: Cinfo.h:18
double getSecondLevel() const
Definition: PulseGen.cpp:247
double getDelay(unsigned int index) const
Definition: PulseGen.cpp:368
void setFirstDelay(double value)
Definition: PulseGen.cpp:231
void setSecondLevel(double value)
Definition: PulseGen.cpp:240
static const Cinfo * pulseGenCinfo
Definition: PulseGen.cpp:186
Definition: Finfo.h:12
static SrcFinfo1< double > * outputOut()
Definition: PulseGen.cpp:35
vector< double > width_
Definition: PulseGen.h:125