14#include <yarp/os/Time.h>
15#include <yarp/os/Log.h>
16#include <yarp/os/Property.h>
17#include <yarp/os/PeriodicThread.h>
18#include <yarp/dev/PolyDriver.h>
34 reqIdsUnion=
new char[0x800];
36 for (
int i=0; i<0x800; ++i) reqIdsUnion[i]=
UNREQ;
45 delete [] reqIdsUnion;
60 if (!config.check(
"physDevice"))
62 yError(
"SharedCanBus could not find low level can driver specification\n");
66 if (mDevice!=config.find(
"physDevice").asString())
return false;
68 if (config.findGroup(
"CAN").check(
"sharedCanPeriod"))
70 int sharedCanPeriod = config.findGroup(
"CAN").find(
"sharedCanPeriod").asInt32();
71 int currentCanPeriod = (int)(1000.0 * this->getPeriod());
74 yWarning(
"SharedCanBus: Requested a different sharedCanPeriod (%d ms) respect to previous instance (%d ms). Using: %d ms\n", sharedCanPeriod, currentCanPeriod, currentCanPeriod);
78 if (!config.check(
"canDeviceNum"))
return true;
80 return mCanDeviceNum==config.find(
"canDeviceNum").asInt32();
85 std::lock_guard<std::mutex> lck(configMutex);
86 accessPoints.push_back(ap);
93 std::lock_guard<std::mutex> lck(configMutex);
95 int n=accessPoints.size();
97 for (
int i=0; i<
n; ++i)
99 if (ap==accessPoints[i])
101 for (
int id=0;
id<0x800; ++id)
103 if (ap->
hasId(
id)) canIdDeleteUnsafe(
id);
106 accessPoints[i]=accessPoints[
n-1];
108 accessPoints.pop_back();
114 if (accessPoints.size()==0)
122 static const bool NOWAIT=
false;
123 unsigned int msgsNum=0;
125 std::lock_guard<std::mutex> lck(configMutex);
127 bool ret=theCanBus->canRead(readBufferUnion,mBufferSize,&msgsNum,NOWAIT);
131 for (
unsigned int i=0; i<msgsNum; ++i)
133 unsigned int id=readBufferUnion[i].getId();
135 for (
unsigned int p=0;
p<accessPoints.size(); ++
p)
137 if (accessPoints[
p]->hasId(
id))
139 if (accessPoints[
p]->pushReadMsg(readBufferUnion[i])==
false)
141 yError(
"run()-pushReadMsg() failed on CAN bus %d", mCanDeviceNum);
151 std::lock_guard<std::mutex> lck(writeMutex);
152 bool ret=theCanBus->canWrite(msgs,size,sent,wait);
155 yarp::dev::CanBuffer buff=msgs;
156 for (
unsigned int m=0; m<size; ++m)
158 unsigned int id=buff[m].getId();
161 for (
unsigned int p=0;
p<accessPoints.size(); ++
p)
163 if (accessPoints[
p]!=pFrom && accessPoints[
p]->hasId(
id))
165 if (accessPoints[
p]->pushReadMsg(buff[m])==
false)
167 yError(
"canWrite()-pushReadMsg() failed on CAN bus %d", mCanDeviceNum);
179 std::lock_guard<std::mutex> lck(configMutex);
180 if (reqIdsUnion[
id]==
UNREQ)
182 reqIdsUnion[id]=
REQST;
183 theCanBus->canIdAdd(
id);
189 std::lock_guard<std::mutex> lck(configMutex);
190 canIdDeleteUnsafe(
id);
200 if (!theBufferFactory)
202 yError(
"SharedCanBus error: no buffer factory\n");
205 return theBufferFactory;
210 return theCanBusErrors;
213 bool open(yarp::os::Searchable &config)
215 std::lock_guard<std::mutex> lck(configMutex);
218 if (!config.check(
"physDevice"))
220 yError(
"SharedCanBus::open() could not find low level can driver specification\n");
224 std::string device=config.find(
"physDevice").asString();
226 yarp::os::Property prop;
227 prop.fromString(config.toString().c_str());
229 prop.unput(
"device");
230 prop.unput(
"subdevice");
231 prop.unput(
"physDevice");
233 prop.put(
"device",device.c_str());
236 polyDriver.open(prop);
238 if (!polyDriver.isValid())
240 yError(
"SharedCanBus: could not instantiate can device\n");
244 polyDriver.view(theCanBus);
248 yError(
"SharedCanBus: could not get ICanBus interface\n");
252 polyDriver.view(theBufferFactory);
254 if (theBufferFactory==NULL)
256 yError(
"SharedCanBus: could not get ICanBufferFactory interface\n");
260 polyDriver.view(theCanBusErrors);
264 if (config.check(
"canRxQueueSize"))
266 mBufferSize=config.find(
"canRxQueueSize").asInt32();
269 readBufferUnion=theBufferFactory->createBuffer(mBufferSize);
271 bool started=start();
275 if (config.check(
"canDeviceNum"))
277 mCanDeviceNum=config.find(
"canDeviceNum").asInt32();
284 void canIdDeleteUnsafe(
unsigned int id)
286 if (reqIdsUnion[
id]==
REQST)
288 for (
int i=0; i<(int)accessPoints.size(); ++i)
290 if (accessPoints[i]->hasId(
id))
296 reqIdsUnion[id]=
UNREQ;
298 theCanBus->canIdDelete(
id);
304 std::mutex writeMutex;
305 std::mutex configMutex;
310 yarp::dev::PolyDriver polyDriver;
312 yarp::dev::ICanBus *theCanBus;
313 yarp::dev::ICanBufferFactory *theBufferFactory;
314 yarp::dev::ICanBusErrors *theCanBusErrors;
316 std::vector<yarp::dev::CanBusAccessPoint*> accessPoints;
318 yarp::dev::CanBuffer readBufferUnion;
328 for (
unsigned int i=0; i<mDevices.size(); ++i)
330 if (mDevices[i])
delete mDevices[i];
345 for (
unsigned int i=0; i<mDevices.size(); ++i)
347 if (mDevices[i]->IloveUmom(config))
355 if (!scb->
open(config))
361 if (config.findGroup(
"CAN").check(
"sharedCanPeriod"))
363 int sharedCanPeriod = config.findGroup(
"CAN").find(
"sharedCanPeriod").asInt32();
364 scb->setPeriod((
double)sharedCanPeriod/1000.0);
372 mDevices.push_back(scb);
383 std::vector<SharedCanBus*> mDevices;
407 if (!mSharedPhysDevice)
return false;
409 mSharedPhysDevice->detachAccessPoint(
this);
416 if (!mSharedPhysDevice)
return false;
418 return mSharedPhysDevice->canWrite(msgs,size,sent,wait,
this);
423 if (!mSharedPhysDevice)
return false;
425 return mSharedPhysDevice->getCanBus()->canGetBaudRate(rate);
430 if (!mSharedPhysDevice)
return false;
434 yError(
"SharedCanBus: Id=%d is out of 11 bit address range\n",
id);
440 mSharedPhysDevice->canIdAdd(
id);
447 if (!mSharedPhysDevice)
return false;
451 yError(
"SharedCanBus: Id=%d is out of 11 bit address range\n",
id);
457 mSharedPhysDevice->canIdDelete(
id);
464 yarp::dev::CanBuffer cb;
466 if (mSharedPhysDevice) cb = mSharedPhysDevice->getCanBufferFactory()->createBuffer(nmessage);
473 if (!mSharedPhysDevice)
return;
475 yarp::dev::ICanBufferFactory* tmp = mSharedPhysDevice->getCanBufferFactory();
477 if (tmp) tmp->destroyBuffer(msgs);
const int DEFAULT_THREAD_PERIOD
const int CAN_DRIVER_BUFFER_SIZE
#define UNREQ
Copyright (C) 2012 RobotCub Consortium.
static SharedCanBusManager & getInstance()
SharedCanBus * open(yarp::os::Searchable &config)
bool open(yarp::os::Searchable &config)
void canIdAdd(unsigned int id)
bool canWrite(const yarp::dev::CanBuffer &msgs, unsigned int size, unsigned int *sent, bool wait, yarp::dev::CanBusAccessPoint *pFrom)
yarp::dev::ICanBusErrors * getCanBusErrors()
void attachAccessPoint(yarp::dev::CanBusAccessPoint *ap)
void detachAccessPoint(yarp::dev::CanBusAccessPoint *ap)
yarp::dev::ICanBus * getCanBus()
yarp::dev::ICanBufferFactory * getCanBufferFactory()
bool IloveUmom(yarp::os::Searchable &config)
void canIdDelete(unsigned int id)
sharedcan : implements ICanBus interface for multiple access from a single access can driver (for exa...
virtual void destroyBuffer(CanBuffer &msgs)
virtual bool open(yarp::os::Searchable &config)
virtual bool canGetBaudRate(unsigned int *rate)
SharedCanBus * mSharedPhysDevice
bool hasId(unsigned int id)
virtual bool canIdAdd(unsigned int id)
virtual bool canWrite(const CanBuffer &msgs, unsigned int size, unsigned int *sent, bool wait=false)
virtual bool canIdDelete(unsigned int id)
virtual CanBuffer createBuffer(int nmessage)