ethercatcpp
slave_device.h
Go to the documentation of this file.
1 /* File: slave_device.h
2  * This file is part of the program ethercatcpp-core
3  * Program description : EtherCAT driver libraries for UNIX
4  * Copyright (C) 2017-2024 - Robin Passama (LIRMM / CNRS) Arnaud Meline
5  * (LIRMM / CNRS) Benjamin Navarro (LIRMM / CNRS). All Right reserved.
6  *
7  * This software is free software: you can redistribute it and/or modify
8  * it under the terms of the CeCILL-C license as published by
9  * the CEA CNRS INRIA, either version 1
10  * of the License, or (at your option) any later version.
11  * This software is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * CeCILL-C License for more details.
15  *
16  * You should have received a copy of the CeCILL-C License
17  * along with this software. If not, it can be found on the official
18  * website of the CeCILL licenses family (http://www.cecill.info/index.en.html).
19  */
30 #pragma once
31 
32 #include <ethercatcpp/device.h>
34 
35 #include <string>
36 #include <vector>
37 #include <functional>
38 #include <memory>
39 
44 namespace ethercatcpp {
45 
53 class SlaveDevice : public Device {
54 public:
58  1,
60  2,
62  3,
64  };
65 
69  SlaveDevice();
70  virtual ~SlaveDevice();
71 
81  void set_serial_number(uint32_t serial_number);
82 
88  uint32_t eep_manufacturer() const;
89 
95  uint32_t eep_device() const;
96 
102  uint32_t serial_number() const;
103 
104 protected:
105  friend class coe::PDOMapping;
106  friend class coe::PDOBuffer;
107 
122  template <typename T, typename... U>
123  void define_physical_buffer(syncmanager_buffer_t type, uint16_t start_addr,
124  uint32_t flags) {
125  if constexpr (sizeof...(U) == 0) {
126  define_physical_buffer(type, start_addr, flags,
127  static_cast<uint16_t>(sizeof(T)));
128  } else {
130  type, start_addr, flags,
131  static_cast<uint16_t>(sizeof(T) + (sizeof(U) + ...)));
132  }
133  }
134 
146  void define_physical_buffer(syncmanager_buffer_t type, uint16_t start_addr,
147  uint32_t flags, uint16_t length);
148 
160  template <typename T>
161  T* input_buffer(uint16_t start_addr) {
162  return reinterpret_cast<T*>(input_buffer(start_addr));
163  }
164 
165  template <typename T, typename U, typename... Other>
166  std::tuple<T*, U*, Other*...> input_buffer(uint16_t start_addr) {
167  return input_buffer_tuple<T, U, Other...>(start_addr, 0);
168  }
169 
176  uint8_t* input_buffer(uint16_t start_addr);
177 
189  template <typename T>
190  T* output_buffer(uint16_t start_addr) {
191  return reinterpret_cast<T*>(output_buffer(start_addr));
192  }
193 
194  template <typename T, typename U, typename... Other>
195  std::tuple<T*, U*, Other*...> output_buffer(uint16_t start_addr) {
196  return output_buffer_tuple<T, U, Other...>(start_addr, 0);
197  }
198 
205  uint8_t* output_buffer(uint16_t start_addr);
206 
216  void add_run_step(std::function<void()>&& pre,
217  std::function<void()>&& post);
218 
228  void add_init_step(std::function<void()>&& pre,
229  std::function<void()>&& post);
230 
240  void add_end_step(std::function<void()>&& pre,
241  std::function<void()>&& post);
242 
250  void set_id(const std::string& name, uint32_t manufacturer, uint32_t model);
251 
257  void define_distributed_clock(bool have_dc);
258 
264  void define_period_for_non_cyclic_steps(int period);
265 
278  void configure_at_init(std::function<void()>&& func);
279 
289  void configure_at_end(std::function<void()>&& func);
290 
294 
304  int write_sdo(uint16_t index, uint8_t sub_index, int buffer_size,
305  void* buffer) const;
306 
316  int read_sdo(uint16_t index, uint8_t sub_index, int buffer_size,
317  void* buffer) const;
318 
329  template <typename T>
330  int write_sdo(uint16_t index, uint8_t sub_index, T& value) const {
331  return write_sdo(index, sub_index, static_cast<int>(sizeof(T)),
332  reinterpret_cast<void*>(&value));
333  }
334 
345  template <typename T>
346  int read_sdo(uint16_t index, uint8_t sub_index, T& value) const {
347  return read_sdo(index, sub_index, static_cast<int>(sizeof(T)),
348  reinterpret_cast<void*>(&value));
349  }
350 
358  template <typename T>
360  // Have to desactivate buffer to change it
361  T val = 0;
363  return write_sdo(coe::coe_rx_pdo_assign, 0x00, val) != 0;
364  }
365 
374  template <typename T>
375  bool add_command_pdo_mapping(uint16_t pdo_address) {
376  T val = 0;
377  // Check if buffer is desactivate
378  int wkc = read_sdo(coe::coe_rx_pdo_assign, 0x00, val);
379  if (val != 0) { // not in config PDO mode
380  return false;
381  }
382  // Send new PDO address mapping
385  pdo_address);
386  return (wkc == 2);
387  }
388 
396  template <typename T>
398  T val = static_cast<T>(get_command_mappings());
399  // Have to reactivate buffer with map number to valid it
400  return write_sdo(coe::coe_rx_pdo_assign, 0x00, val) != 0;
401  }
402 
410  template <typename T>
412  // Have to desactivate buffer to change it
413  T val = 0;
415  return write_sdo(coe::coe_tx_pdo_assign, 0x00, val) != 0;
416  }
417 
426  template <typename T>
427  bool add_status_pdo_mapping(uint16_t pdo_address) {
428  T val = 0;
429  // Check if buffer is desactivate
430  int wkc = read_sdo(coe::coe_tx_pdo_assign, 0x00, val);
431  if (val != 0) { // no in config PDO mode
432  return false;
433  }
434  // Send new PDO address mapping
436  // increment number of Status pdo mapping to
437  // write in good index
439  pdo_address);
440  return (wkc == 2);
441  }
442 
450  template <typename T>
452  int wkc = 0;
453  T val = get_status_mappings();
454  // Have to reactivate buffer with map number to valid it
455  wkc += write_sdo(coe::coe_tx_pdo_assign, 0x00, val);
456  return wkc > 0;
457  }
458 
462 
471  void configure_dc_sync0(uint32_t cycle_time_0, int32_t cycle_shift) const;
472 
484  void configure_dc_sync0_1(uint32_t cycle_time_0, uint32_t cycle_time_1,
485  int32_t cycle_shift) const; // time in ns
486 
490 
491  int32_t read_file(std::string_view filename, uint32_t password,
492  int32_t size, uint8_t* buffer) const;
493  bool write_file(std::string_view filename, uint32_t password, int32_t size,
494  uint8_t* buffer) const;
495 
499 
500  bool read_sercos(uint8_t drive, uint8_t flags, uint16_t idn, int32_t size,
501  uint8_t* buffer) const;
502  bool write_sercos(uint8_t drive, uint8_t flags, uint16_t idn, int32_t size,
503  uint8_t* buffer) const;
504 
505 #ifdef EOE_AVAILABLE
506  struct EthernetConfiguration {
510  std::string ip;
511  std::string mask;
512  std::string mac;
513  std::string gateway;
514  std::string dns;
515  };
516 
517  bool detect_ethernet_configuration(uint8_t port,
518  EthernetConfiguration& config);
519  bool configure_ethernet(uint8_t port, const EthernetConfiguration& config);
520 
521  int32_t read_ethernet(uint8_t port, int32_t size, uint8_t* buffer);
522  bool write_ethernet(uint8_t port, int32_t size, uint8_t* buffer);
523 #endif
524 private:
525  friend class Master;
526  friend class SlaveInfo;
527 
532  void print_slave_info() const;
538  uint8_t run_steps() const;
539 
545  void pre_run_step(uint8_t step);
551  void post_run_step(uint8_t step);
552 
558  uint8_t init_steps() const;
559 
566  void pre_init_step(uint8_t step);
567 
573  void post_init_step(uint8_t step);
574 
575  /***
576  * @brief Get the number of end steps for the device
577  *
578  * @return number of end steps
579  */
580  uint8_t end_steps() const;
581 
587  void pre_end_step(uint8_t step);
588 
595  void post_end_step(uint8_t step);
596 
600  void update_buffers();
601 
606 
611 
612  void set_command_mappings(uint8_t mappings);
613  uint8_t get_command_mappings() const;
614  void set_status_mappings(uint8_t mappings);
615  uint8_t get_status_mappings() const;
616 
617  std::vector<Device*> device_vector() final;
618 
619  SlaveInfo* slave_address() final;
620 
621  class Impl;
622  std::unique_ptr<Impl> impl_;
623 
624  // Auxiliary template functions
625  template <typename T>
626  std::tuple<T*> input_buffer_tuple(uint16_t start_addr,
627  size_t ptr_increment) {
628  return std::make_tuple(
629  reinterpret_cast<T*>(input_buffer(start_addr) + ptr_increment));
630  }
631 
632  template <typename T, typename U, typename... Other>
633  std::tuple<T*, U*, Other*...> input_buffer_tuple(uint16_t start_addr,
634  size_t ptr_increment) {
635  return std::tuple_cat(input_buffer_tuple<T>(start_addr, ptr_increment),
636  input_buffer_tuple<U, Other...>(
637  start_addr, ptr_increment + sizeof(T)));
638  }
639 
640  template <typename T>
641  std::tuple<T*> output_buffer_tuple(uint16_t start_addr,
642  size_t ptr_increment) {
643  return std::make_tuple(
644  reinterpret_cast<T*>(output_buffer(start_addr) + ptr_increment));
645  }
646 
647  template <typename T, typename U, typename... Other>
648  std::tuple<T*, U*, Other*...> output_buffer_tuple(uint16_t start_addr,
649  size_t ptr_increment) {
650  return std::tuple_cat(output_buffer_tuple<T>(start_addr, ptr_increment),
651  output_buffer_tuple<U, Other...>(
652  start_addr, ptr_increment + sizeof(T)));
653  }
654 };
655 } // namespace ethercatcpp
ethercatcpp::SlaveDevice::input_buffer
T * input_buffer(uint16_t start_addr)
Get data of input physical buffer.
Definition: slave_device.h:161
ethercatcpp::SlaveDevice::SYNCHROS_IN
@ SYNCHROS_IN
define a synchro buffer in (from slave to master)
Definition: slave_device.h:63
ethercatcpp::SlaveDevice::add_command_pdo_mapping
bool add_command_pdo_mapping(uint16_t pdo_address)
Add a new command PDO map link.
Definition: slave_device.h:375
ethercatcpp::SlaveDevice::output_buffer_tuple
std::tuple< T * > output_buffer_tuple(uint16_t start_addr, size_t ptr_increment)
Definition: slave_device.h:641
ethercatcpp::SlaveDevice::impl_
std::unique_ptr< Impl > impl_
Definition: slave_device.h:621
ethercatcpp::SlaveDevice::start_command_pdo_mapping
bool start_command_pdo_mapping()
Start the definition of the command PDO mapping.
Definition: slave_device.h:359
ethercatcpp::SlaveDevice::post_end_step
void post_end_step(uint8_t step)
Launch the post_function for one specific end step.
ethercatcpp::SlaveDevice::end_steps
uint8_t end_steps() const
ethercatcpp::SlaveDevice::launch_init_configuration
void launch_init_configuration()
Call the init configuration function.
ethercatcpp::SlaveDevice::read_file
int32_t read_file(std::string_view filename, uint32_t password, int32_t size, uint8_t *buffer) const
ethercatcpp::SlaveDevice::set_id
void set_id(const std::string &name, uint32_t manufacturer, uint32_t model)
Set a specific ID to the slave.
ethercatcpp::SlaveDevice::serial_number
uint32_t serial_number() const
Get device serial number.
ethercatcpp::SlaveDevice::ASYNCHROS_OUT
@ ASYNCHROS_OUT
define an asynchro mailbox out (from master to slave)
Definition: slave_device.h:57
ethercatcpp::SlaveDevice::slave_address
SlaveInfo * slave_address() final
Get the device corresponding physical slave address.
ethercatcpp::SlaveDevice::output_buffer
std::tuple< T *, U *, Other *... > output_buffer(uint16_t start_addr)
Definition: slave_device.h:195
ethercatcpp::SlaveDevice::pre_init_step
void pre_init_step(uint8_t step)
Launch the pre_function for one specific init step.
ethercatcpp::SlaveDevice::read_sdo
int read_sdo(uint16_t index, uint8_t sub_index, T &value) const
Send a CoE read SDO packet to the slave.
Definition: slave_device.h:346
ethercatcpp::SlaveDevice::add_end_step
void add_end_step(std::function< void()> &&pre, std::function< void()> &&post)
Add a end step and define pre_function and post_function for this end step.
ethercatcpp::SlaveDevice::syncmanager_buffer_t
syncmanager_buffer_t
This enum define all type of buffers (SyncManager type)
Definition: slave_device.h:56
ethercatcpp::SlaveDevice::input_buffer_tuple
std::tuple< T *, U *, Other *... > input_buffer_tuple(uint16_t start_addr, size_t ptr_increment)
Definition: slave_device.h:633
ethercatcpp::coe::PDOMapping
Represent a CANOpen PDO mapping.
Definition: coe_utilities.h:163
ethercatcpp::coe::coe_tx_pdo_assign
static constexpr uint16_t coe_tx_pdo_assign
Definition: coe_utilities.h:61
ethercatcpp::SlaveDevice::configure_at_init
void configure_at_init(std::function< void()> &&func)
Define the function that configures the slave in PREOP state at initialization of the ethercat bus (M...
device.h
Header file for Device class.
ethercatcpp::SlaveDevice::define_physical_buffer
void define_physical_buffer(syncmanager_buffer_t type, uint16_t start_addr, uint32_t flags)
Define a physical buffer (EtherCAT syncManager buffer).
Definition: slave_device.h:123
ethercatcpp::SlaveDevice::pre_run_step
void pre_run_step(uint8_t step)
Launch the pre_function for one specific run step.
ethercatcpp::SlaveDevice::set_command_mappings
void set_command_mappings(uint8_t mappings)
ethercatcpp::SlaveDevice::update_buffers
void update_buffers()
Update In/Out buffers address.
ethercatcpp::SlaveDevice::SlaveInfo
friend class SlaveInfo
Definition: slave_device.h:526
ethercatcpp::SlaveDevice::start_status_pdo_mapping
bool start_status_pdo_mapping()
Start definition of the status PDO mapping.
Definition: slave_device.h:411
ethercatcpp::Master
This class define The EtherCAT Master.
Definition: master.h:50
ethercatcpp::SlaveDevice::define_period_for_non_cyclic_steps
void define_period_for_non_cyclic_steps(int period)
Define the period between two non cyclic steps.
ethercatcpp::SlaveDevice::end_command_pdo_mapping
bool end_command_pdo_mapping()
Finish the definition of the command PDO mapping.
Definition: slave_device.h:397
ethercatcpp::SlaveDevice::configure_dc_sync0
void configure_dc_sync0(uint32_t cycle_time_0, int32_t cycle_shift) const
Define DC synchro signal 0.
ethercatcpp::SlaveDevice::run_steps
uint8_t run_steps() const
Get the number of run steps for the device.
ethercatcpp::SlaveDevice::device_vector
std::vector< Device * > device_vector() final
Get the vector of sub-devices contained by the device.
ethercatcpp::SlaveDevice::get_command_mappings
uint8_t get_command_mappings() const
coe_utilities.h
Main header file for CoE utilities.
ethercatcpp::SlaveDevice::SYNCHROS_OUT
@ SYNCHROS_OUT
define a synchro buffer out (from master to slave)
Definition: slave_device.h:61
ethercatcpp::SlaveDevice::input_buffer_tuple
std::tuple< T * > input_buffer_tuple(uint16_t start_addr, size_t ptr_increment)
Definition: slave_device.h:626
ethercatcpp::SlaveDevice::write_sdo
int write_sdo(uint16_t index, uint8_t sub_index, T &value) const
Send a CoE write SDO packet to the slave.
Definition: slave_device.h:330
ethercatcpp::SlaveDevice::write_sercos
bool write_sercos(uint8_t drive, uint8_t flags, uint16_t idn, int32_t size, uint8_t *buffer) const
ethercatcpp::SlaveDevice::post_init_step
void post_init_step(uint8_t step)
Launch the post_function for one specific init step.
ethercatcpp::Device
This abstract class define an EtherCAT device.
Definition: device.h:49
ethercatcpp::SlaveDevice::add_run_step
void add_run_step(std::function< void()> &&pre, std::function< void()> &&post)
Add a run step and define pre_function and post_function run step.
ethercatcpp::SlaveDevice::read_sdo
int read_sdo(uint16_t index, uint8_t sub_index, int buffer_size, void *buffer) const
read a SDO capable object field
ethercatcpp::SlaveDevice::output_buffer_tuple
std::tuple< T *, U *, Other *... > output_buffer_tuple(uint16_t start_addr, size_t ptr_increment)
Definition: slave_device.h:648
ethercatcpp::SlaveDevice::configure_at_end
void configure_at_end(std::function< void()> &&func)
Define the function that performs configuration actions in PREOP state at termination of the ethercat...
ethercatcpp::SlaveDevice::get_status_mappings
uint8_t get_status_mappings() const
ethercatcpp::coe::coe_rx_pdo_assign
static constexpr uint16_t coe_rx_pdo_assign
Definition: coe_utilities.h:60
ethercatcpp::SlaveDevice::print_slave_info
void print_slave_info() const
Print all slave informations.
ethercatcpp::SlaveDevice::SlaveDevice
SlaveDevice()
Constructor of SlaveDevice class.
ethercatcpp::SlaveDevice::init_steps
uint8_t init_steps() const
Get the number of init steps for the device.
ethercatcpp::SlaveDevice::configure_dc_sync0_1
void configure_dc_sync0_1(uint32_t cycle_time_0, uint32_t cycle_time_1, int32_t cycle_shift) const
Define DC synchro signals 0 and 1.
ethercatcpp::SlaveDevice::input_buffer
std::tuple< T *, U *, Other *... > input_buffer(uint16_t start_addr)
Definition: slave_device.h:166
ethercatcpp::SlaveDevice::set_status_mappings
void set_status_mappings(uint8_t mappings)
ethercatcpp::SlaveDevice::set_serial_number
void set_serial_number(uint32_t serial_number)
Set the serial number of the device.
ethercatcpp::SlaveDevice::end_status_pdo_mapping
bool end_status_pdo_mapping()
Finish definition of the status PDO mapping.
Definition: slave_device.h:451
ethercatcpp::SlaveDevice::eep_manufacturer
uint32_t eep_manufacturer() const
Get EtherCAT device manufacturer id.
ethercatcpp::coe::PDOBuffer
Definition: coe_utilities.h:299
ethercatcpp::SlaveDevice::write_file
bool write_file(std::string_view filename, uint32_t password, int32_t size, uint8_t *buffer) const
ethercatcpp::SlaveDevice::launch_end_configuration
void launch_end_configuration()
Call the end configuration function.
ethercatcpp::SlaveDevice::ASYNCHROS_IN
@ ASYNCHROS_IN
define an asynchro mailbox in (from slave to master)
Definition: slave_device.h:59
ethercatcpp
ethercatcpp::SlaveDevice::output_buffer
T * output_buffer(uint16_t start_addr)
Get data of output physical buffer.
Definition: slave_device.h:190
ethercatcpp::SlaveDevice::add_status_pdo_mapping
bool add_status_pdo_mapping(uint16_t pdo_address)
Add a new STATUS PDO map link.
Definition: slave_device.h:427
ethercatcpp::SlaveDevice::add_init_step
void add_init_step(std::function< void()> &&pre, std::function< void()> &&post)
Add a init step and define pre_function and post_function for this init step.
ethercatcpp::SlaveDevice
This class define an EtherCAT unit device.
Definition: slave_device.h:53
ethercatcpp::SlaveDevice::eep_device
uint32_t eep_device() const
Get EtherCAT device id.
ethercatcpp::SlaveDevice::~SlaveDevice
virtual ~SlaveDevice()
ethercatcpp::SlaveDevice::post_run_step
void post_run_step(uint8_t step)
Launch the post_function for one specific run step.
ethercatcpp::SlaveDevice::write_sdo
int write_sdo(uint16_t index, uint8_t sub_index, int buffer_size, void *buffer) const
write a SDO capable object field
ethercatcpp::SlaveDevice::read_sercos
bool read_sercos(uint8_t drive, uint8_t flags, uint16_t idn, int32_t size, uint8_t *buffer) const
ethercatcpp::SlaveDevice::define_distributed_clock
void define_distributed_clock(bool have_dc)
Define if the slave have a distributed clock.
ethercatcpp::SlaveDevice::pre_end_step
void pre_end_step(uint8_t step)
Launch the pre_function for one specific end step.