Skip to content

Conversation

Sigma1912
Copy link
Contributor

Halui pins are frequently used to interface hardware panel buttons that are not aligned with Gmoccapy's screen buttons. Using halui pins together with any gui can cause unexpected behavior.
Example: starting program execution in program edit mode:
https://forum.linuxcnc.org/gmoccapy/56544-gmoccapy-3-5-1?start=0#331201

By providing native hal pins the behavior can be controlled by the gui itself.
At this point only pins for program.start .stop .pause and .resume are added.

halpins

@hansu
Copy link
Member

hansu commented Jul 6, 2025

Example: starting program execution in program edit mode:

Would the dedicated start pin prohibit starting the program when in edit mode?
Or what are the differences compared to the halui pins?

@Sigma1912
Copy link
Contributor Author

Yes the native pins only allow actions that are also allowed when using the gui buttons.
Example:
If the run-program gui button is not visible and sensitive then the pin 'program.start' will not start gcode execution.

@hansu
Copy link
Member

hansu commented Jul 6, 2025

I don't think it's necessary to prohibit the program from starting when in edit mode IMHO. We only have to make sure that it continues when leaving from that.

@Sigma1912
Copy link
Contributor Author

I don't see much point in starting a program in edit mode but the problem here is a more fundamental one. The gui should really be in control of what an operator can or cannot do. Circumventing the GUI by running what is essentially a second UI in parallel is always going to be asking for trouble.

@zz912
Copy link
Contributor

zz912 commented Jul 6, 2025

It would be a good idea to update the documentation.

@Sigma1912
Copy link
Contributor Author

Sigma1912 commented Jul 6, 2025

It would be a good idea to update the documentation.

I'll be happy to update the docs after we have agreed to merged this.

@c-morley
Copy link
Collaborator

c-morley commented Jul 6, 2025

I think a better in the long run way is to have a HALUI type program that talks directly to the GUI code.
actually (the neglected) panelui is capable of this.
It uses ZMQ to call functions in the (separate) GUI screen code when directed but otherwise uses NML messages for reading status and sending commands.
panelui is too complicated to setup but the premise worked pretty well.

I mean a complete rethink of linuxcnc's communication process would be great but I don't think that's gonna happen soon :)

@Sigma1912
Copy link
Contributor Author

Just to put this into perspective, this is how many pins Gmoccapy currently creates (This PR proposes to make four (4) more):

