13#include <yarp/os/Time.h>
14#include <yarp/os/Network.h>
15#include <yarp/conf/environment.h>
16#include <yarp/os/NetType.h>
19#include "EOropframe_hid.h"
21#include "EoProtocol.h"
22#include "EoManagement.h"
23#include "EoProtocolMN.h"
26using namespace yarp::os;
27using namespace yarp::os::impl;
42 isInRunningMode =
false;
44 verifiedBoardPresence =
false;
45 askedBoardVersion =
false;
46 verifiedBoardTransceiver =
false;
48 cleanedBoardBehaviour =
false;
50 boardMNprotocolversion.major = boardMNprotocolversion.minor;
52 txconfig.runnermode = eomn_appl_runnermode_synchronized;
53 txconfig.safetygap = 0;
54 txconfig.cycletime = defcycletime;
55 txconfig.txratedivider = defTXrateOfRegularROPs;
56 txconfig.maxtimeRX = defmaxtimeRX;
57 txconfig.maxtimeDO = defmaxtimeDO;
58 txconfig.maxtimeTX = defmaxtimeTX;
59 txconfig.logging.flags = (0x0001 << eomn_appl_log_asynchro_exectime_rxdotx_overflow);
60 txconfig.logging.period10ms = 0;
62 memset(verifiedEPprotocol, 0,
sizeof(verifiedEPprotocol));
64 usedNumberOfRegularROPs = 0;
66 for(
int i = 0; i<16; i++)
68 c_string_handler[i] = NULL;
71 std::string tmp = yarp::conf::environment::get_string(
"ETH_VERBOSEWHENOK");
74 verbosewhenok = (bool)(yarp::conf::numeric::from_string(tmp, 0U));
78 verbosewhenok =
false;
83 regularsAreSet =
false;
92 for(
int i=0; i<16; i++)
94 if (c_string_handler[i] != NULL)
96 delete c_string_handler[i];
97 c_string_handler[i] = NULL;
102bool EthResource::lock(
bool on)
128 properties.ipv4addr = remIP;
135 properties.txROPratedivider = txconfig.txratedivider;
154 eOipv4addressing_t localIPv4 = ethManager->getLocalIPV4addressing();
157 if(
false == transceiver.init2(
this, cfgtotal, localIPv4, remIP))
159 yError() <<
"EthResource::open2() cannot init transceiver w/ HostTransceiver::init2() for BOARD" << properties.boardnameString <<
"IP" << properties.ipv4addrString;
166 monitorpresence.config(mpConfig);
167 monitorpresence.tick();
187 destination = properties.ipv4addressing;
188 const void * udp = transceiver.getUDP(sizeofpacket, numofrops);
207 monitorpresence.tick();
214 if(
false == regularsAreSet)
219 return monitorpresence.check();
226 return transceiver.parseUDP(
data, size);
244bool EthResource::isRunning(
void)
246 return(isInRunningMode);
251bool EthResource::verifyBoardTransceiver()
255 if(verifiedBoardTransceiver)
261#define DONT_ASK_COMM_STATUS
263#if defined(DONT_ASK_COMM_STATUS)
265 const eoprot_version_t * pc104versionMN = eoprot_version_of_endpoint_get(eoprot_endpoint_management);
266 const eoprot_version_t * brdversionMN = &boardMNprotocolversion;
275 const eoprot_version_t * pc104versionMN = eoprot_version_of_endpoint_get(eoprot_endpoint_management);
276 const double timeout = 0.100;
278 eOprotID32_t id32 = eoprot_ID_get(eoprot_endpoint_management, eoprot_entity_mn_comm, 0, eoprot_tag_mn_comm_status);
279 eOmn_comm_status_t brdstatus = {0};
282 bool rr = nvman.
ask(ipv4addr, id32, &brdstatus, timeout);
290 eoprot_version_t * brdversionMN = (eoprot_version_t*)&brdstatus.managementprotocolversion;
294 if(pc104versionMN->major != brdversionMN->major)
296 yError() <<
"EthResource::verifyBoardTransceiver() detected different mn protocol major versions: local =" << pc104versionMN->major <<
", remote =" << brdversionMN->major <<
": cannot proceed any further";
301 if(pc104versionMN->minor != brdversionMN->minor)
303 yError() <<
"EthResource::verifyBoardTransceiver() detected different mn protocol minor versions: local =" << pc104versionMN->minor <<
", remote =" << brdversionMN->minor <<
": cannot proceed any further.";
314 verifiedBoardTransceiver =
true;
321bool EthResource::setTimingOfRunningCycle()
334 eOprotID32_t id32 = eoprot_ID_get(eoprot_endpoint_management, eoprot_entity_mn_appl, 0, eoprot_tag_mn_appl_config);
338 if(
false == nvman.
setcheck(properties.ipv4addr, id32, &txconfig, 5, 0.010, 2.0))
340 yWarning() <<
"EthResource::setTimingOfRunningCycle() for BOARD" <<
getProperties().
boardnameString <<
"with IP" <<
getProperties().
ipv4addrString <<
"could not configure: cycletime =" << txconfig.cycletime <<
"usec, RX DO TX = (" << txconfig.maxtimeRX << txconfig.maxtimeDO << txconfig.maxtimeTX <<
") usec and TX rate =" << txconfig.txratedivider <<
" every cycle";
347 yDebug() <<
"EthResource::setTimingOfRunningCycle() for BOARD" <<
getProperties().
boardnameString <<
"with IP" <<
getProperties().
ipv4addrString <<
"has succesfully set: cycletime =" << txconfig.cycletime <<
"usec, RX DO TX = (" << txconfig.maxtimeRX << txconfig.maxtimeDO << txconfig.maxtimeTX <<
") usec and TX rate =" << txconfig.txratedivider <<
" every cycle";
358bool EthResource::cleanBoardBehaviour(
void)
360 if(cleanedBoardBehaviour)
372 regularsAreSet =
false;
380 cleanedBoardBehaviour =
true;
386bool EthResource::testMultipleASK()
394 eOprotID32_t id32_commstatus = eoprot_ID_get(eoprot_endpoint_management, eoprot_entity_mn_comm, 0, eoprot_tag_mn_comm_status);
395 eOmn_comm_status_t value_commstatus = {0};
397 eOprotID32_t id32_applconfig = eoprot_ID_get(eoprot_endpoint_management, eoprot_entity_mn_appl, 0, eoprot_tag_mn_appl_config);
398 eOmn_appl_config_t value_applconfig = {0};
400 eOprotID32_t id32_applconfig_txratedivider = eoprot_ID_get(eoprot_endpoint_management, eoprot_entity_mn_appl, 0, eoprot_tag_mn_appl_config_txratedivider);
401 uint8_t txratedivider = 0;
403 std::vector<eOprotID32_t> id32s;
404 std::vector<void*> values;
406 id32s.push_back(id32_commstatus);
407 values.push_back(&value_commstatus);
409 id32s.push_back(id32_applconfig);
410 values.push_back(&value_applconfig);
412 id32s.push_back(id32_applconfig_txratedivider);
413 values.push_back(&txratedivider);
415 id32s.push_back(id32_applconfig_txratedivider);
416 values.push_back(&txratedivider);
418 id32s.push_back(id32_applconfig_txratedivider);
419 values.push_back(&txratedivider);
421 id32s.push_back(id32_applconfig_txratedivider);
422 values.push_back(&txratedivider);
424 id32s.push_back(id32_applconfig_txratedivider);
425 values.push_back(&txratedivider);
427 id32s.push_back(id32_applconfig_txratedivider);
428 values.push_back(&txratedivider);
430 id32s.push_back(id32_applconfig_txratedivider);
431 values.push_back(&txratedivider);
433 id32s.push_back(id32_applconfig_txratedivider);
434 values.push_back(&txratedivider);
438 double tprev = SystemClock::nowSystem();
439 double tcurr = SystemClock::nowSystem();
441 double delta = tcurr - tprev;
443 yDebug() <<
"before";
444 yDebug() <<
"value_commstatus.managementprotocolversion.major = " << value_commstatus.managementprotocolversion.major <<
"value_commstatus.managementprotocolversion.minor = " << value_commstatus.managementprotocolversion.minor;
445 yDebug() <<
"value_applconfig.cycletime = " << value_applconfig.cycletime <<
"value_applconfig.txratedivider" << value_applconfig.txratedivider <<
"etc";
446 yDebug() <<
"txratedivider = " << txratedivider;
448 tprev = SystemClock::nowSystem();
451 delta = SystemClock::nowSystem() - tprev;
453 yDebug() <<
"parallel mode: after" << delta <<
"seconds";
454 yDebug() <<
"value_commstatus.managementprotocolversion.major = " << value_commstatus.managementprotocolversion.major <<
"value_commstatus.managementprotocolversion.minor = " << value_commstatus.managementprotocolversion.minor;
455 yDebug() <<
"value_applconfig.cycletime = " << value_applconfig.cycletime <<
"value_applconfig.txratedivider" << value_applconfig.txratedivider <<
"etc";
456 yDebug() <<
"txratedivider = " << txratedivider;
458 memset(&value_commstatus, 0,
sizeof(value_commstatus));
459 memset(&value_applconfig, 0,
sizeof(value_applconfig));
463 tprev = SystemClock::nowSystem();
464 nvman.
ask(&transceiver, id32_commstatus, &value_commstatus, 3.0);
465 nvman.
ask(&transceiver, id32_applconfig, &value_applconfig, 3.0);
466 nvman.
ask(&transceiver, id32_applconfig_txratedivider, &txratedivider, 3.0);
467 nvman.
ask(&transceiver, id32_applconfig_txratedivider, &txratedivider, 3.0);
468 nvman.
ask(&transceiver, id32_applconfig_txratedivider, &txratedivider, 3.0);
469 nvman.
ask(&transceiver, id32_applconfig_txratedivider, &txratedivider, 3.0);
470 nvman.
ask(&transceiver, id32_applconfig_txratedivider, &txratedivider, 3.0);
471 nvman.
ask(&transceiver, id32_applconfig_txratedivider, &txratedivider, 3.0);
472 nvman.
ask(&transceiver, id32_applconfig_txratedivider, &txratedivider, 3.0);
473 nvman.
ask(&transceiver, id32_applconfig_txratedivider, &txratedivider, 3.0);
474 delta = SystemClock::nowSystem() - tprev;
476 yDebug() <<
"serial mode: after" << delta <<
"seconds";
477 yDebug() <<
"value_commstatus.managementprotocolversion.major = " << value_commstatus.managementprotocolversion.major <<
"value_commstatus.managementprotocolversion.minor = " << value_commstatus.managementprotocolversion.minor;
478 yDebug() <<
"value_applconfig.cycletime = " << value_applconfig.cycletime <<
"value_applconfig.txratedivider" << value_applconfig.txratedivider <<
"etc";
479 yDebug() <<
"txratedivider = " << txratedivider;
491 if((uint8_t)ep >= eoprot_endpoints_numberof)
493 yError() <<
"EthResource::verifyEPprotocol() called with wrong ep = " << ep <<
": cannot proceed any further";
497 if(
true == verifiedEPprotocol[ep])
502 if(
false == verifyBoard())
508 if(
false == askBoardVersion())
523 const double timeout = 0.100;
525 eOprotID32_t id2send = eo_prot_ID32dummy;
526 eOprotID32_t id2wait = eo_prot_ID32dummy;
527 eOmn_command_t command = {0};
531 id2send = eoprot_ID_get(eoprot_endpoint_management, eoprot_entity_mn_comm, 0, eoprot_tag_mn_comm_cmmnds_command_queryarray);
532 memset(&command, 0,
sizeof(command));
533 command.cmd.opc = eomn_opc_query_array_EPdes;
534 command.cmd.queryarray.opcpar.opc = eomn_opc_query_array_EPdes;
535 command.cmd.queryarray.opcpar.endpoint = eoprot_endpoint_all;
536 command.cmd.queryarray.opcpar.setnumber = 0;
537 command.cmd.queryarray.opcpar.setsize = 0;
540 id2wait = eoprot_ID_get(eoprot_endpoint_management, eoprot_entity_mn_comm, 0, eoprot_tag_mn_comm_cmmnds_command_replyarray);
544 if(
false == nvman.
command(properties.ipv4addr, id2send, &command, id2wait, &command, timeout))
551 eOmn_cmd_replyarray_t* cmdreplyarray = (eOmn_cmd_replyarray_t*)&command.cmd.replyarray;
552 EOarray* array = (EOarray*)cmdreplyarray->array;
555 uint8_t sizeofarray = eo_array_Size(array);
558 for(
int i=0; i<sizeofarray; i++)
560 eoprot_endpoint_descriptor_t *epd = (eoprot_endpoint_descriptor_t*)eo_array_At(array, i);
562 if(epd->endpoint == eoprot_endpoint_management)
564 const eoprot_version_t * pc104versionMN = eoprot_version_of_endpoint_get(eoprot_endpoint_management);
565 if(pc104versionMN->major != epd->version.major)
567 yError() <<
"EthResource::verifyEPprotocol() for ep =" << eoprot_EP2string(epd->endpoint) <<
"detected: pc104.version.major =" << pc104versionMN->major <<
"and board.version.major =" << epd->version.major;
572 if(pc104versionMN->minor != epd->version.minor)
574 yError() <<
"EthResource::verifyEPprotocol() for ep =" << eoprot_EP2string(epd->endpoint) <<
"detected: pc104.version.minor =" << pc104versionMN->minor <<
"and board.version.minor =" << epd->version.minor;
580 if(epd->endpoint == ep)
582 const eoprot_version_t * pc104versionEP = eoprot_version_of_endpoint_get(ep);
583 if(pc104versionEP->major != epd->version.major)
585 yError() <<
"EthResource::verifyEPprotocol() for ep =" << eoprot_EP2string(epd->endpoint) <<
"detected: pc104.version.major =" << pc104versionEP->major <<
"and board.version.major =" << epd->version.major;
590 if(pc104versionEP->minor != epd->version.minor)
592 yError() <<
"EthResource::verifyEPprotocol() for ep =" << eoprot_EP2string(epd->endpoint) <<
"detected: pc104.version.minor =" << pc104versionEP->minor <<
"and board.version.minor =" << epd->version.minor;
600 verifiedEPprotocol[ep] =
true;
608bool EthResource::verifyBoard(
void)
610 if((
true == verifyBoardPresence()) &&
611 (
true == verifyBoardTransceiver()) &&
612 (
true == cleanBoardBehaviour()) &&
613 (
true == setTimingOfRunningCycle()) )
622bool EthResource::verifyBoardPresence(
void)
624 if(verifiedBoardPresence)
629 const double timeout = 1.00;
630 const int retries = 20;
632 double start_time = yarp::os::Time::now();
635 verifiedBoardPresence = nvman.
ping(properties.ipv4addr, boardMNprotocolversion, timeout, retries);
637 double end_time = yarp::os::Time::now();
639 if(
true == verifiedBoardPresence)
641 verifiedBoardPresence =
true;
652 return(verifiedBoardPresence);
656bool EthResource::askBoardVersion(
void)
659 if(askedBoardVersion)
664 const double timeout = 0.500;
666 eOprotID32_t id32 = eoprot_ID_get(eoprot_endpoint_management, eoprot_entity_mn_appl, 0, eoprot_tag_mn_appl_status);
667 eOmn_appl_status_t applstatus = {0};
671 askedBoardVersion = nvman.
ask(properties.ipv4addr, id32, &applstatus, timeout);
673 if(
false == askedBoardVersion)
682 properties.firmwareversion.major = applstatus.version.major;
683 properties.firmwareversion.minor = applstatus.version.minor;
686 properties.firmwaredate.year = applstatus.buildate.year;
687 properties.firmwaredate.month = applstatus.buildate.month;
688 properties.firmwaredate.day = applstatus.buildate.day;
689 properties.firmwaredate.hour = applstatus.buildate.hour;
690 properties.firmwaredate.min = applstatus.buildate.min;
692 char versstr[32] = {0};
693 snprintf(versstr,
sizeof(versstr),
"ver %d.%d built on ", properties.firmwareversion.major, properties.firmwareversion.minor);
694 char datestr[32] = {0};
695 eo_common_date_to_string(properties.firmwaredate, datestr,
sizeof(datestr));
697 properties.firmwareString = string(versstr) + string(datestr);
700 if(eobool_true == eoboards_is_eth((eObrd_type_t)applstatus.boardtype))
702 detectedBoardType = (eObrd_ethtype_t) applstatus.boardtype;
706 detectedBoardType = eobrd_ethtype_unknown;
709 if(detectedBoardType != properties.boardtype)
711 yWarning() <<
"EthResource::askBoardVersion(): detected wrong board. expecting" << properties.boardtypeString <<
"and detected" << eoboards_type2string2(eoboards_ethtype2type(detectedBoardType), eobool_true);
715 yInfo() <<
"EthResource::askBoardVersion() found BOARD" << properties.boardnameString <<
"@ IP" << properties.ipv4addrString <<
"of type" << properties.boardtypeString<<
"with FW =" << properties.firmwareString;
718 return(askedBoardVersion);
724 bool replied =
false;
726 double start_time = yarp::os::Time::now();
730 for(
unsigned int numOfattempts=0; numOfattempts<(retries+1); numOfattempts++)
732 if(
true == nvman.
ask(&transceiver, id32, value, timeout))
746 double end_time = yarp::os::Time::now();
761 double start_time = yarp::os::Time::now();
763 bool replied = nvman.
ask(&transceiver, id32s, values, timeout);
765 double end_time = yarp::os::Time::now();
779 return nvman.
set(properties.ipv4addr, id32, value);
785 return nvman.
setcheck(properties.ipv4addr, id32, value, retries, waitbeforecheck, timeout);
791 char canfullmessage[128];
793 static const char * sourcestrings[] =
800 int source = EOMN_INFO_PROPERTIES_FLAGS_get_source(infobasic->properties.flags);
801 const char * str_source = (source > eomn_info_source_can2) ? (sourcestrings[3]) : (sourcestrings[source]);
802 uint16_t address = EOMN_INFO_PROPERTIES_FLAGS_get_address(infobasic->properties.flags);
803 uint8_t *p64 = (uint8_t*)&(infobasic->properties.par64);
805 int msg_id = (p64[1]&0xF0) >> 4;
807 uint32_t sec = infobasic->timestamp / 1000000;
808 uint32_t msec = (infobasic->timestamp % 1000000) / 1000;
809 uint32_t usec = infobasic->timestamp % 1000;
811 const char *boardstr = properties.boardnameString.c_str();
816 snprintf(canfullmessage,
sizeof(canfullmessage),
"Error while parsing the message: CAN address detected is out of allowed range");
817 snprintf(str,
sizeof(str),
"from BOARD %s (%s), src %s, adr %d, time %ds %dm %du: CAN PRINT MESSAGE[id %d] -> %s",
818 properties.ipv4addrString.c_str(),
833 if (c_string_handler[address] == NULL)
837 can_msg.
setCanData(infobasic->properties.par64);
838 can_msg.
setId(msg_id);
839 can_msg.
setSize(infobasic->properties.par16);
840 int ret = c_string_handler[address]->add_string(&can_msg);
845 char* themsg = c_string_handler[address]->get_string(ret);
846 memcpy(canfullmessage, themsg,
sizeof(canfullmessage));
847 canfullmessage[63] = 0;
848 c_string_handler[address]->clear_string(ret);
850 snprintf(str,
sizeof(str),
"from BOARD %s (%s), src %s, adr %d, time %ds %dm %du: CAN PRINT MESSAGE[id %d] -> %s",
851 properties.ipv4addrString.c_str(),
868bool EthResource::serviceCommand(eOmn_serv_operation_t operation, eOmn_serv_category_t category,
const eOmn_serv_parameter_t* param,
double timeout,
int times)
870 eOprotID32_t id2send = eoprot_ID_get(eoprot_endpoint_management, eoprot_entity_mn_service, 0, eoprot_tag_mn_service_cmmnds_command);
871 eOprotID32_t id2wait = eoprot_ID_get(eoprot_endpoint_management, eoprot_entity_mn_service, 0, eoprot_tag_mn_service_status_commandresult);
873 eOmn_service_cmmnds_command_t command = {0};
874 eOmn_service_command_result_t result = {0};
876 command.operation = operation;
877 command.category = category;
880 memcpy(&command.parameter, param,
sizeof(eOmn_serv_parameter_t));
884 memset(&command.parameter, 0,
sizeof(eOmn_serv_parameter_t));
885 if((eomn_serv_operation_regsig_load == operation) || ((eomn_serv_operation_regsig_clear == operation)))
887 eo_array_New(eOmn_serv_capacity_arrayof_id32, 4, &command.parameter.arrayofid32);
891 command.parameter.configuration.type = eomn_serv_NONE;
898 bool replied =
false;
899 for(
int i=0; i<times; i++)
901 if(
true == nvman.
command(properties.ipv4addr, id2send, &command, id2wait, &result, timeout))
916 return(result.latestcommandisok);
922 eOmn_serv_parameter_t prepared {};
925 yError() <<
"EthResource::serviceVerifyActivate(): MC requires"
929 const auto* request = param ? &prepared :
nullptr;
930 const bool result = serviceCommand(eomn_serv_operation_verifyactivate, category, request, timeout, 3);
941 eOmn_serv_parameter_t param = {0};
942 EOarray *array = eo_array_New(eOmn_serv_capacity_arrayof_id32, 4, ¶m.arrayofid32);
943 for(
int i=0; i<id32vector.size(); i++)
945 eOprotID32_t id32 = id32vector.at(i);
946 eo_array_PushBack(array, &id32);
949 regularsAreSet = serviceCommand(eomn_serv_operation_regsig_load, category, ¶m, timeout, 3);
951 return regularsAreSet;
958 bool ret = serviceCommand(eomn_serv_operation_start, category, NULL, timeout, 3);
962 isInRunningMode =
true;
971 bool ret = serviceCommand(eomn_serv_operation_stop, category, NULL, timeout, 3);
978 if(ret && (category == eomn_serv_category_all))
980 regularsAreSet =
false;
992 return transceiver.read(id32,
data);
998 return transceiver.write(id32, value, overrideROprotection);
1009 return &transceiver;
void setSize(uint8_t size)
void setCanData(uint64_t data)
POSServiceConfiguration posServiceConfiguration
bool getRemoteValues(const std::vector< eOprotID32_t > &id32s, const std::vector< void * > &values, const double timeout=0.500)
const void * getUDPtransmit(eOipv4addressing_t &destination, size_t &sizeofpacket, uint16_t &numofrops)
bool processRXpacket(const void *data, size_t size)
HostTransceiver * getTransceiver()
bool getLocalValue(const eOprotID32_t id32, void *value)
bool serviceSetRegulars(eOmn_serv_category_t category, vector< eOprotID32_t > &id32vector, double timeout=0.500)
bool open2(eOipv4addr_t remIP, yarp::os::Searchable &cfgtotal)
bool serviceStop(eOmn_serv_category_t category, double timeout=0.500)
bool verifyEPprotocol(eOprot_endpoint_t ep)
bool getRemoteValue(const eOprotID32_t id32, void *value, const double timeout=0.100, const unsigned int retries=0)
bool setLocalValue(eOprotID32_t id32, const void *value, bool overrideROprotection=false)
bool setRemoteValue(const eOprotID32_t id32, void *value)
bool setcheckRemoteValue(const eOprotID32_t id32, void *value, const unsigned int retries=10, const double waitbeforecheck=0.001, const double timeout=0.050)
bool serviceVerifyActivate(eOmn_serv_category_t category, const eOmn_serv_parameter_t *param, double timeout=0.500)
const Properties & getProperties()
bool serviceStart(eOmn_serv_category_t category, double timeout=0.500)
bool CANPrintHandler(eOmn_info_basic_t *infobasic)
static TheEthManager * instance()
static theNVmanager & getInstance()
bool setcheck(const eOprotIP_t ipv4, const eOprotID32_t id32, const void *value, const unsigned int retries=10, double waitbeforecheck=0.001, double timeout=0.5)
bool ask(const eOprotIP_t ipv4, const eOprotID32_t id32, void *value, const double timeout=0.5)
bool command(const eOprotIP_t ipv4, const eOprotID32_t id32cmd, const void *cmd, const eOprotID32_t id32rep, void *rep, double timeout=0.5)
bool ping(const eOprotIP_t ipv4, eoprot_version_t &mnprotversion, const double timeout=0.5, const unsigned int retries=20)
bool set(const eOprotIP_t ipv4, const eOprotID32_t id32, const void *value)
void feat_PrintInfo(char *string)
void feat_PrintError(char *string)
bool read(yarp::os::Searchable &cfgtotal, pc104Data &pc104data)
bool print(const pc104Data &pc104data)
double periodmissingreport
double monitorpresence_periodofmissingreport
bool monitorpresence_enabled
double monitorpresence_timeout
boardProperties properties
eOipv4addressing_t ipv4addressing
std::string ipv4addressingstring
eOmn_appl_config_t txconfig