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