From bbb86ba4424390f4134a8151c9f0b4e3754f8523 Mon Sep 17 00:00:00 2001 From: david mueller Date: Thu, 6 Aug 2026 16:21:55 +0100 Subject: [PATCH 1/2] Adds a new 'momentary2nist' component This component does what the legacy 'toggle2nist' man page described plus added debounce on input pins and a maximum output pulse length to recover if the 'is-on' signal does not change state. --- src/hal/components/momentary2nist.comp | 85 ++++++++++++++++++++++++++ 1 file changed, 85 insertions(+) create mode 100644 src/hal/components/momentary2nist.comp diff --git a/src/hal/components/momentary2nist.comp b/src/hal/components/momentary2nist.comp new file mode 100644 index 00000000000..420c114e481 --- /dev/null +++ b/src/hal/components/momentary2nist.comp @@ -0,0 +1,85 @@ +component momentary2nist "momentary button to nist logic"; + +description +""" +Momentary2nist can be used with a momentary push button +to control a device that has separate on and off inputs +and an is-on output. +A debounce delay in cycles can be set for 'in'. (default = 2) +A maximum output pulse length in cycles can be set for 'on' and 'off'. (default = 100) + +* On a rising edge on pin *in* when *is-on* is low: It sets *on* until *is-on* becomes high. +* On a rising edge on pin *in* when *is-on* is high: It sets *off* until *is-on* becomes low. +* Pins *on* and *off* remain high until *is-on* confirms the respective state or until *max-pulse-length* is reached. +.... + ┐ ┌─────xxxxxxxxxxxx┐ ┌─────xxxxxxxxxxxx┐ +in : └─────┘ xxxxxxxxxxxx└───────────┘ xxxxxxxxxxxx└───── + + ┐ ┌───────────┐ +on : └─────┘ └───────────────────────────────────────── + + ┐ ┌───────────┐ +off : └───────────────────────────────────┘ └─────────── + + ┐ ┌─────────────────────────────┐ +is-on: └─────────────────┘ └─────────── +.... + +"""; + +pin in bool in "momentary button in"; +pin in bool is_on "current state of device"; +pin in ui32 debounce = 2 "debounce delay for 'in'-pin in cycles"; +pin in ui32 max_pulse_length = 100 "max output pulse length"; +pin out bool on "turn device on"; +pin out bool off "turn device off"; +variable unsigned debounce_cntr; +variable unsigned pulse_length; +variable bool state; + +option period no; +function _; +license "GPL"; +author "David Mueller"; +;; +FUNCTION(_) { + + rtapi_bool in_val = in; + rtapi_bool ison_val = is_on; + rtapi_uint debounce_val = debounce; + + if (( debounce_val < 1 ) || ( debounce_val > 10000 )) { + debounce_val = 2; // set a sane value + } + + if (in_val && state == 0 ) { // input has changed from debounced 0 -> 1 + debounce_cntr++; + if ( debounce_cntr >= debounce_val ) { + if (!ison_val) { // turn ON if it's off + on_set(1); + off_set(0); + } else { // turn OFF if it's on + on_set(0); + off_set(1); + } + state = 1; + debounce_cntr = 0; + } + } else if (!in_val && state == 1) { // input has changed from debounced 1 -> 0 + debounce_cntr++; + if ( debounce_cntr >= debounce_val ) { + state = 0; + debounce_cntr = 0; + } + } else if ((!ison_val && off) || (ison_val && on) || (pulse_length > max_pulse_length)) { + // reset outputs once device has switched or maximum pulse length is reached + on_set(0); + off_set(0); + debounce_cntr = 0; + pulse_length = 0; + } else { + debounce_cntr = 0; + pulse_length ++; + } +} + From dfb5b80c3683fee7da46646179f84e1ac3183db7 Mon Sep 17 00:00:00 2001 From: david mueller Date: Thu, 6 Aug 2026 15:07:39 +0100 Subject: [PATCH 2/2] toggle2nist.comp: restore 2.9 logic, add debounce, fix description Restores the legacy functionality (as in 2.9) plus added input debounce and and a maximum output pulse length to recover if the 'is-on' signal does not change state. Also fixes the description so it matches actual (legacy) behavior. --- src/hal/components/toggle2nist.comp | 55 +++++++++++++++++------------ 1 file changed, 32 insertions(+), 23 deletions(-) diff --git a/src/hal/components/toggle2nist.comp b/src/hal/components/toggle2nist.comp index 6d723121369..9c164425f21 100644 --- a/src/hal/components/toggle2nist.comp +++ b/src/hal/components/toggle2nist.comp @@ -2,17 +2,19 @@ component toggle2nist "toggle button to nist logic"; description """ -Toggle2nist can be used with a momentary push button +Toggle2nist can be used with a latching switch or push button to control a device that has separate on and off inputs and an is-on output. A debounce delay in cycles can be set for 'in'. (default = 2) +A maximum output pulse length in cycles can be set for 'on' and 'off'. (default = 100) * On a rising edge on pin *in* when *is-on* is low: It sets *on* until *is-on* becomes high. -* On a rising edge on pin *in* when *is-on* is high: It sets *off* until *is-on* becomes low. +* On a falling edge on pin *in* when *is-on* is high: It sets *off* until *is-on* becomes low. +* Pins *on* and *off* remain high until *is-on* confirms the respective state or until *max-pulse-length* is reached. .... -       ┐     ┌─────xxxxxxxxxxxx┐           ┌─────xxxxxxxxxxxx┐ -in   : └─────┘     xxxxxxxxxxxx└───────────┘     xxxxxxxxxxxx└───── +       ┐     ┌─────────────────────────────┐ +in   : └─────┘                             └───────────────────────        ┐     ┌───────────┐ on   : └─────┘           └───────────────────────────────────────── @@ -26,52 +28,59 @@ is-on: └─────────────────┘        """; -pin in bool in "momentary button in"; +pin in bool in "toggle button in"; pin in bool is_on "current state of device"; pin in ui32 debounce = 2 "debounce delay for 'in'-pin in cycles"; +pin in ui32 max_pulse_length = 100 "max output pulse length"; pin out bool on "turn device on"; pin out bool off "turn device off"; -variable int debounce_cntr; -variable unsigned debounce_val; -variable int state; +variable unsigned debounce_cntr; +variable unsigned pulse_length; +variable bool state; option period no; function _; license "GPL"; -author "Anders Wallin, David Mueller"; +author "Anders Wallin"; ;; FUNCTION(_) { - if (( debounce < 1 ) || ( debounce > 10000 )) { - debounce_val = 2; /* set a sane value */ - } else { - debounce_val = debounce; + rtapi_bool in_val = in; + rtapi_bool ison_val = is_on; + rtapi_uint debounce_val = debounce; + + if (( debounce_val < 1 ) || ( debounce_val > 10000 )) { + debounce_val = 2; // set a sane value } - if (in && state == 0 ) { /* input has changed from debounced 0 -> 1 */ + if (in_val && state == 0 ) { /* input has changed from debounced 0 -> 1 */ debounce_cntr++; - if ( debounce_cntr >= (int)debounce_val ) { - if (!is_on) { /* turn ON if it's off */ + if ( debounce_cntr >= debounce_val ) { + if (!ison_val) { /* turn ON if it's off */ on_set(1); off_set(0); - } else { /* turn OFF if it's on */ - on_set(0); - off_set(1); } state = 1; debounce_cntr = 0; } - } else if (!in && state == 1) { /* input has changed from debounced 1 -> 0 */ + } else if (!in_val && state == 1) { /* input has changed from debounced 1 -> 0 */ debounce_cntr++; - if ( debounce_cntr >= (int)debounce_val ) { + if ( debounce_cntr >= debounce_val ) { + if (ison_val) { /* turn OFF if it's on */ + on_set(0); + off_set(1); + } state = 0; debounce_cntr = 0; } - } else if ((!is_on && off) || (is_on && on)) { /* reset outputs once device has switched*/ + } else if ((!ison_val && off) || (ison_val && on) || (pulse_length > max_pulse_length)) { + // reset outputs once device has switched or maximum pulse length is reached on_set(0); off_set(0); debounce_cntr = 0; + pulse_length = 0; } else { - debounce_cntr = 0; + debounce_cntr = 0; + pulse_length ++; } }