14#include <yarp/os/Time.h>
15#include <ace/config.h>
17#include <ace/Log_Msg.h>
18#include <ace/Sched_Params.h>
28#define NTCAN_HANDLE HANDLE
32#include <yarp/dev/ControlBoardInterfacesImpl.h>
39typedef int (*
PV) (
const char *fmt, ...);
41using namespace yarp::os;
54 _zeros = allocAndCheck<double>(nj);
71 checkAndDestroy<double>(
_zeros);
129 bool error (
const CMSG& m);
206 if (
_handle != ACE_INVALID_HANDLE)
241 if (res != NTCAN_SUCCESS)
245 if (res != NTCAN_SUCCESS)
253 for (i = 0; i < 0xff; i++)
256 for (i = 0x100; i < 0x1ff; i++)
271 if (
_handle != ACE_INVALID_HANDLE)
274 if (res != NTCAN_SUCCESS)
292 if (res != NTCAN_SUCCESS)
308 memset (&
x, 0,
sizeof(CMSG));
315 if ((joint % 2) == 1)
347 int ret = ACE_OS::sprintf (
_printBuffer,
"class: %2d s: %2x d: %2x c: %1d msg: %3d (%x) ",
351 ((m.data[0] & 0x80)==0)?0:1,
361 for (j = 1; j < m.len; j++)
363 ret += ACE_OS::sprintf (
_printBuffer+ret,
"%x ", m.data[j]);
365 ret += ACE_OS::sprintf(
_printBuffer+ret,
"st: %x\n", m.msg_lost);
376 if (!
_p)
return false;
381 (*_p) (
"Sniffer: write buffer\n");
385 (*_p) (
"Sniffer: reply buffer\n");
389 (*_p) (
"Sniffer: read buffer\n");
392 (*_p) (
"Sniffer: -------------\n");
399 if (m.len & NTCAN_NO_DATA)
return true;
400 if (m.msg_lost != 0) {
_msg_lost = m.msg_lost;
return true; }
412 ImplementPidControl<EsdMessageSniffer, IPidControl>(this),
413 ImplementAmplifierControl<EsdMessageSniffer, IAmplifierControl>(this),
414 ImplementEncoders<EsdMessageSniffer, IEncoders>(this)
431 p.fromString(config.toString());
433 if (!
p.check(
"GENERAL")) {
434 ACE_OS::fprintf(stderr,
"Cannot understand configuration parameters\n");
439 int nj =
p.findGroup(
"GENERAL").find(
"Joints").asInt32();
444 Bottle &xtmp =
p.findGroup(
"CAN").findGroup(
"CanDeviceNum");
447 xtmp =
p.findGroup(
"CAN").findGroup(
"CanMyAddress");
450 xtmp =
p.findGroup(
"CAN").findGroup(
"CanPollingInterval");
453 xtmp =
p.findGroup(
"CAN").findGroup(
"CanTimeout");
454 params.
_timeout=xtmp.get(1).asInt32();
456 xtmp =
p.findGroup(
"CAN").findGroup(
"CanAddresses");
457 for (i = 1; i < xtmp.size(); i++) params.
_destinations[i-1] = (
unsigned char)(xtmp.get(i).asInt32());
460 xtmp =
p.findGroup(
"GENERAL").findGroup(
"AxisMap");
461 ACE_ASSERT (xtmp.size() == nj+1);
462 for (i = 1; i < xtmp.size(); i++) params.
_axisMap[i-1] = xtmp.get(i).asInt32();
463 xtmp =
p.findGroup(
"GENERAL").findGroup(
"Encoder");
464 ACE_ASSERT (xtmp.size() == nj+1);
465 for (i = 1; i < xtmp.size(); i++) params.
_angleToEncoder[i-1] = xtmp.get(i).asFloat64();
466 xtmp =
p.findGroup(
"GENERAL").findGroup(
"Zeros");
467 ACE_ASSERT (xtmp.size() == nj+1);
468 for (i = 1; i < xtmp.size(); i++) params.
_zeros[i-1] = xtmp.get(i).asFloat64();
470 if (
p.findGroup(
"GENERAL").find(
"Verbose").asInt32() == 1)
471 params.
_p = ACE_OS::printf;
480 std::lock_guard<std::mutex> lck(
_mutex);
488 ImplementPidControl<EsdMessageSniffer, IPidControl>::
490 ImplementAmplifierControl<EsdMessageSniffer, IAmplifierControl>::
492 ImplementEncoders<EsdMessageSniffer, IEncoders>::
497 std::unique_lock<std::mutex> lck(
mtx_done);
510 ACE_OS::fprintf(stderr,
"EsdSniffer::close called\n");
513 ImplementPidControl<EsdMessageSniffer, IPidControl>::uninitialize();
514 ImplementAmplifierControl<EsdMessageSniffer, IAmplifierControl>::uninitialize();
515 ImplementEncoders<EsdMessageSniffer, IEncoders>::uninitialize();
527 bool messagePending =
false;
529 int remainingMsgs = 0;
530 bool noreply =
false;
543 while (!isStopping() || messagePending)
545 before = Time::now();
548 if (r.
read () !=
true)
550 (*r.
_p) (
"Sniffer: read failed\n");
558 if (m.len & NTCAN_NO_DATA)
561 (*r.
_p) (
"Sniffer: error in message %x len: %d type: %x: %x\n",
562 m.id, m.len, m.data[0], m.msg_lost);
566 if ((m.id & 0x700) == 0x100)
573 const int addr = ((m.id & 0x0f0) >> 4);
584 switch (m.id & 0x00f)
597 case CAN_BCAST_PID_VAL:
609 case CAN_BCAST_STATUS:
622 case CAN_BCAST_CURRENT:
652 if (m.len & NTCAN_NO_DATA)
655 (*r.
_p) (
"Sniffer: error in message %x len: %d type: %x: %x\n",
656 m.id, m.len, m.data[0], m.msg_lost);
661 if (((m.id &0x700) == 0) &&
662 ((m.data[0] & 0x7f) < NUM_OF_MESSAGES))
667 if (((m.id & 0x700) == 0) &&
674 if (((r.
_writeBuffer[j].id & 0x0f) == ((m.id & 0xf0) >> 4)) &&
681 (*r.
_p) (
"Sniffer: message %x was already replied\n", m.id);
689 if (remainingMsgs < 1)
691 messagePending =
false;
706 messagePending =
false;
718 (*r.
_p) (
"Sniffer: timeout - still %d messages unacknowledged\n", remainingMsgs);
722 messagePending =
false;
745 (*r.
_p) (
"Sniffer: write message of %d elments failed\n", r.
_writeMessages);
750 messagePending =
true;
783 if (r.
_p) (*r.
_p)(
"Sniffer: thread can't poll fast enough (time: %f)\n", now-before);
794 std::lock_guard<std::mutex> lck(
_mutex);
796 _p = (int (*) (
const char *fmt, ...))
cmd;
837 ACE_ASSERT (i >= 0 && i <= r.
getJoints());
839 std::lock_guard<std::mutex> lck(
_mutex);
848 std::lock_guard<std::mutex> lck(
_mutex);
859 ACE_ASSERT (i >= 0 && i <= r.
getJoints());
861 lock_guard<mutex> lck(
_mutex);
870 std::lock_guard<std::mutex> lck(
_mutex);
881 ACE_ASSERT (i >= 0 && i <= r.
getJoints());
883 std::lock_guard<std::mutex> lck(
_mutex);
893 std::lock_guard<std::mutex> lck(
_mutex);
906 std::lock_guard<std::mutex> lck(
_mutex);
917 ACE_ASSERT (i >= 0 && i <= r.
getJoints());
919 std::lock_guard<std::mutex> lck(
_mutex);
930 std::lock_guard<std::mutex> lck(
_mutex);
967 std::unique_lock<std::mutex> lck(
mtx_done);
995 std::unique_lock<std::mutex> lck(
mtx_done);
1037 std::unique_lock<std::mutex> lck(
mtx_done);
1042 ACE_OS::memset (
out, 0,
sizeof(
double) * r.
getJoints());
1047 for (i = 0, j = 0; i < r.
getJoints(); i++)
1055 out[i] = *((
short *)(m.data+1));
1087 std::unique_lock<std::mutex> lck(
mtx_done);
1117 std::unique_lock<std::mutex> lck(
mtx_done);
1130 ACE_ASSERT ((axis % 2) == 0);
1150 std::unique_lock<std::mutex> lck(
mtx_done);
1181 std::unique_lock<std::mutex> lck(
mtx_done);
1223 std::unique_lock<std::mutex> lck(
mtx_done);
1228 ACE_OS::memset (
out, 0,
sizeof(
double) * r.
getJoints());
1233 for (i = 0, j = 0; i < r.
getJoints(); i++)
1241 out[i] = *((
int *)(m.data+1));
CanBusResources & RES(void *res)
const int ESD_MAX_CARDS
Max number of addressable cards in this implementation.
int(* PV)(const char *fmt,...)
class for interfacing with the ESD can device driver and reading messages.
CMSG _readBuffer[BUF_SIZE]
char _printBuffer[16384]
pointer to a printf type function used to spy on can messages.
bool _error_status
number of joints (ncards * 2).
unsigned char _my_address
local storage for bcast messages.
CMSG _replyBuffer[BUF_SIZE]
write buffer.
int _timeout
the actual ddriver handle.
BCastBufferElement * _bcastRecvBuffer
reply buffer.
bool getErrorStatus(void) const
unsigned char _destinations[ESD_MAX_CARDS]
int _polling_interval
this is my thread timeout.
int _speed
thread polling interval.
PV _p
error status of the last packet (true = error).
CMSG _writeBuffer[BUF_SIZE]
size of the write packet.
int getJoints(void) const
long int _txQueueSize
network number.
int _njoints
list of connected cards (and their addresses).
int _networkN
speed of the bus.
bool error(const CMSG &m)
bool addMessage(int msg_id, int joint)
bool initialize(const EsdMessageSnifferParameters &parms)
int _msg_lost
size of the last read buffer.
int _writeMessages
read buffer.
bool printMessage(const CMSG &m)
virtual bool close(void)
Close the device driver.
bool getBCastPositionErrors(double *cmd)
bool getBCastPositions(double *p)
bool setDebugPrintFunction(void *cmd)
int(* _p)(const char *fmt,...)
pointer to the function printing the device debug information.
bool _readWord16(int msg, int axis, short &value)
virtual bool open(EsdMessageSnifferParameters ¶ms)
Open the device driver.
EsdMessageSniffer()
Constructor.
std::condition_variable cv_done
bool getBCastCurrents(double *p)
virtual ~EsdMessageSniffer()
Destructor.
bool _readWord16Array(int msg, double *out)
reads an array.
bool _writeDWord(int msg, int axis, int value)
write a DWord
bool getBCastFaults(int *p)
bool _writeWord16Ex(int msg, int axis, short s1, short s2)
two shorts in a single Can message (both must belong to the same control card).
virtual bool getAxes(int *axis)
Get the number of controlled axes.
bool getBCastPIDOutput(int i, double *value)
bool getBCastCurrent(int i, double *value)
bool _readDWordArray(int msg, double *out)
reads an array of double words.
bool getBCastPosition(int i, double *value)
reads an array of double from the broadcast message position buffer.
bool _writeNone(int msg, int axis)
helper functions.
bool ENABLED(int axis)
helper function to check whether the enabled flag is on or off.
bool getBCastPIDOutputs(double *p)
bool _writeWord16(int msg, int axis, short s)
helper functions
bool _readDWord(int msg, int axis, int &value)
sends a message and gets a dword back.
bool setBCastMessages(int i, int value)
sets the broadcast policy for a given board (don't need to be called twice).
bool getBCastPositionError(int i, double *value)
#define CAN_BCAST_POSITION
A container class to pass parameters to the open() method of the device driver.
int _njoints
network number
unsigned char _my_address
number of joints (cards * 2)
EsdMessageSnifferParameters(int nj)
Constructor.
int _timeout
thread polling interval [ms]
int(* _p)(const char *fmt,...)
number of cycles before timing out
int _polling_interval
my address
~EsdMessageSnifferParameters()
Destructor.
unsigned char * _destinations
printf-like function for spying messages
int * _axisMap
destination addresses
double * _zeros
angle to encoder conversion factors
double * _angleToEncoder
axis remapping lookup-table