58 const char * baudrate;
64 typedef void* CANHandle;
66 extern "C" uint8_t canReceive_driver(CANHandle, Message *);
67 extern "C" uint8_t canSend_driver(CANHandle, Message
const *);
68 extern "C" CANHandle canOpen_driver(CANBoard *);
69 extern "C" int32_t canClose_driver(CANHandle);
70 extern "C" uint8_t canChangeBaudRate_driver(CANHandle,
char *);
84 bool Core::start(
const std::string busname,
const std::string& baudrate) {
88 CANBoard board = {busname.c_str(), baudrate.c_str()};
89 m_handle = canOpen_driver(&board);
92 ERROR(
"Cannot open the CANOpen device.");
97 m_loop_thread = std::thread(&Core::receive_loop,
this, std::ref(m_running));
102 bool Core::start(
const std::string busname,
const unsigned baudrate) {
103 if (baudrate>=1000000 && baudrate%1000000==0) {
104 return start(busname, std::to_string(baudrate/1000000)+
"M");
105 }
else if (baudrate>=1000 && baudrate%1000==0) {
106 return start(busname, std::to_string(baudrate/1000)+
"K");
108 return start(busname, std::to_string(baudrate));
117 m_loop_thread.detach();
119 DEBUG_LOG(
"Calling canClose.");
120 canClose_driver(m_handle);
124 void Core::receive_loop(std::atomic<bool>& running) {
130 canReceive_driver(m_handle, &message);
131 received_message(message);
138 std::lock_guard<std::mutex> scoped_lock(m_receive_callbacks_mutex);
139 m_receive_callbacks.push_back(callback);
142 void Core::received_message(
const Message& message) {
145 DEBUG_LOG(
"Received message:");
148 if (m_cleanup_futures) {
149 std::lock_guard<std::mutex> scoped_lock(m_callback_futures_mutex);
150 m_callback_futures.remove_if([](
const std::future<void>& f) {
152 return (f.wait_for(std::chrono::steady_clock::duration::zero())==std::future_status::ready);
158 std::lock_guard<std::mutex> scoped_lock(m_receive_callbacks_mutex);
163 std::lock_guard<std::mutex> scoped_lock(m_callback_futures_mutex);
164 m_callback_futures.push_front(
165 std::async(std::launch::async, callback, message)
174 DEBUG_LOG(
"NMT Module Control");
175 DEBUG(message.
print();)
180 DEBUG_LOG(
"Sync or Emergency");
181 DEBUG(message.
print();)
186 DEBUG_LOG(
"Time stamp");
187 DEBUG(message.
print();)
206 DEBUG_LOG(
"PDO receive");
207 DEBUG(message.
print();)
220 DEBUG_LOG(
"SDO (receive/client)");
221 DEBUG(message.
print();)
232 DEBUG_LOG(
"Unknown message:");
233 DEBUG(message.
print();)
249 DEBUG_LOG_EXHAUSTIVE(
"Sending message:");
250 DEBUG_EXHAUSTIVE(message.
print();)
251 canSend_driver(m_handle, &message);
254 m_send_mutex.unlock();
void send(const Message &message)
Sends a message.
NMT nmt
The NMT sub-protocol.
PDO pdo
The PDO sub-protocol.
uint8_t get_function_code() const
Extracts the function code from the COB-ID.
void process_incoming_message(const Message &message) const
Handler for an incoming PDO message.
std::function< void(const Message &) > MessageReceivedCallback
Type of a message receiver function Important: Never call register_receive_callback() from within (->...
void stop()
Stops the receive loop and closes the driver.
void process_incoming_message(const Message &message)
Process incoming SDO message.
SDO sdo
The SDO sub-protocol.
void process_incoming_message(const Message &message)
Process incoming NMT message.
bool start(const std::string busname, const std::string &baudrate)
Opens CAN driver and starts CAN message receive loop.
void register_receive_callback(const MessageReceivedCallback &callback)
Registers a callback function which is called when a message has been received.
This struct represents a CANOpen message.
void print() const
Prints the message to command line.