KaCanOpen
 All Classes Functions Variables Typedefs Enumerations Pages
transmit_pdo_mapping.cpp
1 /*
2  * Copyright (c) 2015, Thomas Keh
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are met:
7  *
8  * 1. Redistributions of source code must retain the above copyright
9  * notice, this list of conditions and the following disclaimer.
10  *
11  * 2. Redistributions in binary form must reproduce the above copyright
12  * notice, this list of conditions and the following disclaimer in the
13  * documentation and/or other materials provided with the distribution.
14  *
15  * 3. Neither the name of the copyright holder nor the names of its
16  * contributors may be used to endorse or promote products derived from
17  * this software without specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
23  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29  * POSSIBILITY OF SUCH DAMAGE.
30  */
31 
32 #include "transmit_pdo_mapping.h"
33 #include "core.h"
34 #include "entry.h"
35 #include "logger.h"
36 #include "dictionary_error.h"
37 
38 #include <cassert>
39 
40 namespace kaco {
41 
42 TransmitPDOMapping::TransmitPDOMapping(Core& core, const std::unordered_map<Address, Entry>& dictionary, const std::unordered_map<std::string, Address>& name_to_address,
43  uint16_t cob_id_, TransmissionType transmission_type_, std::chrono::milliseconds repeat_time_, const std::vector<Mapping>& mappings_)
44  : cob_id(cob_id_),
45  transmission_type(transmission_type_),
46  repeat_time(repeat_time_),
47  mappings(mappings_),
48  m_core(core),
49  m_dictionary(dictionary),
50  m_name_to_address(name_to_address)
51  {
52  check_correctness();
53  }
54 
56  if (transmitter) {
57  transmitter->detach();
58  }
59 }
60 
61 
63 
64  std::vector<uint8_t> data(8,0);
65  size_t max_byte=0;
66 
67  DEBUG_LOG("[TransmitPDOMapping::send] Sending transmit PDO with cob_id 0x"<<std::hex<<cob_id);
68 
69  for (const Mapping& mapping : mappings) {
70 
71  const std::string entry_name = Utils::escape(mapping.entry_name);
72  const Entry& entry = m_dictionary.at(m_name_to_address.at(entry_name));
73  const Value& value = entry.get_value();
74  const std::vector<uint8_t> bytes = value.get_bytes();
75  assert(mapping.offset+bytes.size() <= 8);
76 
77  DEBUG_LOG("[TransmitPDOMapping::send] Mapping:");
78  DEBUG_DUMP(mapping.offset);
79  DEBUG_DUMP(entry_name);
80  DEBUG_DUMP_HEX(value);
81 
82  uint8_t count = 0;
83  for (uint8_t i=mapping.offset; i<mapping.offset+bytes.size(); ++i) {
84  data[i] = bytes[count++];
85  }
86 
87  max_byte = std::max(max_byte, mapping.offset+bytes.size());
88 
89  }
90 
91  data.resize(max_byte+1);
92  m_core.pdo.send(cob_id, data);
93 
94 }
95 
96 void TransmitPDOMapping::check_correctness() const {
97 
98  unsigned size = 0;
99  std::vector<bool> byte_mapped(8,false);
100 
101  for (const Mapping& mapping : mappings) {
102 
103  const std::string entry_name = Utils::escape(mapping.entry_name);
104 
105  if (m_name_to_address.count(entry_name) == 0) {
106  throw dictionary_error(dictionary_error::type::unknown_entry, entry_name);
107  }
108 
109  const Entry& entry = m_dictionary.at(m_name_to_address.at(entry_name));
110  const uint8_t type_size = Utils::get_type_size(entry.type);
111 
112  if (mapping.offset+type_size > 8) {
113  throw dictionary_error(dictionary_error::type::mapping_size, entry_name,
114  "mapping.offset ("+std::to_string(mapping.offset)+") + type_size ("+std::to_string(type_size)+") > 8.");
115  }
116 
117  for (uint8_t i=mapping.offset; i<mapping.offset+type_size; ++i) {
118  if (byte_mapped[i]) {
119  throw dictionary_error(dictionary_error::type::mapping_overlap, entry_name, "Byte index: "+std::to_string(i));
120  }
121  byte_mapped[i] = true;
122  }
123 
124  size += type_size;
125 
126  }
127 
128  if (size > 8) {
129  throw dictionary_error(dictionary_error::type::mapping_size, "",
130  "total size ("+std::to_string(size)+") > 8.");
131  }
132 
133 }
134 
135 } // end namespace kaco
This type of exception is thrown if there are problems accessing the object dictionary or arguments d...
PDO pdo
The PDO sub-protocol.
Definition: core.h:115
const Value & get_value() const
Returns the value.
Definition: entry.cpp:94
std::vector< uint8_t > get_bytes() const
Returns the byte representation (little-endian) as a vector.
Definition: value.cpp:222
void send(uint16_t cob_id, const std::vector< uint8_t > &data)
Sends a PDO message.
Definition: pdo.cpp:83
~TransmitPDOMapping()
Stops the transmitter thread if there is one.
static std::string escape(const std::string &str)
Converts entry names to lower case and replaces all spaces and '-' by underscores.
Definition: utils.cpp:166
std::unique_ptr< std::thread > transmitter
The transmitter thread.
void send() const
Sends the PDO.
This class implements the Core of KaCanOpen It communicates with the CAN driver, sends CAN messages a...
Definition: core.h:59
uint16_t cob_id
COB-ID of the PDO.
This class represents an entry in the object dictionary of a device.
Definition: entry.h:53
std::vector< Mapping > mappings
Mapped entries with offset (see Mapping class)
TransmitPDOMapping(Core &core, const std::unordered_map< Address, Entry > &dictionary, const std::unordered_map< std::string, Address > &name_to_address, uint16_t cob_id_, TransmissionType transmission_type_, std::chrono::milliseconds repeat_time_, const std::vector< Mapping > &mappings_)
Constructor.
This struct represents one mapped entry inside a TransmitPDOMapping.
Definition: mapping.h:43
static uint8_t get_type_size(Type type)
Returns the size of a data type in bytes.
Definition: utils.cpp:112
This class contains a value to be stored in the object dictionary. The value can have one of the type...
Definition: value.h:53