iCub-main
boardTransceiver.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2014 iCub Facility, Istituto Italiano di Tecnologia
3  * Authors: Alberto Cardellino
4  * CopyPolicy: Released under the terms of the LGPLv2.1 or later, see LGPL.TXT
5  *
6  */
7 
8 
9 // --------------------------------------------------------------------------------------------------------------------
10 // - macros
11 // --------------------------------------------------------------------------------------------------------------------
12 
13 
14 
15 // --------------------------------------------------------------------------------------------------------------------
16 // - external dependencies
17 // --------------------------------------------------------------------------------------------------------------------
18 
19 using namespace std;
20 
21 #include <stdint.h>
22 #include <stdlib.h>
23 #include <stdio.h>
24 #include <string.h>
25 
26 #include "boardTransceiver.hpp"
27 #include "FeatureInterface.h"
28 
29 #include "EOYtheSystem.h"
30 #include "EoCommon.h"
31 #include "EOnv.h"
32 #include "EOnv_hid.h"
33 #include "EOrop.h"
34 #include "EoProtocol.h"
35 
36 
37 #include "EOdeviceTransceiver.h"
38 
39 #include "EOprotocolConfigurator.h"
40 
41 #include "EoProtocol.h"
42 #include "EoProtocolMN.h"
43 #include "EoProtocolMC.h"
44 #include "EoProtocolAS.h"
45 #include "EoProtocolSK.h"
46 
47 
48 
49 #include <yarp/os/LogStream.h>
50 
51 #include <yarp/os/Time.h>
52 #include <yarp/os/Bottle.h>
53 
54 using namespace yarp::os;
55 
56 
57 EOnvSet* arrayofnvsets[16] = {NULL};
58 
60 {
61  yTrace();
62 
63  UDP_socket = NULL;
64  remoteipport = 0;
65  localipaddr = 0;
66  remoteipaddr = 0;
67 
68  protboardnumber = eo_prot_BRDdummy;
69  p_RxPkt = NULL;
70  devtxrx = NULL;
71  transceiver = NULL;
72  nvset = NULL;
73 
74  pApplStatus = NULL;
75 
76  oneNV = eo_nv_New();
77 
78  memcpy(&devtxrxcfg, &eo_devicetransceiver_cfg_default, sizeof(eOdevicetransceiver_cfg_t));
79 }
80 
82 {
83  yTrace();
84 }
85 
86 bool BoardTransceiver::configure(yarp::os::ResourceFinder &rf)
87 {
88  yDebug() << " input is " << rf.toString().c_str();
89 
90  if(!rf.check("PC104IpAddress"))
91  {
92  yError() << "missing PC104IpAddress";
93  return false;
94  }
95 
96  if(!rf.check("emsIpAddress"))
97  {
98  yError() << "missing emsIpAddress";
99  return false;
100  }
101 
102  if(!rf.check("port"))
103  {
104  yError() << "missing port";
105  return false;
106  }
107 
108  yDebug() << " I have all params I need!!";
109  Bottle parameter1( rf.find("PC104IpAddress").asString() );
110 
111  int port = rf.find("port").asInt32(); // .get(1).asInt32();
112  strcpy(_fId.PC104ipAddr.string, parameter1.toString().c_str());
113  _fId.PC104ipAddr.port = port;
114 
115  Bottle parameter2( rf.find("emsIpAddress").asString() ); // .findGroup("IpAddress");
116  strcpy(_fId.EMSipAddr.string, parameter2.toString().c_str());
117  _fId.EMSipAddr.port = port;
118 
119  sscanf(_fId.EMSipAddr.string,"\"%d.%d.%d.%d", &_fId.EMSipAddr.ip1, &_fId.EMSipAddr.ip2, &_fId.EMSipAddr.ip3, &_fId.EMSipAddr.ip4);
120  sscanf(_fId.PC104ipAddr.string,"\"%d.%d.%d.%d", &_fId.PC104ipAddr.ip1, &_fId.PC104ipAddr.ip2, &_fId.PC104ipAddr.ip3, &_fId.PC104ipAddr.ip4);
121 
122  snprintf(_fId.EMSipAddr.string, sizeof(_fId.EMSipAddr.string), "%u.%u.%u.%u:%u", _fId.EMSipAddr.ip1, _fId.EMSipAddr.ip2, _fId.EMSipAddr.ip3, _fId.EMSipAddr.ip4, _fId.EMSipAddr.port);
123  snprintf(_fId.PC104ipAddr.string, sizeof(_fId.PC104ipAddr.string), "%u.%u.%u.%u:%u", _fId.PC104ipAddr.ip1, _fId.PC104ipAddr.ip2, _fId.PC104ipAddr.ip3, _fId.PC104ipAddr.ip4, _fId.PC104ipAddr.port);
124 
125  // Check input parameters
126  yDebug() << " boardTransceiver - referred to EMS: " << _fId.EMSipAddr.string;
127 
128 
129  ACE_UINT32 hostip = (_fId.PC104ipAddr.ip1 << 24) | (_fId.PC104ipAddr.ip2 << 16) | (_fId.PC104ipAddr.ip3 << 8) | (_fId.PC104ipAddr.ip4);
130  ACE_INET_Addr myIP((u_short)_fId.PC104ipAddr.port, hostip);
131 // myIP.dump();
132 
133  if(!createSocket(myIP) )
134  { return NULL; }
135 
136  return true;
137 }
138 
139 bool BoardTransceiver::createSocket(ACE_INET_Addr local_addr)
140 {
141  yTrace();
142 
143  UDP_socket = new ACE_SOCK_Dgram();
144  char tmp[64];
145 
146  if(-1 == UDP_socket->open(local_addr))
147  {
148  local_addr.addr_to_string(tmp, 64);
149  yError() << "\n/---------------------------------------------------\\"
150  << "\n| Unable to bind to local IP address " << tmp
151  << "\n\\---------------------------------------------------/";
152  delete UDP_socket;
153  UDP_socket = NULL;
154  }
155  else
156  {
157  yTrace() << "BoardTransceiver created socket correctly!";
158  }
159 
160  return true;
161 }
162 
163 bool BoardTransceiver::init(yarp::os::Searchable &config, uint32_t _localipaddr, uint32_t _remoteipaddr, uint16_t _remoteipport, uint16_t _pktsizerx, FEAT_boardnumber_t _board_n)
164 {
165  // the configuration of the transceiver: it is specific of a given remote board
166  yTrace();
167 
168  // assign values of some member variables
169 
170  protboardnumber = featIdBoardNum2nvBoardNum(_board_n);
171  localipaddr = _localipaddr;
172  remoteipaddr = _remoteipaddr;
173  remoteipport = _remoteipport;
174 
175 
176 
177  if(!initProtocol(config))
178  {
179  yError() << "BoardTransceiver::initProtocol() fails";
180  return false;
181  }
182 
183 
184  if(!prepareTransceiverConfig(config))
185  {
186  yError() << "BoardTransceiver::prepareTransceiverConfig() fails";
187  return false;
188  }
189 
190  // now devtxrxcfg is ready, thus ...
191  // initialise the transceiver: it creates a EOtransceiver and its EOnvSet
192  devtxrx = eo_devicetransceiver_New(&devtxrxcfg); // never returns NULL. it calls its error manager
193  if(devtxrx == NULL)
194  return false;
195 
196  // retrieve the transceiver
197  transceiver = eo_devicetransceiver_GetTransceiver(devtxrx); //CHECK!!!!!
198  if(transceiver == NULL)
199  return false;
200 
201  // retrieve the nvset
202  nvset = eo_devicetransceiver_GetNVset(devtxrx); //CHECK!!!!!
203  if(NULL == nvset)
204  {
205  return false;
206  }
207 
208  arrayofnvsets[protboardnumber] = nvset;
209 
210 
211  // build the packet used for reception.
212  p_RxPkt = eo_packet_New(_pktsizerx);
213  if(p_RxPkt == NULL)
214  return false;
215 
216  eOnvID32_t id32status = eoprot_ID_get(eoprot_endpoint_management, eoprot_entity_mn_appl, 0, eoprot_tag_mn_appl_status);
217  eo_nvset_NV_Get(nvset, eok_ipv4addr_localhost, id32status, oneNV);
218 
219  pApplStatus = (eOmn_appl_status_t*) oneNV->ram;
220  pApplStatus->currstate = applstate_config;
221 
222 
223 
224  return true;
225 }
226 
227 
228 void fromDouble(ACE_Time_Value &v, double x,int unit) {
229 #ifdef YARP_HAS_ACE
230  v.msec(static_cast<int>(x*1000/unit+0.5));
231 #else
232  v.tv_usec = static_cast<int>(x*1000000/unit+0.5) % 1000000;
233  v.tv_sec = static_cast<int>(x/unit);
234 #endif
235 }
236 
237 // Main loop here!!!
239 {
240  ACE_INET_Addr sender_addr;
241  ssize_t recv_size;
242  ACE_Time_Value recvTimeOut;
243  fromDouble(recvTimeOut, 1.0);
244 
245  uint8_t *p_sendData;
246  uint16_t bytes_to_send = 0;
247 
248  uint8_t incoming_msg[RECV_BUFFER_SIZE];
249 
250  bool parsepacket = false;
251  bool transmitpacket = false;
252 
253  //std::cout << " BoardTransceiver is running happily!" << std::endl;
254 
255  // get pkt from socket: blocking call with timeout
256  recv_size = UDP_socket->recv((void *) incoming_msg, RECV_BUFFER_SIZE, sender_addr, 0, &recvTimeOut);
257 
258  switch(pApplStatus->currstate)
259  {
260  case applstate_config:
261  { // in configuration state the ems is triggered only for non-empty packets. it sends back a ropframe even if empty
262  if(recv_size > 0)
263  {
264  parsepacket = true;
265  transmitpacket = true;
266  }
267  } break;
268 
269  case applstate_running:
270  { // in running state the ems is triggered every millisecond. it parses non-empty packets. it always sends a ropframe back, even if empty.
271  if(recv_size > 0)
272  {
273  parsepacket = true;
274  }
275  transmitpacket = true;
276  } break;
277 
278  case applstate_error:
279  {
280  if(recv_size > 0)
281  {
282  parsepacket = true;
283  transmitpacket = true;
284  }
285  } break;
286 
287  default:
288  {
289 
290  } break;
291 
292  }
293 
294  if(parsepacket)
295  {
296  onMsgReception(incoming_msg, recv_size);
297  }
298 
299  if(transmitpacket)
300  {
301  getTransmit(&p_sendData, &bytes_to_send);
302 
303  ssize_t ret = UDP_socket->send(p_sendData, bytes_to_send, remoteipaddr);
304  if(ret < 0)
305  {
306  yError() << "Unable to send a message";
307  }
308  }
309 
310  return true; // if false the program quits from the forever loop
311 }
312 
313 
314 
315 // somebody passes the received packet - this is used just as an interface
316 void BoardTransceiver::onMsgReception(uint8_t *data, uint16_t size)
317 {
318  if(NULL == data)
319  {
320  yError() << "eo BoardTransceiver::onMsgReception() called with NULL data";
321  return;
322  }
323 
324  yError() << "Received a message with size = " << size;
325 
326 
327  uint16_t numofrops;
328  uint64_t txtime;
329  uint16_t capacityrxpkt = 0;
330 
331  // protezione per la scrittura dei dati all'interno della memoria del transceiver, su ricezione di un rop.
332  // il mutex e' unico per tutto il transceiver
333  eo_packet_Capacity_Get(p_RxPkt, &capacityrxpkt);
334  if(size > capacityrxpkt)
335  {
336  yError () << "received packet has size " << size << "which is higher than capacity of rx pkt = " << capacityrxpkt << "\n";
337  return;
338  }
339 
340  eo_packet_Payload_Set(p_RxPkt, data, size);
341  eo_packet_Addressing_Set(p_RxPkt, remoteipaddr, remoteipport);
342  eo_transceiver_Receive(transceiver, p_RxPkt, &numofrops, &txtime);
343 }
344 
345 
346 
347 /* This function just modify the pointer 'data', in order to point to transceiver's memory where a copy of the ropframe
348  * to be sent is stored.
349  * The memory holding this ropframe will be written ONLY in case of a new call of eo_transceiver_Transmit function,
350  * therefore it is safe to use it. No concurrency is involved here.
351  */
352 void BoardTransceiver::getTransmit(uint8_t **data, uint16_t *size)
353 {
354  if((NULL == data) || (NULL == size))
355  {
356  yError() << "eo BoardTransceiver::getTransmit() called with NULL data or size";
357  return;
358  }
359 
360  uint16_t numofrops;
361  EOpacket* ptrpkt = NULL;
362  eOresult_t res;
363 
364  *size = 0;
365  *data = NULL;
366 
367 
368  res = eo_transceiver_outpacket_Prepare(transceiver, &numofrops);
369  if(eores_OK != res)
370  {
371  yError() << "eo BoardTransceiver::getTransmit(): failure of eo_transceiver_outpacket_Prepare()";
372  return;
373  }
374 
375  res = eo_transceiver_outpacket_Get(transceiver, &ptrpkt);
376  if(eores_OK != res)
377  {
378  yError() << "eo BoardTransceiver::getTransmit(): failure of eo_transceiver_outpacket_Get()";
379  return;
380  }
381 
382  // now ptrpkt points to internal tx packet of the transceiver.
383  eo_packet_Payload_Get(ptrpkt, data, size);
384 }
385 
386 
387 
389 {
390  return(protboardnumber);
391 }
392 
393 
394 void embOBJerror(eOerrmanErrorType_t errtype, eOid08_t taskid, const char *eobjstr, const char *info)
395 {
396  static const char* theerrors[] = { "eo_errortype_info", "eo_errortype_warning", "eo_errortype_weak", "eo_errortype_fatal" };
397 
398  yError() << "embOBJerror(): errtype = " << theerrors[errtype] << "from EOobject = " << eobjstr << " w/ message = " << info;
399 
400  if(errtype == eo_errortype_fatal)
401  {
402  yError() << "embOBJerror(): FATAL ERROR: the calling thread shall now be stopped in a forever loop here inside";
403  for(;;);
404  }
405 
406 }
407 
408 void eoy_initialise(void)
409 {
410  // marco.accame: in here we init the embOBJ system for YARP.
411  eOerrman_cfg_t errmanconfig = {0};
412  errmanconfig.extfn.usr_on_error = embOBJerror;
413  const eOysystem_cfg_t *syscfg = NULL;
414  const eOmempool_cfg_t *mpoolcfg = NULL; // uses standard mode
415  //const eOerrman_cfg_t *errmancf = NULL; // uses default mode
416  eoy_sys_Initialise(syscfg, mpoolcfg, &errmanconfig);
417 }
418 
419 bool BoardTransceiver::initProtocol(yarp::os::Searchable &config)
420 {
421  static bool alreadyinitted = false;
422 
423  if(false == alreadyinitted)
424  {
425  // before using embOBJ we need initialing its system. it is better to init it again in case someone did not do it
426  eoy_initialise();
427 
428  static const uint8_t numOfBoardsinRobot = eoprot_boards_maxnumberof; // to be initialise later or w/ a proper number from XML ...
429 
430  // init the protocol to manage all boards of the robot
431  if(eores_OK != eoprot_config_board_numberof(numOfBoardsinRobot))
432  {
433  yError() << "BoardTransceiver::initProtocol(): call to eoprot_config_board_numberof() fails.";
434  return(false);
435  }
436 
437  // configure all the callbacks of all endpoints.
438 
439  eoprot_override_mn();
440  eoprot_override_mc();
441  eoprot_override_as();
442  eoprot_override_sk();
443 
444  // ok. all is done correctly
445  alreadyinitted = true;
446 
447  // yWarning() << "BoardTransceiver::initProtocol() CALLED W/ INITIALISATION";
448  }
449  else
450  {
451  // yWarning() << "BoardTransceiver::initProtocol() CALLED W/OUT INITIALISATION";
452  }
453 
454  return(true);
455 }
456 
457 extern "C" {
458 void boardtransceiver_fun_UPDT_mn_appl_cmmnds_go2state(const EOnv* nv, const eOropdescriptor_t* rd);
459 }
460 
461 void BoardTransceiver::eoprot_override_mn(void)
462 { // nothing to do
463 
464  static const eOprot_callbacks_endpoint_descriptor_t mn_callbacks_descriptor_endp =
465  {
466  EO_INIT(.endpoint) eoprot_endpoint_management,
467  EO_INIT(.raminitialise) NULL // or any xxeoprot_fun_INITIALISE_mn
468  };
469 
470  static const eOprot_callbacks_variable_descriptor_t mn_callbacks_descriptors_vars[] =
471  {
472  // appl
473  { //
474  EO_INIT(.endpoint) eoprot_endpoint_management,
475  EO_INIT(.entity) eoprot_entity_mn_appl,
476  EO_INIT(.tag) eoprot_tag_mn_appl_cmmnds_go2state,
477  EO_INIT(.init) NULL,
479  }
480  };
481 
482 
483  // ------------------------------------------------------------------------------------------------------------------------------------
484  // -- general ram initialise of sk endpoint called by every board.
485 
486  // we dont do any general initialisation, even if we could do it with a xxeoprot_fun_INITIALISE_sk() function
487  //eoprot_config_callbacks_endpoint_set(&sk_callbacks_descriptor_endp);
488 
489 
490  // ------------------------------------------------------------------------------------------------------------------------------------
491  // -- override of the callbacks of variables of mc. common to every board. we use the id, even if the eoprot_config_variable_callback()
492  // operates on any index.
493 
494  uint32_t number = sizeof(mn_callbacks_descriptors_vars)/sizeof(mn_callbacks_descriptors_vars[0]);
495  uint32_t i = 0;
496 
497  for(i=0; i<number; i++)
498  {
499  eoprot_config_callbacks_variable_set(&mn_callbacks_descriptors_vars[i]);
500  }
501 }
502 
503 extern "C" {
504 void boardtransceiver_fun_UPDT_mc_joint_cmmnds_interactionmode(const EOnv* nv, const eOropdescriptor_t* rd);
505 }
506 
507 void BoardTransceiver::eoprot_override_mc(void)
508 {
509 
510  static const eOprot_callbacks_endpoint_descriptor_t mc_callbacks_descriptor_endp =
511  {
512  EO_INIT(.endpoint) eoprot_endpoint_motioncontrol,
513  EO_INIT(.raminitialise) NULL // or any xxeoprot_fun_INITIALISE_mc
514  };
515 
516  static const eOprot_callbacks_variable_descriptor_t mc_callbacks_descriptors_vars[] =
517  {
518  // joint
519 #if 0
520  { // joint_config
521  EO_INIT(.endpoint) eoprot_endpoint_motioncontrol,
522  EO_INIT(.entity) eoprot_entity_mc_joint,
523  EO_INIT(.tag) eoprot_tag_mc_joint_config,
524  EO_INIT(.init) NULL,
525  EO_INIT(.update) eoprot_fun_UPDT_mc_joint_config
526  },
527  { // joint_config_pidposition
528  EO_INIT(.endpoint) eoprot_endpoint_motioncontrol,
529  EO_INIT(.entity) eoprot_entity_mc_joint,
530  EO_INIT(.tag) eoprot_tag_mc_joint_config_pidposition,
531  EO_INIT(.init) NULL,
532  EO_INIT(.update) eoprot_fun_UPDT_mc_joint_config_pidposition
533  },
534  { // joint_config_impedance
535  EO_INIT(.endpoint) eoprot_endpoint_motioncontrol,
536  EO_INIT(.entity) eoprot_entity_mc_joint,
537  EO_INIT(.tag) eoprot_tag_mc_joint_config_impedance,
538  EO_INIT(.init) NULL,
539  EO_INIT(.update) eoprot_fun_UPDT_mc_joint_config_impedance
540  },
541  { // joint_config_pidtorque
542  EO_INIT(.endpoint) eoprot_endpoint_motioncontrol,
543  EO_INIT(.entity) eoprot_entity_mc_joint,
544  EO_INIT(.tag) eoprot_tag_mc_joint_config_pidtorque,
545  EO_INIT(.init) NULL,
546  EO_INIT(.update) eoprot_fun_UPDT_mc_joint_config_pidtorque
547  },
548  { // joint_status
549  EO_INIT(.endpoint) eoprot_endpoint_motioncontrol,
550  EO_INIT(.entity) eoprot_entity_mc_joint,
551  EO_INIT(.tag) eoprot_tag_mc_joint_status,
552  EO_INIT(.init) NULL,
553  EO_INIT(.update) eoprot_fun_UPDT_mc_joint_status
554  },
555  { // joint_status_basic
556  EO_INIT(.endpoint) eoprot_endpoint_motioncontrol,
557  EO_INIT(.entity) eoprot_entity_mc_joint,
558  EO_INIT(.tag) eoprot_tag_mc_joint_status_basic,
559  EO_INIT(.init) NULL,
560  EO_INIT(.update) eoprot_fun_UPDT_mc_joint_status_basic
561  },
562  { // joint_cmmnds_setpoint731
563  EO_INIT(.endpoint) eoprot_endpoint_motioncontrol,
564  EO_INIT(.entity) eoprot_entity_mc_joint,
565  EO_INIT(.tag) eoprot_tag_mc_joint_cmmnds_setpoint,
566  EO_INIT(.init) NULL,
567  EO_INIT(.update) eoprot_fun_UPDT_mc_joint_cmmnds_setpoint
568  },
569  { // joint_config_limitsofjoint
570  EO_INIT(.endpoint) eoprot_endpoint_motioncontrol,
571  EO_INIT(.entity) eoprot_entity_mc_joint,
572  EO_INIT(.tag) eoprot_tag_mc_joint_config_limitsofjoint,
573  EO_INIT(.init) NULL,
574  EO_INIT(.update) eoprot_fun_UPDT_mc_joint_config_limitsofjoint
575  },
576  // motor
577  { // motor_config
578  EO_INIT(.endpoint) eoprot_endpoint_motioncontrol,
579  EO_INIT(.entity) eoprot_entity_mc_motor,
580  EO_INIT(.tag) eoprot_tag_mc_motor_config,
581  EO_INIT(.init) NULL,
582  EO_INIT(.update) eoprot_fun_UPDT_mc_motor_config
583  },
584  { // motor_config_maxcurrentofmotor
585  EO_INIT(.endpoint) eoprot_endpoint_motioncontrol,
586  EO_INIT(.entity) eoprot_entity_mc_motor,
587  EO_INIT(.tag) eoprot_tag_mc_motor_config_maxcurrentofmotor,
588  EO_INIT(.init) NULL,
589  EO_INIT(.update) eoprot_fun_UPDT_mc_motor_config_maxcurrentofmotor
590  },
591  { // motor_status_basic
592  EO_INIT(.endpoint) eoprot_endpoint_motioncontrol,
593  EO_INIT(.entity) eoprot_entity_mc_motor,
594  EO_INIT(.tag) eoprot_tag_mc_motor_status_basic,
595  EO_INIT(.init) NULL,
596  EO_INIT(.update) eoprot_fun_UPDT_mc_motor_status_basic
597  }
598 #endif
599 
600  // in here put what the ems needs to do when some variables arrive
601 
602  { // ...............
603  EO_INIT(.endpoint) eoprot_endpoint_motioncontrol,
604  EO_INIT(.entity) eoprot_entity_mc_joint,
605  EO_INIT(.tag) eoprot_tag_mc_joint_cmmnds_interactionmode,
606  EO_INIT(.init) NULL,
608  }
609  };
610 
611 
612  // ------------------------------------------------------------------------------------------------------------------------------------
613  // -- general ram initialise of mc endpoint called by every board.
614 
615  // we dont do any general initialisation, even if we could do it with a xxeoprot_fun_INITIALISE_mc() function
616  //eoprot_config_callbacks_endpoint_set(&mc_callbacks_descriptor_endp);
617 
618 
619  // ------------------------------------------------------------------------------------------------------------------------------------
620  // -- override of the callbacks of variables of mc. common to every board. we use the id, even if the eoprot_config_variable_callback()
621  // operates on any index.
622 
623  uint32_t number = sizeof(mc_callbacks_descriptors_vars)/sizeof(mc_callbacks_descriptors_vars[0]);
624  uint32_t i = 0;
625 
626  for(i=0; i<number; i++)
627  {
628  eoprot_config_callbacks_variable_set(&mc_callbacks_descriptors_vars[i]);
629  }
630 
631 }
632 
633 
634 void BoardTransceiver::eoprot_override_as(void)
635 {
636 
637  // dont configure anything for now
638 #if 0
639 
640  static const eOprot_callbacks_endpoint_descriptor_t as_callbacks_descriptor_endp =
641  {
642  EO_INIT(.endpoint) eoprot_endpoint_analogsensors,
643  EO_INIT(.raminitialise) NULL // or any xxeoprot_fun_INITIALISE_as
644  };
645 
646  static const eOprot_callbacks_variable_descriptor_t as_callbacks_descriptors_vars[] =
647  {
648  // strain
649  { // strain_status_calibratedvalues
650  EO_INIT(.endpoint) eoprot_endpoint_analogsensors,
651  EO_INIT(.entity) eoprot_entity_as_strain,
652  EO_INIT(.tag) eoprot_tag_as_strain_status_calibratedvalues,
653  EO_INIT(.init) NULL,
655  },
656  { // strain_status_uncalibratedvalues
657  EO_INIT(.endpoint) eoprot_endpoint_analogsensors,
658  EO_INIT(.entity) eoprot_entity_as_strain,
659  EO_INIT(.tag) eoprot_tag_as_strain_status_uncalibratedvalues,
660  EO_INIT(.init) NULL,
662  },
663  // mais
664  { // mais_status_the15values
665  EO_INIT(.endpoint) eoprot_endpoint_analogsensors,
666  EO_INIT(.entity) eoprot_entity_as_mais,
667  EO_INIT(.tag) eoprot_tag_as_mais_status_the15values,
668  EO_INIT(.init) NULL,
670  }
671  };
672 
673 
674  // ------------------------------------------------------------------------------------------------------------------------------------
675  // -- general ram initialise of as endpoint called by every board.
676 
677  // we dont do any general initialisation, even if we could do it with a xxeoprot_fun_INITIALISE_as() function
678  //eoprot_config_callbacks_endpoint_set(&as_callbacks_descriptor_endp);
679 
680 
681 
682  // ------------------------------------------------------------------------------------------------------------------------------------
683  // -- override of the callbacks of variables of mc. common to every board. we use the id, even if the eoprot_config_variable_callback()
684  // operates on any index.
685 
686  uint32_t number = sizeof(as_callbacks_descriptors_vars)/sizeof(as_callbacks_descriptors_vars[0]);
687  uint32_t i = 0;
688 
689  for(i=0; i<number; i++)
690  {
691  eoprot_config_callbacks_variable_set(&as_callbacks_descriptors_vars[i]);
692  }
693 
694 #endif
695 }
696 
697 
698 void BoardTransceiver::eoprot_override_sk(void)
699 {
700  // dont configure anything for now
701 #if 0
702  static const eOprot_callbacks_endpoint_descriptor_t sk_callbacks_descriptor_endp =
703  {
704  EO_INIT(.endpoint) eoprot_endpoint_skin,
705  EO_INIT(.raminitialise) NULL // or any xxeoprot_fun_INITIALISE_sk
706  };
707 
708  static const eOprot_callbacks_variable_descriptor_t sk_callbacks_descriptors_vars[] =
709  {
710  // skin
711  { // strain_status_calibratedvalues
712  EO_INIT(.endpoint) eoprot_endpoint_skin,
713  EO_INIT(.entity) eoprot_entity_sk_skin,
714  EO_INIT(.tag) eoprot_tag_sk_skin_status_arrayof10canframes,
715  EO_INIT(.init) NULL,
716  EO_INIT(.update) eoprot_fun_UPDT_sk_skin_status_arrayof10canframes
717  }
718  };
719 
720 
721  // ------------------------------------------------------------------------------------------------------------------------------------
722  // -- general ram initialise of sk endpoint called by every board.
723 
724  // we dont do any general initialisation, even if we could do it with a xxeoprot_fun_INITIALISE_sk() function
725  //eoprot_config_callbacks_endpoint_set(&sk_callbacks_descriptor_endp);
726 
727 
728  // ------------------------------------------------------------------------------------------------------------------------------------
729  // -- override of the callbacks of variables of mc. common to every board. we use the id, even if the eoprot_config_variable_callback()
730  // operates on any index.
731 
732  uint32_t number = sizeof(sk_callbacks_descriptors_vars)/sizeof(sk_callbacks_descriptors_vars[0]);
733  uint32_t i = 0;
734 
735  for(i=0; i<number; i++)
736  {
737  eoprot_config_callbacks_variable_set(&sk_callbacks_descriptors_vars[i]);
738  }
739 #endif
740 }
741 
742 
743 void cpp_protocol_callback_incaseoferror_in_sequencenumberReceived(uint32_t remipv4addr, uint64_t rec_seqnum, uint64_t expected_seqnum)
744 {
745  long long unsigned int exp = expected_seqnum;
746  long long unsigned int rec = rec_seqnum;
747  printf("Error in sequence number from 0x%x!!!! \t Expected %llu, received %llu\n", remipv4addr, exp, rec);
748 };
749 
750 //extern "C" {
751 //extern void protocol_callback_incaseoferror_in_sequencenumberReceived(uint32_t remipv4addr, uint64_t rec_seqnum, uint64_t expected_seqnum);
752 //}
753 
754 
755 bool BoardTransceiver::prepareTransceiverConfig(yarp::os::Searchable &config)
756 {
757 
758  memcpy(&devtxrxcfg, &eo_devicetransceiver_cfg_default, sizeof(eOdevicetransceiver_cfg_t));
759 
760  // the nvsetcfg of the board ...
761  devtxrxcfg.nvsetdevcfg = getNVset_DEVcfg(config);
762 
763  if(NULL == devtxrxcfg.nvsetdevcfg)
764  {
765  return(false);
766  }
767 
768  devtxrxcfg.remotehostipv4addr = remoteipaddr;
769  devtxrxcfg.remotehostipv4port = remoteipport;
770 
771 
772  const eOtransceiver_sizes_t devsizes =
773  {
774  EO_INIT(.capacityoftxpacket) 1408,
775  EO_INIT(.capacityofrop) 256,
776  EO_INIT(.capacityofropframeregulars) 1024,
777  EO_INIT(.capacityofropframeoccasionals) 128,
778  EO_INIT(.capacityofropframereplies) 256,
779  EO_INIT(.maxnumberofregularrops) 32
780  };
781 
782  memcpy(&devtxrxcfg.sizes, &devsizes, sizeof(eOtransceiver_sizes_t));
783 
784 
785 
786 
787  // other configurable parameters for eOhosttransceiver_cfg_t
788  // - mutex_fn_new, transprotection, nvsetprotection are left (NULL, eo_trans_protection_none, eo_nvset_protection_none)
789  // as in default because we dont protect internally w/ a mutex
790  // - proxycfg is left NULL as in default because we dont use a proxy.
791 
792  // marco.accame on 29 apr 2014: so that the EOreceiver calls this funtion in case of error in sequence number
793  devtxrxcfg.extfn.onerrorseqnumber = cpp_protocol_callback_incaseoferror_in_sequencenumberReceived;
794 
795 
796  return(true);
797 }
798 
799 
800 
801 
802 const eOnvset_DEVcfg_t * BoardTransceiver::getNVset_DEVcfg(yarp::os::Searchable &config)
803 {
804 
805  const eOnvset_DEVcfg_t* nvsetdevcfg = NULL;
806 
807 
808 
809  nvsetdevcfg = NULL;
810 
811  eOprotconfig_cfg_t protcfg;
812  memcpy(&protcfg, &eo_protconfig_cfg_default, sizeof(eOprotconfig_cfg_t));
813  // ok, now i get the values from config and run ...
814 
815  // at least ... this one
816  protcfg.board = get_protBRDnumber();
817 
818  if(config.isNull())
819  {
820  yWarning() << "BoardTransceiver-> board " << get_protBRDnumber()+1 << " misses: entire PROTOCOL group ... using max capabilities";
821  //return false;
822  }
823  else
824  {
825  int number;
826 
827  if(false == config.check("endpointManagementIsSupported"))
828  {
829  yWarning() << "BoardTransceiver-> board " << get_protBRDnumber()+1 << " misses: mandatory config of entire MN endpoint ... enabled w/ max capabilities" <<
830  " (comm, appl) = (" << protcfg.en_mn_entity_comm_numberof << ", " << protcfg.en_mn_entity_appl_numberof << ")";
831  }
832  else if((false == config.check("entityMNcommunicationNumberOf")) || (false == config.check("entityMNapplicationNumberOf")))
833  {
834  yWarning() << "BoardTransceiver-> board " << get_protBRDnumber()+1 << " misses: mandatory config of some MN entities ... using max capabilities" <<
835  " (comm, appl) = (" << protcfg.en_mn_entity_comm_numberof << ", " << protcfg.en_mn_entity_appl_numberof << ")";
836  }
837  else
838  {
839  // ok, retrieve the numbers ...
840  number = config.find("endpointManagementIsSupported").asInt32();
841  protcfg.ep_management_is_present = (0 == number) ? (eobool_false) : (eobool_true);
842  if(eobool_true == protcfg.ep_management_is_present)
843  {
844  protcfg.en_mn_entity_comm_numberof = config.find("entityMNcommunicationNumberOf").asInt32();
845  protcfg.en_mn_entity_appl_numberof = config.find("entityMNapplicationNumberOf").asInt32();
846  }
847  else
848  {
849  protcfg.en_mn_entity_comm_numberof = 0;
850  protcfg.en_mn_entity_appl_numberof = 0;
851  }
852  // sanity check
853  if((protcfg.en_mn_entity_comm_numberof > 1) || (protcfg.en_mn_entity_appl_numberof > 1))
854  {
855  yWarning() << "BoardTransceiver-> board " << get_protBRDnumber()+1 << " has: a strange number of MN entities" <<
856  " (comm, appl) = (" << protcfg.en_mn_entity_comm_numberof << ", " << protcfg.en_mn_entity_appl_numberof << ")";
857  }
858 
859  }
860 
861 
862  if(false == config.check("endpointMotionControlIsSupported"))
863  {
864  yWarning() << "BoardTransceiver-> board " << get_protBRDnumber()+1 << " misses: mandatory config of entire MC endpoint ... enabled w/ max capabilities" <<
865  " (joint, motor, contr) = (" << protcfg.en_mc_entity_joint_numberof << ", " << protcfg.en_mc_entity_motor_numberof <<
866  ", " << protcfg.en_mc_entity_controller_numberof << ")";
867  }
868  else if((false == config.check("entityMCjointNumberOf")) || (false == config.check("entityMCmotorNumberOf")) ||
869  (false == config.check("entityMCmotorNumberOf")))
870  {
871  yWarning() << "BoardTransceiver-> board " << get_protBRDnumber()+1 << " misses: mandatory config of some MC entities ... using max capabilities" <<
872  " (joint, motor, contr) = (" << protcfg.en_mc_entity_joint_numberof << ", " << protcfg.en_mc_entity_motor_numberof <<
873  ", " << protcfg.en_mc_entity_controller_numberof << ")";
874  }
875  else
876  {
877  number = config.find("endpointMotionControlIsSupported").asInt32();
878  protcfg.ep_motioncontrol_is_present = (0 == number) ? (eobool_false) : (eobool_true);
879  if(eobool_true == protcfg.ep_motioncontrol_is_present)
880  {
881  protcfg.en_mc_entity_joint_numberof = config.find("entityMCjointNumberOf").asInt32();
882  protcfg.en_mc_entity_motor_numberof = config.find("entityMCmotorNumberOf").asInt32();
883  protcfg.en_mc_entity_controller_numberof = config.find("entityMCcontrollerNumberOf").asInt32();
884  }
885  else
886  {
887  protcfg.en_mc_entity_joint_numberof = 0;
888  protcfg.en_mc_entity_motor_numberof = 0;
889  protcfg.en_mc_entity_controller_numberof = 0;
890  }
891  // sanity check
892  if((protcfg.en_mc_entity_joint_numberof > 16) || (protcfg.en_mc_entity_motor_numberof > 16) ||
893  (protcfg.en_mc_entity_controller_numberof > 1))
894  {
895  yWarning() << "BoardTransceiver-> board " << get_protBRDnumber()+1 << " has: a strange number of MC entities" <<
896  " (joint, motor, contr) = (" << protcfg.en_mc_entity_joint_numberof << ", " << protcfg.en_mc_entity_motor_numberof <<
897  ", " << protcfg.en_mc_entity_controller_numberof << ")";
898  }
899  }
900 
901 
902  if(false == config.check("endpointAnalogSensorsIsSupported"))
903  {
904  yWarning() << "BoardTransceiver-> board " << get_protBRDnumber()+1 << " misses: mandatory config of entire AS endpoint ... enabled w/ max capabilities" <<
905  " (strain, mais, extorque) = (" << protcfg.en_as_entity_strain_numberof << ", " << protcfg.en_as_entity_mais_numberof <<
906  ", " << protcfg.en_as_entity_extorque_numberof << ")";
907  }
908  else if((false == config.check("entityASstrainNumberOf")) || (false == config.check("entityASmaisNumberOf")) ||
909  (false == config.check("entityASextorqueNumberOf")))
910  {
911  yWarning() << "BoardTransceiver-> board " << get_protBRDnumber()+1 << " misses: mandatory config of some AS entities ... using max capabilities" <<
912  " (strain, mais, extorque) = (" << protcfg.en_as_entity_strain_numberof << ", " << protcfg.en_as_entity_mais_numberof <<
913  ", " << protcfg.en_as_entity_extorque_numberof << ")";
914  }
915  else
916  {
917  number = config.find("endpointAnalogSensorsIsSupported").asInt32();
918  protcfg.ep_analogsensors_is_present = (0 == number) ? (eobool_false) : (eobool_true);
919  if(eobool_true == protcfg.ep_analogsensors_is_present)
920  {
921  protcfg.en_as_entity_strain_numberof = config.find("entityASstrainNumberOf").asInt32();
922  protcfg.en_as_entity_mais_numberof = config.find("entityASmaisNumberOf").asInt32();
923  protcfg.en_as_entity_extorque_numberof = config.find("entityASextorqueNumberOf").asInt32();
924  }
925  else
926  {
927  protcfg.en_as_entity_strain_numberof = 0;
928  protcfg.en_as_entity_mais_numberof = 0;
929  protcfg.en_as_entity_extorque_numberof = 0;
930  }
931  // sanity check
932  if((protcfg.en_as_entity_strain_numberof > 1) || (protcfg.en_as_entity_mais_numberof > 1) ||
933  (protcfg.en_as_entity_extorque_numberof > 16))
934  {
935  yWarning() << "BoardTransceiver-> board " << get_protBRDnumber()+1 << " has: a strange number of AS entities" <<
936  " (strain, mais, extorque) = (" << protcfg.en_as_entity_strain_numberof << ", " << protcfg.en_as_entity_mais_numberof <<
937  ", " << protcfg.en_as_entity_extorque_numberof << ")";
938  }
939  }
940 
941 
942  if(false == config.check("endpointSkinIsSupported"))
943  {
944  yWarning() << "BoardTransceiver-> board " << get_protBRDnumber()+1 << " misses: mandatory config of entire SK endpoint ... enabled w/ max capabilities" <<
945  " (skin) = (" << protcfg.en_sk_entity_skin_numberof << ")";
946  }
947  else if((false == config.check("entitySKskinNumberOf")))
948  {
949  yWarning() << "BoardTransceiver-> board " << get_protBRDnumber()+1 << " misses: mandatory config of some SK entities ... using max capabilities" <<
950  " (skin) = (" << protcfg.en_sk_entity_skin_numberof << ")";
951  }
952  else
953  {
954  number = config.find("endpointSkinIsSupported").asInt32();
955  protcfg.ep_skin_is_present = (0 == number) ? (eobool_false) : (eobool_true);
956  if(eobool_true == protcfg.ep_skin_is_present)
957  {
958  protcfg.en_sk_entity_skin_numberof = config.find("entitySKskinNumberOf").asInt32();
959  }
960  else
961  {
962  protcfg.en_sk_entity_skin_numberof = 0;
963  }
964  // sanity check
965  if((protcfg.en_sk_entity_skin_numberof > 2))
966  {
967  yWarning() << "BoardTransceiver-> board " << get_protBRDnumber()+1 << " has: a strange number of SK entities" <<
968  " (skin) = (" << protcfg.en_sk_entity_skin_numberof << ")";
969  }
970 
971  }
972 
973  printf("\nprotcfg --> bdr %d, mn = %d, mc = %d, as = %d, sk = %d ... co = %d, ap = %d, jn = %d, mt = %d, ct = %d, st = %d, ma = %d, ex = %d, sk = %d\n",
974  protcfg.board,
975  protcfg.ep_management_is_present, protcfg.ep_motioncontrol_is_present, protcfg.ep_analogsensors_is_present, protcfg.ep_skin_is_present,
976  protcfg.en_mn_entity_comm_numberof, protcfg.en_mn_entity_appl_numberof,
977  protcfg.en_mc_entity_joint_numberof, protcfg.en_mc_entity_motor_numberof, protcfg.en_mc_entity_controller_numberof,
978  protcfg.en_as_entity_strain_numberof, protcfg.en_as_entity_mais_numberof, protcfg.en_as_entity_extorque_numberof,
979  protcfg.en_sk_entity_skin_numberof
980  );
981 
982 
983  }
984 
985 
986 
987  nvsetdevcfg = eo_protconfig_DEVcfg_Get(eo_protconfig_New(&protcfg));
988 
989 
990  if(NULL == nvsetdevcfg)
991  {
992  yError() << "BoardTransceiver::getNVset_DEVcfg() -> FAILS as it produces a NULL result";
993  }
994 
995  return(nvsetdevcfg);
996 }
997 
998 #if 0
999 void boardtransceiver_fun_UPDT_mn_appl_cmmnds_go2state(const EOnv* nv, const eOropdescriptor_t* rd)
1000 {
1001  eOmn_appl_state_t *newstate_ptr = (eOmn_appl_state_t *)rd->data;
1002 
1003  switch(*newstate_ptr)
1004  {
1005  case applstate_running:
1006  case applstate_config:
1007  case applstate_error:
1008  {
1009  //applstate = *newstate_ptr;
1010  } break;
1011  }
1012 }
1013 
1014 void boardtransceiver_fun_UPDT_mc_joint_cmmnds_interactionmode(const EOnv* nv, const eOropdescriptor_t* rd)
1015 {
1016  EOnv_hid aNV = {0};
1017  eOnvBRD_t brd = eo_nv_GetBRD(nv);
1018 
1019  EOnvSet* mynvset = arrayofnvsets[brd];
1020 
1021  eOprotIndex_t index = eoprot_ID2index(rd->id32);
1022  eOenum08_t* pmode = (eOenum08_t*) rd->data;
1023 
1024  eOnvID32_t id32status = eoprot_ID_get(eoprot_endpoint_motioncontrol, eoprot_entity_mc_joint, index, eoprot_tag_mc_joint_status);
1025  eo_nvset_NV_Get(mynvset, eok_ipv4addr_localhost, id32status, &aNV);
1026 
1027  eOmc_joint_status_t jointstatus = {0};
1028  uint16_t size = 0;
1029 
1030  eOresult_t res = eo_nv_Get(&aNV, eo_nv_strg_volatile, &jointstatus, &size);
1031  jointstatus.interactionmodestatus = *pmode;
1032  eo_nv_Set(&aNV, &jointstatus, eobool_true, eo_nv_upd_dontdo);
1033 
1034 }
1035 #endif
1036 
1037 // eof
1038 
1039 
1040 
void eoprot_fun_UPDT_as_strain_status_calibratedvalues(const EOnv *nv, const eOropdescriptor_t *rd)
void eoprot_fun_UPDT_as_strain_status_uncalibratedvalues(const EOnv *nv, const eOropdescriptor_t *rd)
void eoprot_fun_UPDT_as_mais_status_the15values(const EOnv *nv, const eOropdescriptor_t *rd)
void eoprot_fun_UPDT_mc_joint_status(const EOnv *nv, const eOropdescriptor_t *rd)
@ data
void cpp_protocol_callback_incaseoferror_in_sequencenumberReceived(uint32_t remipv4addr, uint64_t rec_seqnum, uint64_t expected_seqnum)
EOnvSet * arrayofnvsets[16]
void boardtransceiver_fun_UPDT_mn_appl_cmmnds_go2state(const EOnv *nv, const eOropdescriptor_t *rd)
void embOBJerror(eOerrmanErrorType_t errtype, eOid08_t taskid, const char *eobjstr, const char *info)
void eoy_initialise(void)
void boardtransceiver_fun_UPDT_mc_joint_cmmnds_interactionmode(const EOnv *nv, const eOropdescriptor_t *rd)
exp(-x3 *T)]
ACE_UINT64 txtime
#define RECV_BUFFER_SIZE
virtual void onMsgReception(uint8_t *data, uint16_t size)
bool init(yarp::os::Searchable &config, uint32_t localipaddr, uint32_t remoteipaddr, uint16_t ipport, uint16_t pktsize, FEAT_boardnumber_t board_n)
bool createSocket(ACE_INET_Addr local_addr)
bool configure(yarp::os::ResourceFinder &rf)
void fromDouble(ACE_Time_Value &v, double x, int unit)
void getTransmit(uint8_t **data, uint16_t *size)
eOprotBRD_t get_protBRDnumber(void)
eOprotBRD_t featIdBoardNum2nvBoardNum(FEAT_boardnumber_t fid_boardnum)
uint8_t FEAT_boardnumber_t