1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165 | /* File: BK1150.cpp
* This file is part of the program ethercatcpp-core
* Program description : EtherCAT driver libraries for UNIX
* Copyright (C) 2017-2024 - Robin Passama (LIRMM / CNRS) Arnaud Meline (LIRMM / CNRS) Benjamin Navarro (LIRMM / CNRS). All Right reserved.
*
* This software is free software: you can redistribute it and/or modify
* it under the terms of the CeCILL-C license as published by
* the CEA CNRS INRIA, either version 1
* of the License, or (at your option) any later version.
* This software 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
* CeCILL-C License for more details.
*
* You should have received a copy of the CeCILL-C License
* along with this software. If not, it can be found on the official website
* of the CeCILL licenses family (http://www.cecill.info/index.en.html).
*/
/**
* @file beckhoff_terminals/BK1150.cpp
* @author Robin Passama
* @brief source file for BK1150 class
*
*/
#include <ethercatcpp/beckhoff_terminals/BK1150.h>
// TODO use the correct address and flags (using device info)
#define OUTPUT_ADDRESS 0x1000
#define INPUT_ADDRESS 0x1700
#define OUTPUT_FLAGS 0x00010024
#define INPUT_FLAGS 0x00010000
#define ASYNCH_OUTPUT_ADDRESS 0x1e00
#define ASYNCH_INPUT_ADDRESS 0x1f00
#define ASYNCH_OUTPUT_FLAGS 0x00010026
#define ASYNCH_INPUT_FLAGS 0x00010022
namespace ethercatcpp {
namespace {
//----------------------------------------------------------------------------//
// M A I L B O X D E F I N I T I O N S //
//----------------------------------------------------------------------------//
// Define output mailbox size
struct [[gnu::packed]] mailbox_out_t {
int8_t mailbox[256];<--- struct member 'mailbox_out_t::mailbox' is never used.
};
// Define input mailbox size
struct [[gnu::packed]] mailbox_in_t {
int8_t mailbox[256];<--- struct member 'mailbox_in_t::mailbox' is never used.
};
} // namespace
BK1150::BK1150() : SlaveDevice() {
set_id("BK1150", 0x00000002, 0x047e2c22);
// Mailboxes configuration (asynchronous communications) -> size of
// mailboxes will always be the same for the BK1150
define_physical_buffer<mailbox_out_t>(
ASYNCHROS_OUT, ASYNCH_OUTPUT_ADDRESS,
ASYNCH_OUTPUT_FLAGS); // address and FLAG (interne ethercat)
define_physical_buffer<mailbox_in_t>(
ASYNCHROS_IN, ASYNCH_INPUT_ADDRESS,
ASYNCH_INPUT_FLAGS); // address and FLAG (interne ethercat)
// Note: mailbox_out_t and mailbox_in_t given by get device info
} // constructor end
uint8_t* BK1150::output(uint8_t index, uint8_t& bit_shift) {
bit_shift = extensions_[index]->bits_shift_out();
uint8_t* returned = output_buffer(OUTPUT_ADDRESS);
returned += extensions_[index]->byte_shift_out();
return (returned);
}
uint8_t* BK1150::input(uint8_t index, uint8_t& bit_shift) {
bit_shift = extensions_[index]->bits_shift_in();
uint8_t* returned = input_buffer(INPUT_ADDRESS);
returned += extensions_[index]->byte_shift_in();
return (returned);
}
void BK1150::update_command_buffer() {
for (const auto& ext : extensions_) {
ext->update_command_buffer();
}
}
void BK1150::unpack_status_buffer() {
for (const auto& ext : extensions_) {
ext->unpack_status_buffer();
}
}
void BK1150::init() { // function used as a kind of "constructor" to finish
// building the dymaically defined object
// HEADER bytes for the BK1150
uint16_t cyclic_size_out = 2, cyclic_size_in = 2;
// WARNING managememory alignement for Beckhoff K BUS
// digital device (e.G. KL2284 ot KL1104):: 1 == input 2 == output => bit
// are aligned in same order non digital (e.g. KL3062) => Word (byte)
// alignement in same order
for (const auto& ext : non_digital_extensions_) {
// memorize bytes (word) and bits shift for each device
// Note: for non digital device bits shift is always 0
ext->set_shifts_out(cyclic_size_out);
ext->set_shifts_In(cyclic_size_in);
cyclic_size_out += ext->size_out();
cyclic_size_in += ext->size_in();
}
// for digital devices the size is given in BITS not in BYTES
uint8_t bits_out = 0, bits_in = 0;
for (const auto& ext : digital_extensions_) {
// memorize bytes (word) and bits shift for each device
// WARNING: for digital device bits shift must be carefully defined
ext->set_shifts_out(cyclic_size_out, bits_out);
ext->set_shifts_In(cyclic_size_in, bits_in);
// updating total size in bytes
// adding size in bytes: dividing bits number by 8
cyclic_size_out +=
static_cast<uint16_t>(ext->size_out() / 8); // 0 or more
cyclic_size_in +=
static_cast<uint16_t>(ext->size_in() / 8); // 0 or more
// memorizing remaining bits
bits_out = ext->size_out() % 8;
bits_in = ext->size_in() % 8;
}
// Note: adding an additional byte if there are remaining bits
cyclic_size_out += (bits_out ? 1 : 0);
cyclic_size_in += (bits_in ? 1 : 0);
// complete work aligment with an extra byte if necessary
if (cyclic_size_out % 2) {
++cyclic_size_out;
}
if (cyclic_size_in % 2) {
++cyclic_size_in;
}
// In/out buffer config
// WARNING : SIZE will change dependending on KL extensions and number
// BUT address and flags are always the same (address is the address of the
// beginning of the BK1150 memory SO will never change)
define_physical_buffer(SYNCHROS_OUT, OUTPUT_ADDRESS, OUTPUT_FLAGS,
cyclic_size_out); // size depand of configured PDO
define_physical_buffer(SYNCHROS_IN, INPUT_ADDRESS, INPUT_FLAGS,
cyclic_size_in); // size depand of configured PDO
//----------------------------------------------------------------------------//
// R U N S S T E P S //
//----------------------------------------------------------------------------//
add_run_step([this]() { update_command_buffer(); },
[this]() { unpack_status_buffer(); }); // add_Run_Step end
}
const std::shared_ptr<KLExtensionCard>&
BK1150::extension(unsigned int index) const {
return (extensions_[index]);
}
} // namespace ethercatcpp
|