iCub-main
Loading...
Searching...
No Matches
canControlUtils.h
Go to the documentation of this file.
1// -*- mode:C++; tab-width:4; c-basic-offset:4; indent-tabs-mode:nil -*-
2
3/*
4 * Copyright (C) 2008 The RobotCub Consortium
5 * Author: Lorenzo Natale
6 * website: www.robotcub.org
7 * Permission is granted to copy, distribute, and/or modify this program
8 * under the terms of the GNU General Public License, version 2 or any
9 * later version published by the Free Software Foundation.
10 *
11 * A copy of the license can be found at
12 * http://www.robotcub.org/icub/license/gpl.txt
13 *
14 * This program is distributed in the hope that it will be useful, but
15 * WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
17 * Public License for more details
18*/
19
20
21#ifndef __CANUTILS__
22#define __CANUTILS__
23
24#include <list>
25
26#include "yarp/dev/CanBusInterface.h"
27
33inline int getRcp(const yarp::dev::CanMessage &m)
34{
35 return (m.getId()&0x0f);
36}
37
43inline int getSender(const yarp::dev::CanMessage &m)
44{
45 return (m.getId()&0xf0)>>4;
46}
47
52inline int getClass(const yarp::dev::CanMessage &m)
53{
54 return (m.getId()&0x700);
55}
56
60inline unsigned char getMessageType(const yarp::dev::CanMessage &m)
61{
62 return m.getData()[0]&0x7f;
63}
64
70inline int getJoint(const yarp::dev::CanMessage &m, const unsigned char *invM)
71{
72 int sender=getSender(m);
73 int odd=((m.getData()[0]&0x80)==0) ? 0:1;
74 return invM[sender]+odd;
75}
76
77
83template<class T>
84long getRcp(const T &m)
85{
86 return (m.id&0x0f);
87}
88
94template<class T>
95long getSender(const T &m)
96{
97 return (m.id&0xf0)>>4;
98}
99
104template<class T>
105long getClass(const T &m)
106{
107 return (m.id&0x700);
108}
109
113template<class T>
114unsigned char getMessageType(const T &m)
115{
116 return m.data[0]&0x7f;
117}
118
124template<class T>
125int getJoint(const T &m, const unsigned char *invM)
126{
127 int sender=getSender(m);
128 int odd=((m.data[0]&0x80)==0) ? 0:1;
129 return invM[sender]+odd;
130}
131
133
134inline void DEBUG_FUNC(const char *fmt, ...)
135{
136#ifdef CAN_DEBUG
137 va_list ap;
138 va_start(ap, fmt);
139 char buffer[DEBUG_PRINTF_BUFFER_LENGTH];
140#ifdef WIN32
141 _vsnprintf(buffer, DEBUG_PRINTF_BUFFER_LENGTH, fmt, ap);
142#else
143 vsnprintf(buffer, DEBUG_PRINTF_BUFFER_LENGTH, fmt, ap);
144#endif
145 yDebug("%s", buffer);
146 va_end(ap);
147#endif
148}
149
150
152{
153 int id;
154 unsigned int waitTime; //ms
155};
156
157// A fifo of threads. There is one on each entry in the RequestsQueue.
158class ThreadFifo: public std::list<ThreadId>
159{
160 public:
162
163 // A pop function; get and destroy from front, just get thread id
164 inline bool pop(int &ret)
165 {
166 ThreadId tmp;
167 if (empty())
168 return false;
169
170 tmp=front();
171 pop_front();
172
173 ret=tmp.id;
174 return true;
175 }
176
177 // Push a thread id from back. waitTime is initialized to zero
178 inline bool push(int id)
179 {
180 ThreadId tmp;
181 tmp.id=id;
182 tmp.waitTime=0;
183 push_back(tmp);
184 return true;
185 }
186};
187
188// A structure to hold a request (joint, msg and waiting thread)
190{
191 int joint;
192 int msg;
194};
195
196// A table, the index is a given can message type+the joint number.
197// Each entry stores a list of waiting threads.
198// At the moment the size of this table is statically determined (
199// maximum size, given the number of joints and the number of messages,
200// but it could be allocated at runtime, when requests arrive).
202{
203private:
204 ThreadFifo *requests;
205 int njoints;
206 int num_of_messages;
207 int pendings;
208 int elements;
209public:
210 RequestsQueue(int joints, int num_msgs)
211 {
212 DEBUG_FUNC("Allocating %d x %d\n", joints, num_msgs);
213 elements=joints*num_msgs;
214 requests=new ThreadFifo[elements];
215 num_of_messages=num_msgs;
216 njoints=joints;
217 pendings=0;
218 }
219
221 {
222 delete [] requests;
223 }
224
225 ThreadFifo *getFifo(int j, int msg)
226 {
227 unsigned int i=msg&0x7F;
228 // fprintf(stderr, "Asking FIFO for joint:%d msg:%d\n", j, i);
229 int index=j*num_of_messages+i;
230 DEBUG_FUNC("%d %d\n", index, elements);
231
232 if ((index>=0)&&(index<elements))
233 return requests+index;
234 else
235 return 0;
236 }
237
238 // pop a request
239 int pop(int j, int msg)
240 {
241 if (pendings<=0)
242 {
243 DEBUG_FUNC("Error, queue of requests empty");
244 return -1;
245 }
246
247 int ret;
248 ThreadFifo *fifo=getFifo(j, msg);
249 if (!fifo)
250 return -1;
251
252 if (!fifo->pop(ret))
253 return -1;
254 pendings--;
255 return ret;
256 }
257
259 {
260 return pendings;
261 }
262
263 // append requests
264 void append(const CanRequest &rqst)
265 {
266 ThreadFifo *fifo=getFifo(rqst.joint, rqst.msg);
267 if (!fifo)
268 return;
269
270 fifo->push(rqst.threadId);
271 pendings++;
272 }
273
274 inline int getNJoints()
275 {return njoints;}
276 inline int getNMessages()
277 {return num_of_messages;}
278};
279
280#endif
int getJoint(const yarp::dev::CanMessage &m, const unsigned char *invM)
Extract the joint number to which a RECEIVED message is referring to.
unsigned char getMessageType(const yarp::dev::CanMessage &m)
Extract 7 lsb of first byte; this is the message type in our protocol.
int getRcp(const yarp::dev::CanMessage &m)
Extract least significative 4 bits, from the id of a can msg.
const int DEBUG_PRINTF_BUFFER_LENGTH
int getSender(const yarp::dev::CanMessage &m)
Extract most significative 4 bits of the least significative byte from the id of a can msg.
int getClass(const yarp::dev::CanMessage &m)
Extract message class, three bit least significative of the first byte of the message ID.
void DEBUG_FUNC(const char *fmt,...)
ThreadFifo * getFifo(int j, int msg)
void append(const CanRequest &rqst)
int pop(int j, int msg)
RequestsQueue(int joints, int num_msgs)
bool pop(int &ret)
bool push(int id)
unsigned int waitTime