/ src / hal / components / oneshot.comp
oneshot.comp
 1  //   This is a component for EMC2 HAL
 2  //   Copyright 2006 John Kasunich <jmkasunich@users.sourceforge.net>
 3  //
 4  //   This program is free software; you can redistribute it and/or modify
 5  //   it under the terms of the GNU General Public License as published by
 6  //   the Free Software Foundation; either version 2 of the License, or
 7  //   (at your option) any later version.
 8  //
 9  //   This program is distributed in the hope that it will be useful,
10  //   but WITHOUT ANY WARRANTY; without even the implied warranty of
11  //   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  //   GNU General Public License for more details.
13  //
14  //   You should have received a copy of the GNU General Public License
15  //   along with this program; if not, write to the Free Software
16  //   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
17  
18  component oneshot "one-shot pulse generator";
19  
20  description """creates a variable-length output pulse when the input changes 
21  state. This function needs to run in a thread which supports floating point
22  (typically the servo thread). This means that the pulse length has to be a
23  multiple of that thread period, typically 1mS. 
24  For a similar function that can run in the base thread, and which offers higher 
25  resolution, see "edge".""";
26  
27  pin in bit in "Trigger input";
28  pin in bit reset "Reset";
29  pin out bit out "Active high pulse";
30  pin out bit out_not "Active low pulse";
31  pin in float width=0 "Pulse width in seconds";
32  pin out float time_left "Time left in current output pulse";
33  
34  param rw bit retriggerable=TRUE "Allow additional edges to extend pulse";
35  param rw bit rising=TRUE "Trigger on rising edge";
36  param rw bit falling=FALSE "Trigger on falling edge";
37  
38  option data internal;
39  option extra_setup yes;
40  
41  function _ "Produce output pulses from input edges";
42  license "GPL";
43  ;;
44  
45  typedef struct {
46      double timer;
47      char old_in;
48  } internal;
49  
50  EXTRA_SETUP(){
51      data.timer = 0.0;
52      data.old_in = 0;
53      return 0;
54  }
55  
56  FUNCTION(_){ 
57      int new, old, trigger;
58  
59      if (reset) {
60          data.timer = 0.0;
61          data.old_in = 0;
62          out = 0;
63          out_not = 1;
64          return;
65      }
66      new = in;
67      old = data.old_in;
68      trigger = 0;
69      /* detect edges */
70      if ( new && (!old) && rising ) trigger = 1;
71      if ( old && (!new) && falling ) trigger = 1;
72      data.old_in = new;
73      /* is a pulse already running? */
74      if ( data.timer > 0.0 ) {
75  	if ( ! retriggerable ) {
76  	    /* ignore edges during pulse */
77  	    trigger = 0;
78  	}
79  	/* decrement timer */
80  	data.timer -= period * 0.000000001;
81  	if ( data.timer < 0.0 ) data.timer = 0.0;
82      }
83      if ( trigger ) {
84  	/* (re)start pulse */
85  	data.timer = width;
86      }
87      /* drive outputs */
88      time_left = data.timer;
89      if ( data.timer > 0.0 ) {
90  	out = 1;
91  	out_not = 0;
92      } else {
93  	out = 0;
94  	out_not = 1;
95      }
96  }
97