dev(UML-1462): Доработал custom tuple и мелкие улучшения
This commit is contained in:
parent
d356b80aac
commit
95f2cc120e
@ -21,7 +21,7 @@ void EthEcatPdoFMMU::init() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void EthEcatPdoFMMU::process() {
|
void EthEcatPdoFMMU::wait_op() {
|
||||||
free_rtos::Semaphore& init_sem = ecat_buffer_.get_ecat().get_init_sem();
|
free_rtos::Semaphore& init_sem = ecat_buffer_.get_ecat().get_init_sem();
|
||||||
free_rtos::Semaphore& process_sem = ecat_buffer_.get_ecat().get_process_sem();
|
free_rtos::Semaphore& process_sem = ecat_buffer_.get_ecat().get_process_sem();
|
||||||
std::array<std::array<uint8_t, 55>, 2> process_data;
|
std::array<std::array<uint8_t, 55>, 2> process_data;
|
||||||
@ -31,44 +31,50 @@ void EthEcatPdoFMMU::process() {
|
|||||||
process_data[0].fill(0x00);
|
process_data[0].fill(0x00);
|
||||||
process_data[1].fill(0x00);
|
process_data[1].fill(0x00);
|
||||||
|
|
||||||
read(0, process_data[0], process_data[1]);
|
read(process_data[0], process_data[1]);
|
||||||
|
/*
|
||||||
for(uint8_t& byte : process_data[0]) {
|
for(uint8_t& byte : process_data[0]) {
|
||||||
DebugP_log("0x%01x", byte);
|
DebugP_log("0x%01x", byte);
|
||||||
}
|
}
|
||||||
DebugP_log("\r\n");
|
DebugP_log("\r\n");
|
||||||
|
*/
|
||||||
write(0, process_data[0], process_data[1]);
|
write(process_data[0], process_data[1]);
|
||||||
|
|
||||||
init_sem.post();
|
init_sem.post();
|
||||||
process_sem.pend();
|
process_sem.pend();
|
||||||
|
|
||||||
for(uint32_t i = 0; i < 250; i++) {
|
for(uint32_t i = 0; i < 250; i++) {
|
||||||
read(0, process_data[0], process_data[1]);
|
read(process_data[0], process_data[1]);
|
||||||
|
/*
|
||||||
for(uint8_t& byte : process_data[0]) {
|
for(uint8_t& byte : process_data[0]) {
|
||||||
DebugP_log("0x%01x", byte);
|
DebugP_log("0x%01x", byte);
|
||||||
}
|
}
|
||||||
DebugP_log("\r\n");
|
DebugP_log("\r\n");
|
||||||
|
*/
|
||||||
write(0, process_data[0], process_data[1]);
|
write(process_data[0], process_data[1]);
|
||||||
|
|
||||||
//ClockP_usleep(125ul);
|
//ClockP_usleep(125ul);
|
||||||
}
|
}
|
||||||
|
|
||||||
init_sem.post();
|
init_sem.post();
|
||||||
process_sem.pend();
|
process_sem.pend();
|
||||||
|
}
|
||||||
|
|
||||||
|
void EthEcatPdoFMMU::process() {
|
||||||
|
std::array<std::array<uint8_t, 55>, 2> process_data;
|
||||||
|
|
||||||
|
wait_op();
|
||||||
|
|
||||||
while(1)
|
while(1)
|
||||||
{
|
{
|
||||||
read(0, process_data[0], process_data[1]);
|
read(process_data[0], process_data[1]);
|
||||||
|
/*
|
||||||
for(uint8_t& byte : process_data[0]) {
|
for(uint8_t& byte : process_data[0]) {
|
||||||
DebugP_log("0x%01x", byte);
|
DebugP_log("0x%01x", byte);
|
||||||
}
|
}
|
||||||
DebugP_log("\r\n");
|
DebugP_log("\r\n");
|
||||||
|
*/
|
||||||
write(0, process_data[0], process_data[1]);
|
write(process_data[0], process_data[1]);
|
||||||
|
|
||||||
//ClockP_usleep(125ul);
|
//ClockP_usleep(125ul);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -48,55 +48,71 @@ private:
|
|||||||
};
|
};
|
||||||
|
|
||||||
class EthEcatPdoFMMU {
|
class EthEcatPdoFMMU {
|
||||||
public:
|
private:
|
||||||
EthEcatPdoFMMU(ecat_buffer::EthEcatBuffer& ecat_mailbox): ecat_buffer_{ecat_mailbox} { }
|
|
||||||
|
|
||||||
void init();
|
|
||||||
|
|
||||||
template<typename... DataTypes>
|
template<typename... DataTypes>
|
||||||
void write(size_t slave_index, DataTypes&... data);
|
void write_recursion(datagram::EcatTelegram& telegram, size_t slave_index, DataTypes&... data);
|
||||||
|
|
||||||
template<typename DataType, typename... DataTypes>
|
template<typename DataType, typename... DataTypes>
|
||||||
void write(size_t slave_index, DataType& head, DataTypes&... tail) {
|
void write_recursion(datagram::EcatTelegram& telegram, size_t slave_index, DataType& head, DataTypes&... tail) {
|
||||||
datagram::EcatTelegram& telegram = ecat_buffer_.get_ecat().get_telegram();
|
|
||||||
|
|
||||||
pdo_fmmu_slaves_[slave_index].write(telegram, head);
|
pdo_fmmu_slaves_[slave_index].write(telegram, head);
|
||||||
|
|
||||||
slave_index++;
|
slave_index++;
|
||||||
|
|
||||||
if(slave_index < pdo_fmmu_slaves_.size()) {
|
write_recursion(telegram, slave_index, tail...);
|
||||||
write(slave_index, tail...);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
void write(size_t slave_index) { }
|
void write_recursion(datagram::EcatTelegram& telegram, size_t slave_index) { }
|
||||||
|
|
||||||
template<typename... DataTypes>
|
template<typename... DataTypes>
|
||||||
void read(size_t slave_index, DataTypes&... data);
|
void read_recursion(datagram::EcatTelegram& telegram, size_t slave_index, DataTypes&... data);
|
||||||
|
|
||||||
template<typename DataType, typename... DataTypes>
|
template<typename DataType, typename... DataTypes>
|
||||||
void read(size_t slave_index, DataType& head, DataTypes&... tail) {
|
void read_recursion(datagram::EcatTelegram& telegram, size_t slave_index, DataType& head, DataTypes&... tail) {
|
||||||
datagram::EcatTelegram& telegram = ecat_buffer_.get_ecat().get_telegram();
|
|
||||||
|
|
||||||
pdo_fmmu_slaves_[slave_index].read(telegram, head);
|
pdo_fmmu_slaves_[slave_index].read(telegram, head);
|
||||||
|
|
||||||
slave_index++;
|
slave_index++;
|
||||||
|
|
||||||
if(slave_index < pdo_fmmu_slaves_.size()) {
|
read_recursion(telegram, slave_index, tail...);
|
||||||
read(slave_index, tail...);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
void read(size_t slave_index) { }
|
void read_recursion(datagram::EcatTelegram& telegram, size_t slave_index) { }
|
||||||
|
|
||||||
|
public:
|
||||||
|
EthEcatPdoFMMU(ecat_buffer::EthEcatBuffer& ecat_mailbox): ecat_buffer_{ecat_mailbox} { }
|
||||||
|
|
||||||
|
void init();
|
||||||
void process();
|
void process();
|
||||||
|
|
||||||
|
template<typename... DataTypes>
|
||||||
|
void write(DataTypes&... data) {
|
||||||
|
datagram::EcatTelegram& telegram = ecat_buffer_.get_ecat().get_telegram();
|
||||||
|
|
||||||
|
if(sizeof...(data) > pdo_fmmu_slaves_.size()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
write_recursion(telegram, 0, data...);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename... DataTypes>
|
||||||
|
void read(DataTypes&... data) {
|
||||||
|
datagram::EcatTelegram& telegram = ecat_buffer_.get_ecat().get_telegram();
|
||||||
|
|
||||||
|
if(sizeof...(data) > pdo_fmmu_slaves_.size()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
read_recursion(telegram, 0, data...);
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
ecat_buffer::EthEcatBuffer& ecat_buffer_;
|
ecat_buffer::EthEcatBuffer& ecat_buffer_;
|
||||||
|
|
||||||
std::vector<EcatPdoFMMUSlave> pdo_fmmu_slaves_;
|
std::vector<EcatPdoFMMUSlave> pdo_fmmu_slaves_;
|
||||||
|
|
||||||
|
void wait_op();
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace ecat_pdo_fmmu
|
} // namespace ecat_pdo_fmmu
|
||||||
|
|||||||
@ -106,17 +106,17 @@ struct MailboxHeader {
|
|||||||
|
|
||||||
// Специализация шаблона для распаковки протокола CoE
|
// Специализация шаблона для распаковки протокола CoE
|
||||||
template<typename... TailT>
|
template<typename... TailT>
|
||||||
struct CustomTuple<ecat_sdo_mailbox::CoEElements, ecat_sdo_mailbox::CompleteSize, TailT...> : CustomTuple<TailT...> {
|
struct custom_tuple<ecat_sdo_mailbox::CoEElements&, ecat_sdo_mailbox::CompleteSize&, TailT...> : custom_tuple<TailT...> {
|
||||||
CustomTuple(ecat_sdo_mailbox::CoEElements& head, ecat_sdo_mailbox::CompleteSize& complete_size, TailT&... tail)
|
custom_tuple(ecat_sdo_mailbox::CoEElements& head, ecat_sdo_mailbox::CompleteSize& complete_size, TailT... tail)
|
||||||
: CustomTuple<TailT...>(tail...)
|
: custom_tuple<TailT...>(tail...)
|
||||||
, head_(head)
|
, head_(head)
|
||||||
, complete_size_(complete_size) { }
|
, complete_size_(complete_size) { }
|
||||||
|
|
||||||
using TBase = CustomTuple<TailT...>;
|
using TBase = custom_tuple<TailT...>;
|
||||||
|
|
||||||
constexpr static size_t size = sizeof(ecat_sdo_mailbox::CoEElements) + sizeof(ecat_sdo_mailbox::CompleteSize) + TBase::size;
|
constexpr static size_t size = sizeof(ecat_sdo_mailbox::CoEElements) + sizeof(ecat_sdo_mailbox::CompleteSize) + TBase::size;
|
||||||
|
|
||||||
TBase& base_ = static_cast<TBase&>(*this);
|
//TBase& base_ = static_cast<TBase&>(*this);
|
||||||
ecat_sdo_mailbox::CoEElements& head_;
|
ecat_sdo_mailbox::CoEElements& head_;
|
||||||
ecat_sdo_mailbox::CompleteSize& complete_size_;
|
ecat_sdo_mailbox::CompleteSize& complete_size_;
|
||||||
|
|
||||||
@ -127,13 +127,13 @@ struct CustomTuple<ecat_sdo_mailbox::CoEElements, ecat_sdo_mailbox::CompleteSize
|
|||||||
(void)complete_size;
|
(void)complete_size;
|
||||||
|
|
||||||
raw += sizeof(ecat_sdo_mailbox::CompleteSize);
|
raw += sizeof(ecat_sdo_mailbox::CompleteSize);
|
||||||
raw = base_.pack(raw);
|
raw = TBase::pack(raw);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(head_.command_specifier.transfer_type == static_cast<uint8_t>(ecat_sdo_mailbox::TransferType::EXPEDITED)) {
|
if(head_.command_specifier.transfer_type == static_cast<uint8_t>(ecat_sdo_mailbox::TransferType::EXPEDITED)) {
|
||||||
// По-нормальному мы не должны сюда попадать, т.к. в expedited транзакции не должно быть блока CompleteSize,
|
// По-нормальному мы не должны сюда попадать, т.к. в expedited транзакции не должно быть блока CompleteSize,
|
||||||
// значит либо пользователь ошибся, либо после предыдущей отправки датаграммы слейв указал тип expedited
|
// значит либо пользователь ошибся, либо после предыдущей отправки датаграммы слейв указал тип expedited
|
||||||
raw = base_.pack(raw);
|
raw = TBase::pack(raw);
|
||||||
raw += sizeof(ecat_sdo_mailbox::CompleteSize);
|
raw += sizeof(ecat_sdo_mailbox::CompleteSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -155,11 +155,11 @@ struct CustomTuple<ecat_sdo_mailbox::CoEElements, ecat_sdo_mailbox::CompleteSize
|
|||||||
complete_size_ = *complete_size;
|
complete_size_ = *complete_size;
|
||||||
|
|
||||||
raw += sizeof(ecat_sdo_mailbox::CompleteSize);
|
raw += sizeof(ecat_sdo_mailbox::CompleteSize);
|
||||||
raw = base_.unpack(raw);
|
raw = TBase::unpack(raw);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(head_.command_specifier.transfer_type == static_cast<uint8_t>(ecat_sdo_mailbox::TransferType::EXPEDITED)) {
|
if(head_.command_specifier.transfer_type == static_cast<uint8_t>(ecat_sdo_mailbox::TransferType::EXPEDITED)) {
|
||||||
raw = base_.unpack(raw);
|
raw = TBase::unpack(raw);
|
||||||
raw += sizeof(ecat_sdo_mailbox::CompleteSize);
|
raw += sizeof(ecat_sdo_mailbox::CompleteSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -239,7 +239,7 @@ public:
|
|||||||
auto slave_address = slave.get_slave_address<TypeT>();
|
auto slave_address = slave.get_slave_address<TypeT>();
|
||||||
std::array<address::Offset, 4>& buffer_regs = buffer_slave_.get_buffer_regs();
|
std::array<address::Offset, 4>& buffer_regs = buffer_slave_.get_buffer_regs();
|
||||||
MailboxHeader header{
|
MailboxHeader header{
|
||||||
.length = CustomTuple<DataTypes...>::size,
|
.length = custom_tuple<DataTypes...>::size,
|
||||||
.address = 0, // slave.get_slave_address<command::FP>()
|
.address = 0, // slave.get_slave_address<command::FP>()
|
||||||
.channel = channel,
|
.channel = channel,
|
||||||
.priority = priority,
|
.priority = priority,
|
||||||
@ -247,7 +247,7 @@ public:
|
|||||||
.cnt = static_cast<uint16_t>(counter_)
|
.cnt = static_cast<uint16_t>(counter_)
|
||||||
};
|
};
|
||||||
datagram::EcatDatagram<TCommand, MailboxHeader, DataTypes...> datagram{ {{slave_address, buffer_regs[MailboxesRegs::WRITE]}}, header, data... };
|
datagram::EcatDatagram<TCommand, MailboxHeader, DataTypes...> datagram{ {{slave_address, buffer_regs[MailboxesRegs::WRITE]}}, header, data... };
|
||||||
uint16_t padding = buffer_slave_.get_buffer_properties_write().length - sizeof(MailboxHeader) - CustomTuple<DataTypes...>::size;
|
uint16_t padding = buffer_slave_.get_buffer_properties_write().length - sizeof(MailboxHeader) - custom_tuple<DataTypes...>::size;
|
||||||
|
|
||||||
datagram.set_padding(padding);
|
datagram.set_padding(padding);
|
||||||
|
|
||||||
@ -266,7 +266,7 @@ public:
|
|||||||
std::array<address::Offset, 4>& buffer_regs = buffer_slave_.get_buffer_regs();
|
std::array<address::Offset, 4>& buffer_regs = buffer_slave_.get_buffer_regs();
|
||||||
MailboxHeader header;
|
MailboxHeader header;
|
||||||
datagram::EcatDatagram<TCommand, MailboxHeader, DataTypes...> datagram{ {{slave_address, buffer_regs[MailboxesRegs::READ]}}, header, data... };
|
datagram::EcatDatagram<TCommand, MailboxHeader, DataTypes...> datagram{ {{slave_address, buffer_regs[MailboxesRegs::READ]}}, header, data... };
|
||||||
uint16_t padding = buffer_slave_.get_buffer_properties_read().length - sizeof(MailboxHeader) - CustomTuple<DataTypes...>::size;
|
uint16_t padding = buffer_slave_.get_buffer_properties_read().length - sizeof(MailboxHeader) - custom_tuple<DataTypes...>::size;
|
||||||
|
|
||||||
datagram.set_padding(padding);
|
datagram.set_padding(padding);
|
||||||
|
|
||||||
|
|||||||
@ -125,20 +125,20 @@ void EthEcat::set_slaves_to_default() {
|
|||||||
uint8_t m_data_out{0x00};
|
uint8_t m_data_out{0x00};
|
||||||
datagram::EcatDatagram<command::BWR, uint8_t> m{ {{broadcast, ECT_REG_EEPCFG}}, m_data_out };
|
datagram::EcatDatagram<command::BWR, uint8_t> m{ {{broadcast, ECT_REG_EEPCFG}}, m_data_out };
|
||||||
|
|
||||||
//a + b + c + d + e + f + g + h + i + j + k + l + m;
|
a + b + c + d + e + f + g + h + i + j + k + l + m;
|
||||||
telegram_.transfer(a);
|
telegram_.transfer(a);
|
||||||
telegram_.transfer(b);
|
//telegram_.transfer(b);
|
||||||
telegram_.transfer(c);
|
//telegram_.transfer(c);
|
||||||
telegram_.transfer(d);
|
//telegram_.transfer(d);
|
||||||
telegram_.transfer(e);
|
//telegram_.transfer(e);
|
||||||
telegram_.transfer(f);
|
//telegram_.transfer(f);
|
||||||
telegram_.transfer(g);
|
//telegram_.transfer(g);
|
||||||
telegram_.transfer(h);
|
//telegram_.transfer(h);
|
||||||
telegram_.transfer(i);
|
//telegram_.transfer(i);
|
||||||
telegram_.transfer(j);
|
//telegram_.transfer(j);
|
||||||
telegram_.transfer(k);
|
//telegram_.transfer(k);
|
||||||
telegram_.transfer(l);
|
//telegram_.transfer(l);
|
||||||
telegram_.transfer(m);
|
//telegram_.transfer(m);
|
||||||
|
|
||||||
DebugP_log("a.get_wkc() = %d\r\n", a.get_wkc());
|
DebugP_log("a.get_wkc() = %d\r\n", a.get_wkc());
|
||||||
DebugP_log("b.get_wkc() = %d\r\n", b.get_wkc());
|
DebugP_log("b.get_wkc() = %d\r\n", b.get_wkc());
|
||||||
@ -157,8 +157,8 @@ void EthEcat::set_slaves_to_default() {
|
|||||||
|
|
||||||
uint16_t EthEcat::slaves_detecting() {
|
uint16_t EthEcat::slaves_detecting() {
|
||||||
address::Broadcast broadcast{0x0000};
|
address::Broadcast broadcast{0x0000};
|
||||||
uint16_t data_out{0x0000};
|
uint16_t data{0x0000};
|
||||||
datagram::EcatDatagram<command::BRD, uint16_t> datagram{ {{broadcast, ECT_REG_TYPE}}, data_out };
|
datagram::EcatDatagram<command::BRD, uint16_t> datagram{ {{broadcast, ECT_REG_TYPE}}, data };
|
||||||
|
|
||||||
telegram_.transfer(datagram);
|
telegram_.transfer(datagram);
|
||||||
|
|
||||||
|
|||||||
@ -43,12 +43,12 @@ public:
|
|||||||
|
|
||||||
template<typename TypeT>
|
template<typename TypeT>
|
||||||
void set_slave_address(typename TypeT::TSlaveAddress&& slave_address) {
|
void set_slave_address(typename TypeT::TSlaveAddress&& slave_address) {
|
||||||
std::get<static_cast<size_t>(TypeT::type)>(slave_addresses_) = slave_address;
|
free_rtos::get<static_cast<size_t>(TypeT::type)>(slave_addresses_) = slave_address;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename TypeT>
|
template<typename TypeT>
|
||||||
typename TypeT::TSlaveAddress& get_slave_address() {
|
typename TypeT::TSlaveAddress& get_slave_address() {
|
||||||
return std::get<static_cast<size_t>(TypeT::type)>(slave_addresses_);
|
return free_rtos::get<static_cast<size_t>(TypeT::type)>(slave_addresses_);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename TypeT>
|
template<typename TypeT>
|
||||||
@ -266,8 +266,6 @@ private:
|
|||||||
e_pktTotal
|
e_pktTotal
|
||||||
};
|
};
|
||||||
|
|
||||||
static constexpr uint16_t max_number_of_slaves = 32;
|
|
||||||
|
|
||||||
TEthPkt * p_pkt_;
|
TEthPkt * p_pkt_;
|
||||||
TEthPkt * p_pkt_next_;
|
TEthPkt * p_pkt_next_;
|
||||||
|
|
||||||
|
|||||||
@ -10,11 +10,11 @@
|
|||||||
|
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <array>
|
#include <array>
|
||||||
#include <tuple>
|
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
|
|
||||||
#include "ethernet_industry/ethercattype.hpp"
|
#include "ethernet_industry/ethercattype.hpp"
|
||||||
#include "ethernet_industry/eth_ecat_types.h"
|
#include "ethernet_industry/eth_ecat_types.h"
|
||||||
|
#include "ethernet_industry/eth_ecat_custom_tuple.hpp"
|
||||||
|
|
||||||
namespace free_rtos {
|
namespace free_rtos {
|
||||||
|
|
||||||
@ -26,17 +26,17 @@ using Broadcast = uint16_t;
|
|||||||
using Station = uint16_t;
|
using Station = uint16_t;
|
||||||
using Logical = uint32_t;
|
using Logical = uint32_t;
|
||||||
|
|
||||||
using SlaveAddresses = std::tuple<Position, Broadcast, Station, Logical>;
|
using SlaveAddresses = free_rtos::custom_tuple<Position, Broadcast, Station, Logical>;
|
||||||
|
|
||||||
// Register offset
|
// Register offset
|
||||||
using Offset = uint16_t;
|
using Offset = uint16_t;
|
||||||
|
|
||||||
using PositionAddress = std::tuple<Position, Offset>;
|
using PositionAddress = free_rtos::custom_tuple<Position, Offset>;
|
||||||
using BroadcastAddress = std::tuple<Broadcast, Offset>;
|
using BroadcastAddress = free_rtos::custom_tuple<Broadcast, Offset>;
|
||||||
using StationAddress = std::tuple<Station, Offset>;
|
using StationAddress = free_rtos::custom_tuple<Station, Offset>;
|
||||||
using LogicalAddress = std::tuple<Logical>;
|
using LogicalAddress = free_rtos::custom_tuple<Logical>;
|
||||||
|
|
||||||
using Addresses = std::tuple<PositionAddress, BroadcastAddress, StationAddress, LogicalAddress>;
|
using Addresses = free_rtos::custom_tuple<PositionAddress, BroadcastAddress, StationAddress, LogicalAddress>;
|
||||||
|
|
||||||
} // namespace address
|
} // namespace address
|
||||||
|
|
||||||
@ -79,12 +79,33 @@ struct TypeBase {
|
|||||||
|
|
||||||
template<TYPE_INDEX type_index>
|
template<TYPE_INDEX type_index>
|
||||||
struct Type : public TypeBase {
|
struct Type : public TypeBase {
|
||||||
using TAddress = typename std::tuple_element<static_cast<size_t>(type_index), address::Addresses>::type;
|
using TAddress = typename free_rtos::custom_tuple_element<static_cast<size_t>(type_index), address::Addresses>::type;
|
||||||
using TSlaveAddress = typename std::tuple_element<0, TAddress>::type;
|
using TSlaveAddress = typename free_rtos::custom_tuple_element<0, TAddress>::type;
|
||||||
|
|
||||||
static constexpr TYPE_INDEX type = type_index;
|
static constexpr TYPE_INDEX type = type_index;
|
||||||
|
};
|
||||||
|
|
||||||
static constexpr ec_cmdtype get_cmd(DIR_INDEX dir) {
|
using AP = Type<TYPE_INDEX::AP>;
|
||||||
|
using B = Type<TYPE_INDEX::B>;
|
||||||
|
using FP = Type<TYPE_INDEX::FP>;
|
||||||
|
using L = Type<TYPE_INDEX::L>;
|
||||||
|
|
||||||
|
class EcatCommandBase {
|
||||||
|
public:
|
||||||
|
EcatCommandBase(TYPE_INDEX type, DIR_INDEX dir)
|
||||||
|
: cmd_{get_cmd_from_table(type, dir)} { }
|
||||||
|
|
||||||
|
EcatCommandBase()
|
||||||
|
: cmd_{ec_cmdtype::EC_CMD_NOP} { }
|
||||||
|
|
||||||
|
uint8_t get_cmd() {
|
||||||
|
return cmd_;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
ec_cmdtype cmd_;
|
||||||
|
|
||||||
|
static constexpr ec_cmdtype get_cmd_from_table(TYPE_INDEX type, DIR_INDEX dir) {
|
||||||
std::array<std::array<ec_cmdtype, 4>, 4> commands = {{
|
std::array<std::array<ec_cmdtype, 4>, 4> commands = {{
|
||||||
{{EC_CMD_APRD, EC_CMD_APWR, EC_CMD_APRW, EC_CMD_ARMW}},
|
{{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_BRD, EC_CMD_BWR, EC_CMD_BRW, EC_CMD_NOP}},
|
||||||
@ -96,63 +117,29 @@ struct Type : public TypeBase {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
using AP = Type<TYPE_INDEX::AP>;
|
|
||||||
using B = Type<TYPE_INDEX::B>;
|
|
||||||
using FP = Type<TYPE_INDEX::FP>;
|
|
||||||
using L = Type<TYPE_INDEX::L>;
|
|
||||||
|
|
||||||
class EcatCommandBase {
|
|
||||||
public:
|
|
||||||
EcatCommandBase(ec_cmdtype cmd)
|
|
||||||
: cmd_{cmd} { }
|
|
||||||
|
|
||||||
EcatCommandBase()
|
|
||||||
: cmd_{ec_cmdtype::EC_CMD_NOP} { }
|
|
||||||
|
|
||||||
uint8_t get_cmd() {
|
|
||||||
return cmd_;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
ec_cmdtype cmd_;
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename TypeT, typename DirT>
|
template<typename TypeT, typename DirT>
|
||||||
class EcatCommand : public EcatCommandBase {
|
class EcatCommand : public EcatCommandBase {
|
||||||
static_assert(std::is_base_of<TypeBase, TypeT>::value == true, "TypeT should be derived from command::TypeBase");
|
static_assert(std::is_base_of<TypeBase, TypeT>::value == true, "TypeT should be derived from command::TypeBase");
|
||||||
static_assert(std::is_base_of<DirBase, DirT>::value == true, "DirT should be derived from command::DirBase");
|
static_assert(std::is_base_of<DirBase, DirT>::value == true, "DirT should be derived from command::DirBase");
|
||||||
|
|
||||||
public:
|
public:
|
||||||
EcatCommand(typename TypeT::TAddress fields)
|
EcatCommand(typename TypeT::TAddress address)
|
||||||
: EcatCommandBase{TypeT::get_cmd(DirT::dir)}
|
: EcatCommandBase{TypeT::type, DirT::dir}
|
||||||
, address_union_{fields} { }
|
, address_{address} { }
|
||||||
|
|
||||||
EcatCommand() { }
|
EcatCommand() { }
|
||||||
|
|
||||||
uint32_t get_address() {
|
uint32_t get_address() {
|
||||||
return address_union_.dword_;
|
uint32_t address{0x00000000};
|
||||||
|
|
||||||
|
address_.pack(reinterpret_cast<uint8_t*>(&address));
|
||||||
|
|
||||||
|
return address;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
template<typename FieldsT>
|
|
||||||
union AddressUnion
|
|
||||||
{
|
|
||||||
AddressUnion(FieldsT fields)
|
|
||||||
: fields_{fields} { }
|
|
||||||
|
|
||||||
AddressUnion() { }
|
typename TypeT::TAddress address_;
|
||||||
|
|
||||||
AddressUnion& operator=(const AddressUnion& other) {
|
|
||||||
fields_ = other.fields_;
|
|
||||||
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
FieldsT fields_;
|
|
||||||
uint32_t dword_;
|
|
||||||
};
|
|
||||||
|
|
||||||
AddressUnion<typename TypeT::TAddress> address_union_;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|||||||
@ -12,42 +12,47 @@ namespace free_rtos {
|
|||||||
|
|
||||||
// Базовый шаблон класса, никогда не инстанциируется, поэтому без тела
|
// Базовый шаблон класса, никогда не инстанциируется, поэтому без тела
|
||||||
template<typename... Args>
|
template<typename... Args>
|
||||||
struct CustomTuple;
|
struct custom_tuple;
|
||||||
|
|
||||||
// Основная специализация шаблона. Есть еще одна для протокола CoE.
|
// Основная специализация шаблона. Есть еще одна для протокола CoE.
|
||||||
template<typename HeadT, typename... TailT>
|
template<typename HeadT, typename... TailT>
|
||||||
struct CustomTuple<HeadT, TailT...> : CustomTuple<TailT...> {
|
struct custom_tuple<HeadT, TailT...> : custom_tuple<TailT...> {
|
||||||
CustomTuple(HeadT& head, TailT&... tail)
|
custom_tuple(HeadT head, TailT... tail)
|
||||||
: CustomTuple<TailT...>(tail...)
|
: custom_tuple<TailT...>(tail...)
|
||||||
, head_(head) { }
|
, head_(head) { }
|
||||||
|
|
||||||
using TBase = CustomTuple<TailT...>;
|
custom_tuple()
|
||||||
|
: custom_tuple<TailT...>() { }
|
||||||
|
|
||||||
constexpr static size_t size = sizeof(HeadT) + TBase::size;
|
using TBase = custom_tuple<TailT...>;
|
||||||
|
using THead = HeadT;
|
||||||
|
using THeadDeref = typename std::remove_reference<THead>::type;
|
||||||
|
|
||||||
TBase& base_ = static_cast<TBase&>(*this);
|
constexpr static size_t size = sizeof(THeadDeref) + TBase::size;
|
||||||
HeadT& head_;
|
|
||||||
|
//TBase& base_ = static_cast<TBase&>(*this);
|
||||||
|
THead head_;
|
||||||
|
|
||||||
uint8_t* pack(uint8_t *raw) {
|
uint8_t* pack(uint8_t *raw) {
|
||||||
HeadT *head = new(raw) HeadT{head_};
|
THeadDeref *head = new(raw) THeadDeref{head_};
|
||||||
|
|
||||||
(void)head;
|
(void)head;
|
||||||
|
|
||||||
return base_.pack(raw + sizeof(HeadT));
|
return TBase::pack(raw + sizeof(THeadDeref));
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t* unpack(uint8_t *raw) {
|
uint8_t* unpack(uint8_t *raw) {
|
||||||
HeadT *head = reinterpret_cast<HeadT*>(raw);
|
THeadDeref *head = reinterpret_cast<THeadDeref*>(raw);
|
||||||
|
|
||||||
head_ = *head;
|
head_ = *head;
|
||||||
|
|
||||||
return base_.unpack(raw + sizeof(HeadT));
|
return TBase::unpack(raw + sizeof(THeadDeref));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Специализация завершения рекурсии
|
// Специализация завершения рекурсии
|
||||||
template<>
|
template<>
|
||||||
struct CustomTuple<> {
|
struct custom_tuple<> {
|
||||||
constexpr static size_t size = 0;
|
constexpr static size_t size = 0;
|
||||||
|
|
||||||
uint8_t* pack(uint8_t *raw) {
|
uint8_t* pack(uint8_t *raw) {
|
||||||
@ -59,8 +64,33 @@ struct CustomTuple<> {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template<size_t index, typename TupleT>
|
||||||
|
struct custom_tuple_element;
|
||||||
|
|
||||||
|
template<size_t index, typename HeadT, typename... TailT>
|
||||||
|
struct custom_tuple_element<index, custom_tuple<HeadT, TailT...>> {
|
||||||
|
using TBase = custom_tuple_element<index - 1, custom_tuple<TailT...>>;
|
||||||
|
using type = typename TBase::type;
|
||||||
|
|
||||||
|
static type& get(custom_tuple<HeadT, TailT...>& t) {
|
||||||
|
return TBase::get(t);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename HeadT, typename... TailT>
|
||||||
|
struct custom_tuple_element<0, custom_tuple<HeadT, TailT...>> {
|
||||||
|
using type = HeadT;
|
||||||
|
|
||||||
|
static type& get(custom_tuple<HeadT, TailT...>& t) {
|
||||||
|
return t.head_;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template<size_t index, typename TupleT>
|
||||||
|
typename custom_tuple_element<index, TupleT>::type& get(TupleT& t) {
|
||||||
|
return custom_tuple_element<index, TupleT>::get(t);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
#endif /* FREE_RTOS_ETHERNET_INDUSTRY_ETH_ECAT_CUSTOM_TUPLE_HPP_ */
|
#endif /* FREE_RTOS_ETHERNET_INDUSTRY_ETH_ECAT_CUSTOM_TUPLE_HPP_ */
|
||||||
|
|||||||
@ -13,8 +13,8 @@
|
|||||||
#include "ethernet/eth.hpp"
|
#include "ethernet/eth.hpp"
|
||||||
#include "ethernet_industry/ethercattype.hpp"
|
#include "ethernet_industry/ethercattype.hpp"
|
||||||
#include "ethernet_industry/eth_ecat_types.h"
|
#include "ethernet_industry/eth_ecat_types.h"
|
||||||
#include "ethernet_industry/eth_ecat_command.hpp"
|
|
||||||
#include "ethernet_industry/eth_ecat_custom_tuple.hpp"
|
#include "ethernet_industry/eth_ecat_custom_tuple.hpp"
|
||||||
|
#include "ethernet_industry/eth_ecat_command.hpp"
|
||||||
|
|
||||||
namespace free_rtos {
|
namespace free_rtos {
|
||||||
|
|
||||||
@ -95,7 +95,7 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
CommandT command_;
|
CommandT command_;
|
||||||
CustomTuple<DataTypes...> data_;
|
custom_tuple<DataTypes&...> data_;
|
||||||
|
|
||||||
uint8_t* pack_wkc(uint8_t *raw) {
|
uint8_t* pack_wkc(uint8_t *raw) {
|
||||||
TEcatWkc *wkc = new(raw) TEcatWkc{0x0000};
|
TEcatWkc *wkc = new(raw) TEcatWkc{0x0000};
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user