/* Copyright (C) 2018 Raoul Rubien (github.com/rubienr) Updated for Linuxcnc 2020 by alkabal_free.fr This program is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with the program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ #pragma once // local includes #include "pendant-types.h" // system includes #include #include #include #include #include // local library includes #include #include // forward declarations // ---------------------------------------------------------------------- namespace XhcWhb04b6 { // forward declarations class XhcWhb04b6Component; class Hal; class UsbOutPackageData; // ---------------------------------------------------------------------- //! If hand wheel is in step mode (toggled by Step/Con" button) this speed setting is applied. //! In step mode the step is in machine units distance. class HandwheelStepModeStepSize { public: enum class PositionNameIndex : uint8_t { RotaryButton0001 = 0, RotaryButton0010 = 1, RotaryButton0100 = 2, RotaryButton100 = 3, RotaryButton500 = 4, RotaryButton1000 = 5, NA0 = 6, RotaryButtonUndefined = 7, POSITIONS_COUNT = 8, }; HandwheelStepModeStepSize(); ~HandwheelStepModeStepSize(); //! Translates the button position to step metric units. //! \param buttonPosition //! \return the step size in units ℝ ∈ {0.001, 0.01, 0.1, 1.0, -1} float getStepSize(PositionNameIndex buttonPosition) const; virtual bool isPermitted(PositionNameIndex buttonPosition) const; private: const float mSequence[static_cast::type>(PositionNameIndex::POSITIONS_COUNT)]; }; // ---------------------------------------------------------------------- //! If hand wheel is in MPG mode (toggled by Step/Con/Mpg button) this speed setting is applied. //! In Mpg mode the step speed is in percent of max-velocity. class HandwheelMpgModeStepSize { public: enum class PositionNameIndex : uint8_t { RotaryButton2percent = 0, RotaryButton5percent = 1, RotaryButton10percent = 2, RotaryButton30percent = 3, RotaryButton60percent = 4, RotaryButton100percent = 5, NA0 = 6, RotaryButtonUndefined = 7, POSITIONS_COUNT = 8 }; HandwheelMpgModeStepSize(); ~HandwheelMpgModeStepSize(); //! Translates the button position to step size in %. //! \param buttonPosition //! \return the step size in percent ℕ ∈ {[0, 100], -1} float getStepSize(PositionNameIndex buttonPosition) const; virtual bool isPermitted(PositionNameIndex buttonPosition) const; private: const int8_t mSequence[static_cast::type>(PositionNameIndex::POSITIONS_COUNT)]; }; // ---------------------------------------------------------------------- //! If hand wheel is in con mode (toggled by Step/Con" button) this speed setting is applied. //! In Con mode the step speed is in percent of max-velocity. class HandwheelConModeStepSize { public: enum class PositionNameIndex : uint8_t { RotaryButton2percent = 0, RotaryButton5percent = 1, RotaryButton10percent = 2, RotaryButton30percent = 3, RotaryButton60percent = 4, RotaryButton100percent = 5, NA0 = 6, RotaryButtonUndefined = 7, POSITIONS_COUNT = 8 }; HandwheelConModeStepSize(); ~HandwheelConModeStepSize(); //! Translates the button position to step size in %. //! \param buttonPosition //! \return the step size in percent N ? {[0, 100], -1} float getStepSize(PositionNameIndex buttonPosition) const; virtual bool isPermitted(PositionNameIndex buttonPosition) const; private: const int8_t mSequence[static_cast::type>(PositionNameIndex::POSITIONS_COUNT)]; }; // ---------------------------------------------------------------------- //! If hand wheel is in Lead mode (activated by the feed rotary button) this speed setting is applied. class HandwheelLeadModeStepSize { public: enum class PositionNameIndex : uint8_t { NA0 = 0, NA1 = 1, NA2 = 2, NA3 = 3, NA4 = 4, NA5 = 5, LEAD = 6, UNDEFINED = 7, POSITIONS_COUNT = 8 }; HandwheelLeadModeStepSize(); ~HandwheelLeadModeStepSize(); //! Translates the button position to step size. //! \param buttonPosition //! \return the step size ℕ ∈ {1.0, -1.0} float getStepSize(PositionNameIndex buttonPosition) const; virtual bool isPermitted(PositionNameIndex buttonPosition) const; private: const float mSequence[static_cast::type>(PositionNameIndex::POSITIONS_COUNT)]; }; // ---------------------------------------------------------------------- //! pendant button key code description class KeyCode { public: const uint8_t code; //! default button text as written on pendant (if available) const char* text; //! alternative button text as written on pendant (if available) const char* altText; bool operator==(const KeyCode& other) const; bool operator!=(const KeyCode& other) const; KeyCode(uint8_t code, const char* text, const char* altText); KeyCode(const KeyCode& other); }; // ---------------------------------------------------------------------- std::ostream& operator<<(std::ostream& os, const KeyCode& data); // ---------------------------------------------------------------------- //! meta-button state which is dependent on the "Fn" modifier button's state class MetaButtonCodes { public: const KeyCode& key; const KeyCode& modifier; bool operator==(const MetaButtonCodes& other) const; bool operator!=(const MetaButtonCodes& other) const; MetaButtonCodes(const KeyCode& key, const KeyCode& modifier); virtual ~MetaButtonCodes(); bool containsKeys(const KeyCode& key, const KeyCode& modifier) const; }; // ---------------------------------------------------------------------- //! rotary axis selection button related parameters class AxisRotaryButtonCodes { public: const KeyCode off; const KeyCode x; const KeyCode y; const KeyCode z; const KeyCode a; const KeyCode b; const KeyCode c; const KeyCode undefined; const std::map codeMap; AxisRotaryButtonCodes(); }; // ---------------------------------------------------------------------- //! rotary feed button related parameters class FeedRotaryButtonCodes { public: const KeyCode percent_2; const KeyCode percent_5; const KeyCode percent_10; const KeyCode percent_30; const KeyCode percent_60; const KeyCode percent_100; const KeyCode lead; const KeyCode undefined; const std::map codeMap; FeedRotaryButtonCodes(); }; // ---------------------------------------------------------------------- //! pendant button related parameters class ButtonsCode { public: const KeyCode reset; const KeyCode stop; const KeyCode start; const KeyCode feed_plus; const KeyCode feed_minus; const KeyCode spindle_plus; const KeyCode spindle_minus; const KeyCode machine_home; const KeyCode safe_z; const KeyCode workpiece_home; const KeyCode spindle_on_off; const KeyCode function; const KeyCode probe_z; const KeyCode macro10; const KeyCode continuous; const KeyCode step; const KeyCode undefined; const KeyCode& getKeyCode(uint8_t keyCode) const; const std::map codeMap; ButtonsCode(); }; // ---------------------------------------------------------------------- class KeyEventListener { public: //! Called when button is pressed. //! \param softwareButton the button pressed //! \return true if a subsequent re-evaluation should be performed. //! Example: A button event changes the feed rotary buttons step mode from //! step to con. The button must be re-evaluated, otherwise the //! button state remains untouched until the next button's event. virtual bool onButtonPressedEvent(const MetaButtonCodes& metaButton) = 0; //! Called when button is released. //! \param softwareButton the button released //! \return true if a subsequent re-evaluation should be performed. //! Example: A button event changes the feed rotary buttons step mode from //! step to con. The button must be re-evaluated, otherwise the //! button state remains untouched until the next button's event. virtual bool onButtonReleasedEvent(const MetaButtonCodes& metaButton) = 0; virtual void onAxisActiveEvent(const KeyCode& axis) = 0; virtual void onAxisInactiveEvent(const KeyCode& axis) = 0; virtual void onFeedActiveEvent(const KeyCode& feed) = 0; virtual void onFeedInactiveEvent(const KeyCode& feed) = 0; virtual bool onJogDialEvent(const HandWheelCounters& counters, int8_t delta) = 0; virtual ~KeyEventListener(); }; // ---------------------------------------------------------------------- std::ostream& operator<<(std::ostream& os, const MetaButtonCodes& data); // ---------------------------------------------------------------------- class MetaButtonsCodes { public: const MetaButtonCodes reset; const MetaButtonCodes macro11; const MetaButtonCodes stop; const MetaButtonCodes macro12; const MetaButtonCodes start; const MetaButtonCodes macro13; const MetaButtonCodes feed_plus; const MetaButtonCodes macro1; const MetaButtonCodes feed_minus; const MetaButtonCodes macro2; const MetaButtonCodes spindle_plus; const MetaButtonCodes macro3; // Hardcoded spindle speed const MetaButtonCodes spindle_minus; const MetaButtonCodes macro4; // Hardcoded spindle speed const MetaButtonCodes machine_home; const MetaButtonCodes macro5; const MetaButtonCodes safe_z; const MetaButtonCodes macro6; const MetaButtonCodes workpiece_home; const MetaButtonCodes macro7; const MetaButtonCodes spindle_on_off; const MetaButtonCodes macro8; // Hardcoded toggle spindle direction const MetaButtonCodes function; const MetaButtonCodes probe_z; const MetaButtonCodes macro9; const MetaButtonCodes macro10; // Hardcoded Absolute/relative Dro const MetaButtonCodes macro14; const MetaButtonCodes continuous; const MetaButtonCodes macro15; const MetaButtonCodes step; const MetaButtonCodes macro16; const MetaButtonCodes undefined; const std::list buttons; MetaButtonsCodes(const ButtonsCode& buttons); ~MetaButtonsCodes(); const MetaButtonCodes& find(const KeyCode& keyCode, const KeyCode& modifierCode) const; }; // ---------------------------------------------------------------------- class KeyCodes { public: static const ButtonsCode Buttons; static const MetaButtonsCodes Meta; static const AxisRotaryButtonCodes Axis; static const FeedRotaryButtonCodes Feed; }; // ---------------------------------------------------------------------- class Button { public: Button(const KeyCode& key); virtual ~Button(); virtual const KeyCode& keyCode() const; virtual bool setKeyCode(const KeyCode& keyCode); Button& operator=(const Button& other); protected: const KeyCode* mKey; }; // ---------------------------------------------------------------------- std::ostream& operator<<(std::ostream& os, const Button& data); // ---------------------------------------------------------------------- //! meta-button state which is dependent on the "Fn" modifier button's state class ToggleButton : public Button { public: ToggleButton(const KeyCode& key, const KeyCode& modifier); virtual ~ToggleButton(); virtual const KeyCode& modifierCode() const; virtual void setModifierCode(KeyCode& modifierCode); bool containsKeys(const KeyCode& key, const KeyCode& modifier) const; ToggleButton& operator=(const ToggleButton& other); private: const KeyCode* mModifier; }; // ---------------------------------------------------------------------- std::ostream& operator<<(std::ostream& os, const ToggleButton& data); // ---------------------------------------------------------------------- class RotaryButton : public Button { public: RotaryButton(const KeyCode& keyCode); virtual ~RotaryButton(); virtual bool isPermitted() const = 0; RotaryButton& operator=(const RotaryButton& other); }; // ---------------------------------------------------------------------- std::ostream& operator<<(std::ostream& os, const RotaryButton& data); // ---------------------------------------------------------------------- class FeedRotaryButton : public RotaryButton { public: FeedRotaryButton(const KeyCode& keyCode = KeyCodes::Feed.undefined, HandwheelStepmodes::Mode stepMode = HandwheelStepmodes::Mode::MPG, KeyEventListener* listener = nullptr); ~FeedRotaryButton(); virtual bool setKeyCode(const KeyCode& keyCode) override; void setStepMode(HandwheelStepmodes::Mode stepMode); HandwheelStepmodes::Mode stepMode() const; float stepSize() const; bool isPermitted() const override; FeedRotaryButton& operator=(const FeedRotaryButton& other); private: HandwheelStepmodes::Mode mStepMode; bool mIsPermitted; float mStepSize; bool mIsStepMode_5_10; KeyEventListener* mEventListener; static const HandwheelStepModeStepSize mStepSizeMapper; static const HandwheelMpgModeStepSize mMpgSizeMapper; static const HandwheelConModeStepSize mConSizeMapper; static const HandwheelLeadModeStepSize mLeadSizeMapper; static const std::map mStepKeycodeLut; static const std::map mMpgKeycodeLut; static const std::map mConKeycodeLut; static const std::map mLeadKeycodeLut; void update(); }; // ---------------------------------------------------------------------- std::ostream& operator<<(std::ostream& os, const FeedRotaryButton& data); // ---------------------------------------------------------------------- class AxisRotaryButton : public RotaryButton { public: AxisRotaryButton(const KeyCode& keyCode = KeyCodes::Axis.undefined, KeyEventListener* listener = nullptr); virtual ~AxisRotaryButton(); bool isPermitted() const override; AxisRotaryButton& operator=(const AxisRotaryButton& other); private: KeyEventListener* mEventListener; }; // ---------------------------------------------------------------------- std::ostream& operator<<(std::ostream& os, const AxisRotaryButton& data); // ---------------------------------------------------------------------- class Handwheel { public: Handwheel(const FeedRotaryButton& feedButton, KeyEventListener* listener = nullptr); ~Handwheel(); void enableVerbose(bool enable); void setMode(HandWheelCounters::CounterNameToIndex mode); void count(int8_t delta); const HandWheelCounters& counters() const; HandWheelCounters& counters(); //! En-/disables the incremental counter. //! \param enabled false if counting should be inhibited, true otherwise void setEnabled(bool enabled); private: HandWheelCounters mCounters; bool mIsEnabled{false}; const FeedRotaryButton& mFeedButton; KeyEventListener * mEventListener; std::ostream mDevNull{nullptr}; std::ostream * mWheelCout; const char * mPrefix; }; // ---------------------------------------------------------------------- std::ostream& operator<<(std::ostream& os, const Handwheel& data); // ---------------------------------------------------------------------- class ButtonsState { public: ButtonsState(KeyEventListener* listener = nullptr, const ButtonsState* previousState = nullptr); ~ButtonsState(); ButtonsState& operator=(const ButtonsState& other); void update(const KeyCode& keyCode, const KeyCode& modifierCode, const KeyCode& axisButton, const KeyCode& feedButton); void clearPressedButtons(); const std::list& pressedButtons() const; const MetaButtonCodes* currentMetaButton() const; const AxisRotaryButton& axisButton() const; const FeedRotaryButton& feedButton() const; FeedRotaryButton& feedButton(); private: std::list mPressedButtons; const MetaButtonCodes* mCurrentMetaButton; AxisRotaryButton mAxisButton; FeedRotaryButton mFeedButton; const ButtonsState* mPreviousState; KeyEventListener * mEventListener; }; // ---------------------------------------------------------------------- std::ostream& operator<<(std::ostream& os, const ButtonsState& data); // ---------------------------------------------------------------------- class Display : public KeyEventListener { public: enum class AxisPositionMethod { RELATIVE, ABSOLUTE }; enum class AxisGroup { XYZ, ABC }; Display(const ButtonsState& currentButtonsState, Hal& hal, UsbOutPackageData& displayData); Display(); ~Display(); virtual bool onButtonPressedEvent(const MetaButtonCodes& metaButton) override; virtual bool onButtonReleasedEvent(const MetaButtonCodes& metaButton) override; virtual void onAxisActiveEvent(const KeyCode& axis) override; virtual void onAxisInactiveEvent(const KeyCode& axis) override; virtual void onFeedActiveEvent(const KeyCode& feed) override; virtual void onFeedInactiveEvent(const KeyCode& feed) override; virtual bool onJogDialEvent(const HandWheelCounters& counters, int8_t delta) override; void updateData(); void clearData(); private: const ButtonsState& mCurrentButtonsState; Hal & mHal; UsbOutPackageData & mDisplayData; AxisPositionMethod mAxisPositionMethod; AxisGroup mActiveAxisGroup; }; // ---------------------------------------------------------------------- class Pendant : public KeyEventListener { public: Pendant(Hal& hal, UsbOutPackageData& displayOutData); ~Pendant(); void processEvent(uint8_t keyCode, uint8_t modifierCode, uint8_t rotaryButtonAxisKeyCode, uint8_t rotaryButtonFeedKeyCode, int8_t handWheelStepCount); void updateDisplayData(); void clearDisplayData(); void enableVerbose(bool enable); const ButtonsState& currentButtonsState() const; const ButtonsState& previousButtonsState() const; const Handwheel& handWheel() const; Handwheel& handWheel(); virtual bool onButtonPressedEvent(const MetaButtonCodes& metaButton) override; virtual bool onButtonReleasedEvent(const MetaButtonCodes& metaButton) override; virtual void onAxisActiveEvent(const KeyCode& axis) override; virtual void onAxisInactiveEvent(const KeyCode& axis) override; virtual void onFeedActiveEvent(const KeyCode& axis) override; virtual void onFeedInactiveEvent(const KeyCode& axis) override; virtual bool onJogDialEvent(const HandWheelCounters& counters, int8_t delta) override; //! Sets Lead mode to spindle: Jog dial will change spindle speed. //! Note: Switching Lead mode is not supported at runtime, only at start. //! \sa mIsLeadModeSpindle //! \sa setLeadModeFeed() void setLeadModeSpindle(bool enable); //! Sets Lead mode to feed: Jog dial will change feed override. //! Note: Switching Lead mode is not supported at runtime, only at start. //! \sa mIsLeadModeFeed //! \sa setLeadModeFeed() void setLeadModeFeed(bool enable); void setStepMode_5_10(bool enable); private: Hal& mHal; ButtonsState mPreviousButtonsState; ButtonsState mCurrentButtonsState; Handwheel mHandWheel; Display mDisplay; //! if in Lead mode: if true jog wheel changes the spindle speed, changes the feed override otherwise bool mIsLeadModeSpindle = false; bool mIsLeadModeFeed = false; bool mIsStepMode_5_10 = false; float mScale; float mMaxVelocity; const char * mPrefix; std::ostream mDevNull{nullptr}; std::ostream* mPendantCout; void shiftButtonState(); void processEvent(const KeyCode& keyCode, const KeyCode& modifierCode, const KeyCode& rotaryButtonAxisKeyCode, const KeyCode& rotaryButtonFeedKeyCode, int8_t handWheelStepCount); void dispatchFeedEventToHandwheel(const KeyCode& feed, bool isActive); void dispatchAxisEventToHandwheel(const KeyCode& axis, bool isActive); void dispatchAxisEventToHal(const KeyCode& axis, bool isActive); void dispatchActiveFeedToHal(const KeyCode& feed, bool isActive); void dispatchFeedValueToHal(); }; // ---------------------------------------------------------------------- std::ostream& operator<<(std::ostream& os, const Pendant& data); }