/* * eth_ecat_commands.hpp * * Created on: May 2, 2023 * Author: algin */ #ifndef FREE_RTOS_ETHERNET_INDUSTRY_ETH_ECAT_COMMAND_HPP_ #define FREE_RTOS_ETHERNET_INDUSTRY_ETH_ECAT_COMMAND_HPP_ #include #include #include #include "free_rtos/ethernet_industry/ethercattype.hpp" #include "free_rtos/ethernet_industry/eth_ecat_types.h" #include "free_rtos/ethernet_industry/eth_ecat_custom_tuple.hpp" #include "free_rtos/ethernet_industry/eth_ecat_packer.hpp" namespace free_rtos { namespace address { // Slave addressing types using Position = int16_t; using Broadcast = uint16_t; using Station = uint16_t; using Logical = uint32_t; using SlaveAddresses = custom_tuple; // Register offset using Offset = uint16_t; using PositionAddress = custom_tuple; using BroadcastAddress = custom_tuple; using StationAddress = custom_tuple; using LogicalAddress = custom_tuple; using Addresses = custom_tuple; } // namespace address namespace command { enum class DIR_INDEX : uint16_t { RD = 0, WR, RW, RMW, NO = RMW }; enum class TYPE_INDEX : uint16_t { AP = 0, B, FP, L }; struct DirBase { }; template struct Dir : public DirBase { static constexpr DIR_INDEX dir = dir_index; }; using RD = Dir; using WR = Dir; using RW = Dir; using RMW = Dir; using NO = Dir; struct TypeBase { }; template struct Type : public TypeBase { using TAddress = typename custom_tuple_element(type_index), address::Addresses>::type; using TSlaveAddress = typename custom_tuple_element<0, TAddress>::type; static constexpr TYPE_INDEX type = type_index; }; using AP = Type; using B = Type; using FP = Type; using L = Type; class EcatCommandBase { public: private: }; template class EcatCommand : public EcatCommandBase { static_assert(std::is_base_of::value == true, "TypeT should be derived from command::TypeBase"); static_assert(std::is_base_of::value == true, "DirT should be derived from command::DirBase"); public: EcatCommand(typename TypeT::TAddress&& address) : address_{address} { } EcatCommand() { } using TType = TypeT; using TDir = DirT; static constexpr uint8_t get_cmd() { std::array, 4> commands = {{ {{EC_CMD_APRD, EC_CMD_APWR, EC_CMD_APRW, EC_CMD_ARMW}}, {{EC_CMD_BRD, EC_CMD_BWR, EC_CMD_BRW, EC_CMD_NOP}}, {{EC_CMD_FPRD, EC_CMD_FPWR, EC_CMD_FPRW, EC_CMD_FRMW}}, {{EC_CMD_LRD, EC_CMD_LWR, EC_CMD_LRW, EC_CMD_NOP}} }}; return commands[static_cast(TypeT::type)][static_cast(DirT::dir)]; } static constexpr bool get_skip_pack() { std::array, 4> commands = {{ {{true, false, false, false}}, {{false, false, false, true}}, {{true, false, false, false}}, {{true, false, false, true}} }}; return commands[static_cast(TypeT::type)][static_cast(DirT::dir)]; } static constexpr bool get_skip_unpack() { std::array, 4> commands = {{ {{false, true, false, false}}, {{false, false, false, true}}, {{false, true, false, false}}, {{false, true, false, true}} }}; return commands[static_cast(TypeT::type)][static_cast(DirT::dir)]; } uint32_t get_address() { uint32_t address{0x00000000}; PackFunctor functor{reinterpret_cast(&address)}; for_each(address_, functor); return address; } private: typename TypeT::TAddress address_; }; /* * Position addressing * arg0: Each slave increments Position. Slave is addressed if Position = 0. * arg1: Local register or memory address of the ESC */ using APRD = EcatCommand; using APWR = EcatCommand; using APRW = EcatCommand; using ARMW = EcatCommand; /* * Broadcast addressing * arg0: Each slave increments Position (not used for addressing) * arg1: Local register or memory address of the ESC */ using NOP = EcatCommand; using BRD = EcatCommand; using BRW = EcatCommand; using BWR = EcatCommand; /* * arg0: Slave is addressed if Address matches Configured Station Address or Configured Station Alias (if enabled). * arg1: Local register or memory address of the ESC */ using FPRD = EcatCommand; using FPRW = EcatCommand; using FPWR = EcatCommand; using FPMW = EcatCommand; /* * Logical addressing * arg0: Logical Address (configured by FMMUs) Slave is addressed if FMMU configuration matches Address. */ using LRD = EcatCommand; using LRW = EcatCommand; using LWR = EcatCommand; } // namespace command } #endif /* FREE_RTOS_ETHERNET_INDUSTRY_ETH_ECAT_COMMAND_HPP_ */