# We need extra HAL pins here is where we do it.
# we make pins for the hardware buttons which can be placed around the
# screen to activate the corresponding buttons on the GUI
    def _make_hal_pins(self):
        # generate the horizontal button pins
        for h_button in range(0, 10):
            pin = self.halcomp.newpin("h-button.button-{0}".format(h_button), hal.HAL_BIT, hal.HAL_IN)
            hal_glib.GPin(pin).connect("value_changed", self._button_pin_changed)

        # generate the vertical button pins
        for v_button in range(0, 7):
            pin = self.halcomp.newpin("v-button.button-{0}".format(v_button), hal.HAL_BIT, hal.HAL_IN)
            hal_glib.GPin(pin).connect("value_changed", self._button_pin_changed)

        # buttons for jogging the axis
        for jog_button in self.axis_list:
            pin = self.halcomp.newpin("jog.axis.jog-{0}-plus".format(jog_button), hal.HAL_BIT, hal.HAL_IN)
            hal_glib.GPin(pin).connect("value_changed", self._on_pin_jog_changed, "{0}+".format(jog_button))
            pin = self.halcomp.newpin("jog.axis.jog-{0}-minus".format(jog_button), hal.HAL_BIT, hal.HAL_IN)
            hal_glib.GPin(pin).connect("value_changed", self._on_pin_jog_changed, "{0}-".format(jog_button))

        if self.stat.kinematics_type != linuxcnc.KINEMATICS_IDENTITY:
            for joint_button in range(0, self.stat.joints):
                pin = self.halcomp.newpin("jog.joint.jog-{0}-plus".format(joint_button), hal.HAL_BIT, hal.HAL_IN)
                hal_glib.GPin(pin).connect("value_changed", self._on_pin_jog_changed, "{0}+".format(joint_button))
                pin = self.halcomp.newpin("jog.joint.jog-{0}-minus".format(joint_button), hal.HAL_BIT, hal.HAL_IN)
                hal_glib.GPin(pin).connect("value_changed", self._on_pin_jog_changed, "{0}+".format(joint_button))

        # jog_increment out pin
        self.halcomp.newpin("jog.jog-increment", hal.HAL_FLOAT, hal.HAL_OUT)

        # generate the pins to set the increments
        for buttonnumber in range(0, len(self.jog_increments)):
            pin = self.halcomp.newpin("jog.jog-inc-{0}".format(buttonnumber), hal.HAL_BIT, hal.HAL_IN)
            hal_glib.GPin(pin).connect("value_changed", self._on_pin_incr_changed, buttonnumber)

        # make the pin for unlocking settings page
        pin = self.halcomp.newpin("unlock-settings", hal.HAL_BIT, hal.HAL_IN)
        hal_glib.GPin(pin).connect("value_changed", self._on_unlock_settings_changed)

        # generate the pins to connect encoders to the sliders
        pin = self.halcomp.newpin("feed.feed-override.counts", hal.HAL_S32, hal.HAL_IN)
        hal_glib.GPin(pin).connect("value_changed", self._on_counts_changed, "spc_feed")
        pin = self.halcomp.newpin("spindle.spindle-override.counts", hal.HAL_S32, hal.HAL_IN)
        hal_glib.GPin(pin).connect("value_changed", self._on_counts_changed, "spc_spindle")
        pin = self.halcomp.newpin("jog.jog-velocity.counts", hal.HAL_S32, hal.HAL_IN)
        hal_glib.GPin(pin).connect("value_changed", self._on_counts_changed, "spc_lin_jog_vel")
        pin = self.halcomp.newpin("rapid.rapid-override.counts", hal.HAL_S32, hal.HAL_IN)
        hal_glib.GPin(pin).connect("value_changed", self._on_counts_changed, "spc_rapid")
        self.halcomp.newpin("feed.feed-override.count-enable", hal.HAL_BIT, hal.HAL_IN)
        self.halcomp.newpin("spindle.spindle-override.count-enable", hal.HAL_BIT, hal.HAL_IN)
        self.halcomp.newpin("jog.jog-velocity.count-enable", hal.HAL_BIT, hal.HAL_IN)
        self.halcomp.newpin("rapid.rapid-override.count-enable", hal.HAL_BIT, hal.HAL_IN)

        # generate the pins to connect analog inputs for sliders
        pin = self.halcomp.newpin("feed.feed-override.analog-enable", hal.HAL_BIT, hal.HAL_IN)
        hal_glib.GPin(pin).connect("value_changed", self._on_analog_enable_changed, "spc_feed")
        pin = self.halcomp.newpin("spindle.spindle-override.analog-enable", hal.HAL_BIT, hal.HAL_IN)
        hal_glib.GPin(pin).connect("value_changed", self._on_analog_enable_changed, "spc_spindle")
        pin = self.halcomp.newpin("jog.jog-velocity.analog-enable", hal.HAL_BIT, hal.HAL_IN)
        hal_glib.GPin(pin).connect("value_changed", self._on_analog_enable_changed, "spc_lin_jog_vel")
        pin = self.halcomp.newpin("rapid.rapid-override.analog-enable", hal.HAL_BIT, hal.HAL_IN)
        hal_glib.GPin(pin).connect("value_changed", self._on_analog_enable_changed, "spc_rapid")
        pin = self.halcomp.newpin("feed.feed-override.direct-value", hal.HAL_FLOAT, hal.HAL_IN)
        hal_glib.GPin(pin).connect("value_changed", self._on_analog_value_changed, "spc_feed")
        pin = self.halcomp.newpin("spindle.spindle-override.direct-value", hal.HAL_FLOAT, hal.HAL_IN)
        hal_glib.GPin(pin).connect("value_changed", self._on_analog_value_changed, "spc_spindle")
        pin = self.halcomp.newpin("jog.jog-velocity.direct-value", hal.HAL_FLOAT, hal.HAL_IN)
        hal_glib.GPin(pin).connect("value_changed", self._on_analog_value_changed, "spc_lin_jog_vel")
        pin = self.halcomp.newpin("rapid.rapid-override.direct-value", hal.HAL_FLOAT, hal.HAL_IN)
        hal_glib.GPin(pin).connect("value_changed", self._on_analog_value_changed, "spc_rapid")

        # make a pin to set turtle jog vel
        pin = self.halcomp.newpin("jog.turtle-jog", hal.HAL_BIT, hal.HAL_IN)
        hal_glib.GPin(pin).connect("value_changed", self._on_pin_turtle_jog)

        # make the pins for tool measurement
        self.halcomp.newpin("probeheight", hal.HAL_FLOAT, hal.HAL_OUT)
        pin = self.halcomp.newpin("blockheight", hal.HAL_FLOAT, hal.HAL_OUT)
        hal_glib.GPin(pin).connect("value_changed", self._on_blockheight_value_changed)
        preset = self.prefs.getpref("blockheight", 0.0, float)
        self.halcomp["blockheight"] = preset
        self.halcomp.newpin("toolmeasurement", hal.HAL_BIT, hal.HAL_OUT)
        self.halcomp.newpin("searchvel", hal.HAL_FLOAT, hal.HAL_OUT)
        self.halcomp.newpin("probevel", hal.HAL_FLOAT, hal.HAL_OUT)

        # make pins to react to tool_offset changes
        pin = self.halcomp.newpin("tooloffset-x", hal.HAL_FLOAT, hal.HAL_IN)
        hal_glib.GPin(pin).connect("value_changed", self._offset_changed, "tooloffset-x")
        pin = self.halcomp.newpin("tooloffset-z", hal.HAL_FLOAT, hal.HAL_IN)
        hal_glib.GPin(pin).connect("value_changed", self._offset_changed, "tooloffset-z")
        self.halcomp.newpin("tool-diameter", hal.HAL_FLOAT, hal.HAL_OUT)

        # make a pin to delete a notification message
        pin = self.halcomp.newpin("delete-message", hal.HAL_BIT, hal.HAL_IN)
        hal_glib.GPin(pin).connect("value_changed", self._del_message_changed)

        # for manual tool change dialog
        self.halcomp.newpin("toolchange-number", hal.HAL_S32, hal.HAL_IN)
        self.halcomp.newpin("toolchange-changed", hal.HAL_BIT, hal.HAL_OUT)
        pin = self.halcomp.newpin('toolchange-change', hal.HAL_BIT, hal.HAL_IN)
        hal_glib.GPin(pin).connect('value_changed', self.on_tool_change)
        self.halcomp.newpin('toolchange-confirm', hal.HAL_BIT, hal.HAL_IN)

        # make a pin to confirm a warning dialog
        self.halcomp.newpin('warning-confirm', hal.HAL_BIT, hal.HAL_IN)

        # make a pin to reset feed override to 100 %
        pin = self.halcomp.newpin("feed.reset-feed-override", hal.HAL_BIT, hal.HAL_IN)
        hal_glib.GPin(pin).connect("value_changed", self._reset_override, "feed")

        # make a pin to reset rapid override to 100 %
        pin = self.halcomp.newpin("rapid.reset-rapid-override", hal.HAL_BIT, hal.HAL_IN)
        hal_glib.GPin(pin).connect("value_changed", self._reset_override, "rapid")

        # make a pin to reset spindle override to 100 %
        pin = self.halcomp.newpin("spindle.reset-spindle-override", hal.HAL_BIT, hal.HAL_IN)
        hal_glib.GPin(pin).connect("value_changed", self._reset_override, "spindle")

        # make an error pin to indicate a error to hardware
        self.halcomp.newpin("error", hal.HAL_BIT, hal.HAL_OUT)

        # make pins to indicate program progress information
        self.halcomp.newpin("program.length", hal.HAL_S32, hal.HAL_OUT)
        self.halcomp.newpin("program.current-line", hal.HAL_S32, hal.HAL_OUT)
        self.halcomp.newpin("program.progress", hal.HAL_FLOAT, hal.HAL_OUT)

        # make a pin to set ignore limits
        pin = self.halcomp.newpin("ignore-limits", hal.HAL_BIT, hal.HAL_IN)
        hal_glib.GPin(pin).connect("value_changed", self._ignore_limits)

        # make pins to set optional stops and block delete
        pin = self.halcomp.newpin("optional-stop", hal.HAL_BIT, hal.HAL_IN)
        hal_glib.GPin(pin).connect("value_changed", self._optional_blocks)
        pin = self.halcomp.newpin("blockdelete", hal.HAL_BIT, hal.HAL_IN)
        hal_glib.GPin(pin).connect("value_changed", self._blockdelete)

@c-morley
Copy link
Collaborator

c-morley commented Jul 6, 2025

Yes a better way would be to get rid of as many as possible (in the longer future)
I was not implying that this pull request should not be accepted if they help.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants