iCub-main
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 
33 inline int getRcp(const yarp::dev::CanMessage &m)
34 {
35  return (m.getId()&0x0f);
36 }
37 
43 inline int getSender(const yarp::dev::CanMessage &m)
44 {
45  return (m.getId()&0xf0)>>4;
46 }
47 
52 inline int getClass(const yarp::dev::CanMessage &m)
53 {
54  return (m.getId()&0x700);
55 }
56 
60 inline unsigned char getMessageType(const yarp::dev::CanMessage &m)
61 {
62  return m.getData()[0]&0x7f;
63 }
64 
70 inline 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 
83 template<class T>
84 long getRcp(const T &m)
85 {
86  return (m.id&0x0f);
87 }
88 
94 template<class T>
95 long getSender(const T &m)
96 {
97  return (m.id&0xf0)>>4;
98 }
99 
104 template<class T>
105 long getClass(const T &m)
106 {
107  return (m.id&0x700);
108 }
109 
113 template<class T>
114 unsigned char getMessageType(const T &m)
115 {
116  return m.data[0]&0x7f;
117 }
118 
124 template<class T>
125 int 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 
134 inline 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 
151 struct ThreadId
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.
158 class 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;
193  int threadId;
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 {
203 private:
204  ThreadFifo *requests;
205  int njoints;
206  int num_of_messages;
207  int pendings;
208  int elements;
209 public:
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