DESERT 3.6.0
Loading...
Searching...
No Matches
uwevologicss2cmodem.cpp
Go to the documentation of this file.
1//
2// Copyright (c) 2019 Regents of the SIGNET lab, University of Padova.
3// All rights reserved.
4//
5// Redistribution and use in source and binary forms, with or without
6// modification, are permitted provided that the following conditions
7// are met:
8// 1. Redistributions of source code must retain the above copyright
9// notice, this list of conditions and the following disclaimer.
10// 2. Redistributions in binary form must reproduce the above copyright
11// notice, this list of conditions and the following disclaimer in the
12// documentation and/or other materials provided with the distribution.
13// 3. Neither the name of the University of Padova (SIGNET lab) nor the
14// names of its contributors may be used to endorse or promote products
15// derived from this software without specific prior written permission.
16//
17// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
19// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
20// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
21// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
22// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
23// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
24// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
25// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
26// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
27// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28
29#include "phymac-clmsg.h"
30#include <clmessage.h>
31#include <hdr-uwal.h>
32#include <ms2c_ClMessage.h>
33#include <uwal.h>
34#include <uwevologicss2cmodem.h>
35#include <uwphy-clmsg.h>
36#include <uwsocket.h>
37#include <uwserial.h>
38
39#include <cstring>
40#include <iostream>
41#include <iterator>
42#include <string>
43#include <ostream>
44
45const std::chrono::milliseconds UwEvoLogicsS2CModem::MODEM_TIMEOUT =
46 std::chrono::milliseconds(210);
47
48const std::chrono::seconds UwEvoLogicsS2CModem::WAIT_DELIVERY_BURST =
49 std::chrono::seconds(5);
50
51const std::chrono::milliseconds UwEvoLogicsS2CModem::WAIT_DELIVERY_IM =
52 std::chrono::milliseconds(1000);
53
55
60static class UwEvoLogicsS2C_TclClass : public TclClass
61{
62
63public:
65 : TclClass("Module/UW/UwModem/EvoLogicsS2C")
66 {
67 }
68
69 TclObject *
70 create(int args, const char *const *argv)
71 {
72 return (new UwEvoLogicsS2CModem());
73 }
74
76
78 : UwModem()
79 , p_connector(new UwSocket())
80 , p_interpreter(new UwInterpreterS2C())
81 , status(ModemState::AVAILABLE)
82 , tx_status(TransmissionState::TX_IDLE)
83 , status_m()
84 , tx_status_m()
85 , tx_queue_m()
86 , status_cv()
87 , tx_status_cv()
88 , tx_queue_cv()
89 , receiving(false)
90 , transmitting(false)
91 , im_status_updated(false)
92 , rx_thread()
93 , tx_thread()
94 , tx_mode(TransmissionMode::IM)
95 , ack_mode(false)
96 , curr_source_level(3)
97 , n_rx_failed(0)
98 , pend_source_level(3)
99 , source_level_change(false)
100 , size2dur_()
101 , txdur_file_name_("")
102 , txdur_token_separator_(';')
103 , initLUT_(false)
104
105{
106 bind("buffer_size", (int *) &DATA_BUFFER_LEN);
107 bind("max_read_size", (int *) &MAX_READ_BYTES);
108 bind("max_n_status_queries",
110}
111
116
117void
119{
120 // push new incoming pck into tx_queue
121 hdr_cmn *ch = HDR_CMN(p);
122 hdr_MPhy *ph = HDR_MPHY(p);
123 if (ch->direction() == hdr_cmn::UP) {
124 if (isOn == true) {
125 startRx(p);
126 endRx(p);
127 } else {
128 Packet::free(p);
129 }
130 } else { // DOWN
131 if (!isOn) {
132 return;
133 }
134 ph->Pr = 0;
135 ph->Pn = 0;
136 ph->Pi = 0;
137 ph->txtime = NOW;
138 ph->rxtime = ph->txtime;
139
140 ph->worth_tracing = false;
141
142 ph->srcSpectralMask = getTxSpectralMask(p);
143 ph->srcAntenna = getTxAntenna(p);
144 ph->srcPosition = getPosition();
145 ph->dstSpectralMask = 0;
146 ph->dstPosition = 0;
147 ph->dstAntenna = 0;
148 ph->modulationType = getModulationType(p);
149 ph->duration = getTxDuration(p);
150
151 std::unique_lock<std::mutex> tx_lock(tx_queue_m);
152 tx_queue.push(p);
153 tx_lock.unlock();
155 "EVOLOGICSS2CMODEM",
156 "recv::PUSHING_IN_TX_QUEUE");
157 tx_queue_cv.notify_one();
158 }
159}
160
161int
162UwEvoLogicsS2CModem::command(int argc, const char *const *argv)
163{
164 // Tcl &tcl = Tcl::instance();
165
166 if (argc == 2) {
167 if (!strcmp(argv[1], "start")) {
168 start();
169 return TCL_OK;
170 }
171 if (!strcmp(argv[1], "stop")) {
172 stop();
173 return TCL_OK;
174 }
175 if (!strcmp(argv[1], "setBurstMode")) {
177 return TCL_OK;
178 }
179 if (!strcmp(argv[1], "setIMMode")) {
181 return TCL_OK;
182 }
183 if (!strcmp(argv[1], "enableIMAck")) {
184 ack_mode = true;
185 return TCL_OK;
186 }
187 if (!strcmp(argv[1], "disableIMAck")) {
188 ack_mode = false;
189 return TCL_OK;
190 }
191 if (!strcmp(argv[1], "enableExtProtoMode")) {
192 p_interpreter->setExtProtoMode(true);
193 return TCL_OK;
194 }
195 if (!strcmp(argv[1], "disableExtProtoMode")) {
196 p_interpreter->setExtProtoMode(false);
197 return TCL_OK;
198 }
199 if (!strcmp(argv[1], "initLUT")) {
201 return TCL_OK;
202 }
203 } else if (argc == 3) {
204 if (!strcmp(argv[1], "setConnector")) {
205 if(!strcmp(argv[2], "SOCKET")) {
206 p_connector.reset(new UwSocket());
207 return TCL_OK;
208 }
209 if(!strcmp(argv[2], "SERIAL")) {
210 p_connector.reset(new UwSerial());
211 return TCL_OK;
212 }
213 fprintf(stderr, "Invalid connector type, choose between SOCKET and SERIAL");
214 return TCL_ERROR;
215 }
216 if (!strcmp(argv[1], "setSourceLevel")) {
217 std::stringstream sl_ss(argv[2]);
218 int sl_;
219 if (sl_ss >> sl_)
220 return TCL_OK;
221 else
222 return TCL_ERROR;
223 }
224 if (!strcmp(argv[1], "setTXDurationFileName")) {
225 std::string tmp_ = ((char *) argv[2]);
226 if (tmp_.size() == 0) {
227 fprintf(stderr, "Empty string for the file name");
228 return TCL_ERROR;
229 }
230 txdur_file_name_ = tmp_;
231 return TCL_OK;
232 }
233 if (!strcmp(argv[1], "setLUTSeparator")) {
234 string tmp_ = ((char *) argv[2]);
235 if (tmp_.size() == 0) {
236 fprintf(stderr, "Empty char for the file separator");
237 return TCL_ERROR;
238 }
239 txdur_token_separator_ = tmp_.at(0);
240 return TCL_OK;
241 }
242 }
243
244 return UwModem::command(argc, argv);
245}
246
247void
249{
250 ifstream input_file_;
251 string line_;
252
253 input_file_.open(txdur_file_name_.c_str());
254
255 if (input_file_.is_open()) {
256 while (std::getline(input_file_, line_)) {
257 if (line_[0] == '#')
258 continue;
259
260 std::istringstream line_stream(line_);
261 std::string token;
262
263 std::getline(line_stream, token, txdur_token_separator_);
264 int size = std::atoi(token.c_str());
265 if (size < 1) {
267 "EVOLOGICSS2CMODEM",
268 "initializeLUT::INVALID_PKT_SIZE " + token);
269 continue;
270 }
271
272 std::getline(line_stream, token, txdur_token_separator_);
273 double duration = 0;
274 char *end {};
275 if (token.length() > 0) {
276 duration = std::strtod(token.c_str(), &end);
277
278 if (!(duration > 0))
280 "EVOLOGICSS2CMODEM",
281 "initializeLUT::INVALID_DURATION_FOR_PKT_SIZE "
282 + std::to_string(size));
283 }
284
285 std::getline(line_stream, token, txdur_token_separator_);
286 double proc_delay = 0;
287 if (token.length() > 0) {
288 proc_delay = std::strtod(token.c_str(), &end);
289 duration += proc_delay;
290
291 if (!(proc_delay > 0))
293 "EVOLOGICSS2CMODEM",
294 "initializeLUT::INVALID_PROC_DELAY_FOR_PKT_SIZE "
295 + std::to_string(size));
296 }
297
298 size2dur_[size] = duration;
299 }
300
301 initLUT_ = true;
302 } else {
304 "EVOLOGICSS2CMODEM",
305 "initializeLUT::FAIL_TO_READ_FROM_FILE " + txdur_file_name_);
306 }
307}
308
309int
311{
312 if (m->type() == CLMSG_S2C_POWER_LEVEL) {
313 ClMsgS2CPowerLevel *msg = static_cast<ClMsgS2CPowerLevel *>(m);
314 if (msg->getReqType() == ClMsgUwPhy::SET_REQ) {
316 "UWEVOLOGICSS2CMODEM",
317 "RECEIVED_CLMSG_FOR_POWER_CHANGE");
319 source_level_change = true;
321 return 0;
322 } else if (msg->getReqType() == ClMsgUwPhy::GET_REQ) {
325 return 0;
326 }
327 } else if (m->type() == CLMSG_S2C_TX_MODE) {
328 ClMsgS2CTxMode *msg = static_cast<ClMsgS2CTxMode *>(m);
329 if (msg->getReqType() == ClMsgUwPhy::SET_REQ) {
332 } else {
334 }
336 return 0;
337 } else if (msg->getReqType() == ClMsgUwPhy::GET_REQ) {
340 } else {
342 }
344 return 0;
345 }
346 } else if (m->type() == CLMSG_S2C_RX_FAILED) {
347 ClMsgS2CRxFailed *msg = static_cast<ClMsgS2CRxFailed *>(m);
348 if (msg->getReqType() == ClMsgUwPhy::GET_REQ) {
351 return 0;
352 } else {
353 return 1;
354 }
355 } else if (m->type() == CLMSG_MAC2PHY_GETTXDURATION) {
356 Packet *p = ((ClMsgMac2PhyGetTxDuration *) m)->pkt;
357 hdr_cmn *ch = HDR_CMN(p);
358
359 if (ch->direction() == hdr_cmn::DOWN) {
360 double duration = getTxDuration(p);
361
362 if (duration > 0)
364 "EVOLOGICSS2CMODEM",
365 "recvSyncClMsg::SET_TXDURATION " +
366 std::to_string(duration));
367
368 ((ClMsgMac2PhyGetTxDuration *) m)->setDuration(duration);
369
370 return 0;
371 }
372
373 // Don't set TX duration on RX.
374 ((ClMsgMac2PhyGetTxDuration *) m)->setDuration(-1);
375
376 return 1;
377 }
378
379 return MPhy::recvSyncClMsg(m);
380}
381
382double
384{
385 hdr_uwal *uwalh = HDR_UWAL(p);
386 double tx_duration = -1;
387
388 if (initLUT_)
389 tx_duration = size2dur_[uwalh->binPktLength()];
390 else
392 "EVOLOGICSS2CMODEM",
393 "getTxDuration::FAIL_TO_GET_TXDURATION");
394
395 return tx_duration;
396}
397
398bool
400{
401 std::string config_cmd{""};
402
403 switch (cmd) {
404 case Config::ATL_GET: {
405 std::string command = p_interpreter->buildGetATL();
406 break;
407 }
408 case Config::ATL_SET: {
409 std::string command = p_interpreter->buildSetATL(pend_source_level);
410 break;
411 }
412 case Config::ATAL_GET: {
413 std::string command = p_interpreter->buildGetATAL();
414 break;
415 }
416 case Config::ATAL_SET: {
417 std::string command = p_interpreter->buildSetATAL(modemID);
418 break;
419 }
421 std::string command = p_interpreter->buildATS();
422 break;
423 }
425 std::string command = p_interpreter->buildATV();
426 break;
427 }
428 default:
429 return false;
430 }
431
432 std::unique_lock<std::mutex> state_lock(status_m);
433
434 if (status_cv.wait_for(state_lock, MODEM_TIMEOUT, [&] {
435 return status == ModemState::AVAILABLE;
436 })) {
437
439
440 std::lock_guard<std::mutex> tx_state_lock(tx_status_m);
441
442 if (!p_connector->writeToDevice(config_cmd)) {
444 "EVOLOGICSS2CMODEM",
445 "configure::FAIL_TO_WRITE_TO_DEVICE=" + config_cmd);
446 return false;
447 }
448
449 state_lock.unlock();
451
452 } else {
453
454 return false;
455 }
456
457 return true;
458}
459
460void
462{
463 // this method does nothing in ns, so it can be called from an
464 // external thread
465 // save MAC and AL headers and write payload
466 hdr_mac *mach = HDR_MAC(p);
467 hdr_uwal *uwalh = HDR_UWAL(p);
468 std::string payload;
469 payload.assign(uwalh->binPkt(), uwalh->binPktLength());
470
471 // build command to perform a SEND or SENDIM
472 std::string cmd_s;
474 cmd_s = p_interpreter->buildSendIM(payload, mach->macDA(), ack_mode);
475 } else {
476 cmd_s = p_interpreter->buildSend(payload, mach->macDA());
477 }
478
480 "EVOLOGICSS2CMODEM",
481 "startTx::COMMAND_TX::" + cmd_s);
482
483 // write the obtained command to the device, through the connector
484 std::unique_lock<std::mutex> state_lock(status_m);
485 if (status_cv.wait_for(state_lock, MODEM_TIMEOUT, [&] {
486 return status == ModemState::AVAILABLE;
487 })) {
488
490
491 std::unique_lock<std::mutex> tx_state_lock(tx_status_m);
492
493 if ((p_connector->writeToDevice(cmd_s)) < 0) {
495 "EVOLOGICSS2CMODEM",
496 "startTx::FAIL_TO_WRITE_TO_DEVICE=" + cmd_s);
497 return;
498 }
499
501 status_cv.wait_for(state_lock, MODEM_TIMEOUT, [&] {
503 });
504 state_lock.unlock();
505
507
508 size_t status_polling_counter = 0;
509 im_status_updated.store(false);
510 while (status_polling_counter < MAX_N_STATUS_QUERIES &&
512
513 cmd_s = p_interpreter->buildATDI();
514
516 "EVOLOGICSS2CMODEM",
517 "startTx::SENDING=" + cmd_s);
518
519 if ((p_connector->writeToDevice(cmd_s)) < 0) {
521 "EVOLOGICSS2CMODEM",
522 "startTx::FAIL_TO_WRITE_TO_DEVICE=" + cmd_s);
523 }
524
525 tx_status_cv.wait_for(tx_state_lock, WAIT_DELIVERY_IM, [&] {
527 });
528
531 "EVOLOGICSS2CMODEM",
532 "startTx::TX_IDLE");
533 break;
534 } else {
535 im_status_updated.store(false);
537 "EVOLOGICSS2CMODEM",
538 "startTx::TX_PENDING");
539 }
540
541 status_polling_counter++;
542 }
543
544 // In case the attempts reached MAX_N_STATUS_QUERIES, force
545 // tx_status
546 if (status_polling_counter == MAX_N_STATUS_QUERIES &&
549 "EVOLOGICSS2CMODEM",
550 "startTx::MAX_N_STATUS_QUERIES_REACHED");
551 }
552
553 } else { // tx_mode == TransmissionMode::BURST
554 tx_status_cv.wait_for(tx_state_lock, WAIT_DELIVERY_BURST, [&] {
556 });
557 }
558
559 std::function<void(UwModem &, Packet * p)> callback =
561 ModemEvent e = {callback, p};
562 event_q.push(e);
563
564 } else {
566 "EVOLOGICSS2CMODEM",
567 "startTx::TIMEOUT_EXPIRED::FORCING_MODEM_AVAILABILITY");
569 }
570}
571
572void
574{
576 "EVOLOGICSS2CMODEM",
577 "startRx::CALL_PHY2MACSTARTRX");
578 Phy2MacStartRx(p);
579}
580
581void
583{
584 printOnLog(LogLevel::INFO, "EVOLOGICSS3CMODEM", "endRx::CALL_SENDUP");
585 sendUp(p, 0.01);
586}
587
588void
590{
591 if (modem_address == "") {
592 std::cout << "ERROR: Modem address not set!" << std::endl;
594 LogLevel::ERROR, "EVOLOGICSS2CMODEM", "start::ADDRESS_NOT_SET");
595 return;
596 }
597
598 if (!p_connector->openConnection(modem_address)) {
599 std::cout << "ERROR: connection to modem failed to open: "
600 << modem_address << std::endl;
602 "EVOLOGICSS2CMODEM",
603 "start::CONNECTION_OPEN_FAILED");
604 return;
605 }
606
607 // set flags to true so loops can start
608 receiving.store(true);
609 transmitting.store(true);
610
611 // branch off threads
612 rx_thread = std::thread(&UwEvoLogicsS2CModem::receivingData, this);
613
615
616 checkTimer = new CheckTimer(this);
617 checkTimer->resched(period);
618}
619
620void
622{
623
624 std::cout << "UwEvoLogicsS2CModem::stop() close conn " << std::endl;
625 printOnLog(LogLevel::INFO, "EVOLOGICSS2CMODEM", "stop::CLOSING_CONNECTION");
626
627 receiving.store(false);
628 transmitting.store(false);
629 tx_queue_cv.notify_one();
630 if (tx_thread.joinable())
631 tx_thread.join();
632 if (p_connector->isConnected() && !p_connector->closeConnection()) {
634 "EVOLOGICSS2CMODEM",
635 "stop::CONNECTION_CLOSE_FAIL");
636 }
637 if (rx_thread.joinable()) {
638 rx_thread.join();
639 }
640
641 checkTimer->force_cancel();
642}
643
644void
646{
647 while (transmitting.load()) {
648
649 std::unique_lock<std::mutex> tx_lock(tx_queue_m);
650 tx_queue_cv.wait(
651 tx_lock, [&] { return !tx_queue.empty() || !transmitting; });
652 if (!transmitting) {
653 break;
654 }
655
656 Packet *pck = tx_queue.front();
657 tx_queue.pop();
658 tx_lock.unlock();
659 if (pck) {
660 startTx(pck);
661 }
662
664 "EVOLOGICSS2CMODEM",
665 "transmittingData::BLOCKING_ON_NEXT_PACKET");
666 }
667}
668
669void
671{
673 std::fill(data_buffer.begin(), data_buffer.end(), '\0');
674 // iterators that keep track of read/write operations
675 std::vector<char>::iterator beg_it = data_buffer.begin();
676 std::vector<char>::iterator end_it = data_buffer.begin();
677 // iterators that keep track of commands research
678 std::vector<char>::iterator cmd_b = data_buffer.begin();
679 std::vector<char>::iterator cmd_e = data_buffer.begin();
681 int r_bytes = 0;
682 int offset = 0;
683
684 while (receiving.load()) {
685
686 r_bytes = p_connector->readFromDevice(
687 &(*beg_it) + offset, MAX_READ_BYTES - r_bytes);
688
689 end_it = beg_it + r_bytes + offset;
690
691 while (receiving.load() && r_bytes > 0 &&
692 (cmd = p_interpreter->findResponse(beg_it, end_it, cmd_b)) !=
694
695 while (receiving.load() &&
696 !p_interpreter->parseResponse(
697 cmd, end_it, cmd_b, cmd_e, rx_payload)) {
698
699 int new_r_bytes = p_connector->readFromDevice(
700 &(*end_it), MAX_READ_BYTES - r_bytes);
701
702 r_bytes += new_r_bytes;
703 end_it = beg_it + r_bytes;
704 }
705
707 "EVOLOGICSS2CMODEM",
708 "receivingData::RX_MSG=" + std::string(cmd_b, cmd_e));
709
710 updateStatus(cmd);
711 std::fill(cmd_b, cmd_e, '\0');
712 cmd_b = cmd_e + 1;
713 }
714
715 // check if bytes are left after parsing and move them to beginning
716 if ((int) (cmd_e - beg_it) < r_bytes) {
717 offset = r_bytes - (int) (cmd_e - beg_it);
718 std::copy(cmd_e, cmd_e + offset, data_buffer.begin());
719 } else {
720 offset = 0;
721 }
722 }
723}
724
725void
727{
728 std::unique_lock<std::mutex> state_lock(status_m);
729 switch (cmd) {
730
732
734 status_cv.notify_all();
735 state_lock.unlock();
736
737 Packet *p = Packet::alloc();
739 std::function<void(UwModem &, Packet * p)> callback =
741 ModemEvent e = {callback, p};
742 event_q.push(e);
743 break;
744 }
747 status_cv.notify_all();
748 state_lock.unlock();
749
750 Packet *p = Packet::alloc();
752 std::function<void(UwModem &, Packet * p)> callback =
754 ModemEvent e = {callback, p};
755 event_q.push(e);
756 break;
757 }
760 state_lock.unlock();
761 status_cv.notify_all();
762 break;
763 }
766 state_lock.unlock();
767 status_cv.notify_all();
768 std::unique_lock<std::mutex> tx_state_lock(tx_status_m);
770 im_status_updated.store(true);
771 tx_status_cv.notify_all();
772 break;
773 }
776 state_lock.unlock();
777 status_cv.notify_all();
778 break;
779 }
781 std::unique_lock<std::mutex> tx_state_lock(tx_status_m);
783 im_status_updated.store(true);
784 tx_status_cv.notify_all();
785 status_cv.notify_all();
786 break;
787 }
790 state_lock.unlock();
791 status_cv.notify_all();
792 std::unique_lock<std::mutex> tx_state_lock(tx_status_m);
794 im_status_updated.store(true);
795 tx_status_cv.notify_all();
796 break;
797 }
800 state_lock.unlock();
801 status_cv.notify_all();
802 std::unique_lock<std::mutex> tx_state_lock(tx_status_m);
804 tx_status_cv.notify_all();
805 break;
806 }
809 state_lock.unlock();
810 status_cv.notify_all();
811 break;
812 }
815 status_cv.notify_all();
816 break;
817 }
820 state_lock.unlock();
821 status_cv.notify_all();
822 std::unique_lock<std::mutex> tx_state_lock(tx_status_m);
824 im_status_updated.store(true);
825 tx_status_cv.notify_all();
826 break;
827 }
830 state_lock.unlock();
831 status_cv.notify_all();
832 std::unique_lock<std::mutex> tx_state_lock(tx_status_m);
834 im_status_updated.store(true);
835 tx_status_cv.notify_all();
836 break;
837 }
840 status_cv.notify_all();
841 break;
842 }
845 status_cv.notify_all();
846 break;
847 }
850 status_cv.notify_all();
851 break;
852 }
855 status_cv.notify_all();
856 break;
857 }
860 status_cv.notify_all();
861 break;
862 }
865 state_lock.unlock();
866 status_cv.notify_all();
867 std::unique_lock<std::mutex> tx_state_lock(tx_status_m);
869 im_status_updated.store(true);
870 tx_status_cv.notify_all();
871 break;
872 }
875 status_cv.notify_all();
876 break;
877 }
880 status_cv.notify_all();
881 break;
882 }
885 status_cv.notify_all();
886 break;
887 }
890 status_cv.notify_all();
891 break;
892 }
895 status_cv.notify_all();
896 break;
897 }
899 n_rx_failed++;
901 "EVOLOGICSS2CMODEM",
902 "updateStatus::FAILED_RX");
904 status_cv.notify_all();
905 break;
906 }
909 status_cv.notify_all();
910 break;
911 }
914 state_lock.unlock();
915 status_cv.notify_all();
916 std::unique_lock<std::mutex> tx_state_lock(tx_status_m);
918 im_status_updated.store(true);
919 tx_status_cv.notify_all();
920 break;
921 }
924 status_cv.notify_all();
925 break;
926 }
929 status_cv.notify_all();
930 break;
931 }
934 std::shared_ptr<USBLInfo> pos = p_interpreter->getUSBLInfo();
935
936 std::string log_msg = "updateStatus::USBLLONG::curr_time=" +
937 std::to_string(pos->curr_time) +
938 ",meas_time=" + std::to_string(pos->meas_time) +
939 ",remote_address=" + std::to_string(pos->r_address) +
940 ",X=" + std::to_string(pos->X) +
941 ",Y=" + std::to_string(pos->Y) +
942 ",Z=" + std::to_string(pos->Z) +
943 ",E=" + std::to_string(pos->E) +
944 ",N=" + std::to_string(pos->N) +
945 ",U=" + std::to_string(pos->U) +
946 ",accuracy=" + std::to_string(pos->accuracy);
947 printOnLog(LogLevel::INFO, "EVOLOGICSS2CMODEM", log_msg);
948
949 status_cv.notify_all();
950 break;
951 }
954 status_cv.notify_all();
955 break;
956 }
957 default: {
959 status_cv.notify_all();
960 }
961 }
962
963 printOnLog(LogLevel::DEBUG, "EVOLOGICSS2CMODEM", "updateStatus::END");
964}
965
966void
968{
969 hdr_cmn *ch = HDR_CMN(p);
970 ch->error_ = 1;
971}
972
973void
975{
976 hdr_uwal *uwalh = HDR_UWAL(p);
977 uwalh->binPktLength() = rx_payload.size();
978 std::memset(uwalh->binPkt(), 0, uwalh->binPktLength());
979 std::copy(rx_payload.begin(), rx_payload.end(), uwalh->binPkt());
980 HDR_CMN(p)->direction() = hdr_cmn::UP;
981}
Class representing the message for changing or retrieving the power level (source level)
void set_power_level(int level)
Set the poer level in the selected Cl message.
int get_power_level() const
Retrieve the power level specified in the Cl message.
Class representing the Cl message type used for retrieving the failed receptions counter of S2C devic...
void set_n_rx_failed(int n_failed)
Method used to set the number of reception failures in the message.
Cl Message type for setting the Tx Mode: Instant Message, Burst or Piggyback.
tx_mode_t get_tx_mode() const
Method used to retrieve the TX mode value in the message.
void set_tx_mode(tx_mode_t mode)
Method that sets the TX mode in the message to the specified value.
void setReqType(ReqType type)
method to set the request type
ReqType getReqType()
method to return the request type
std::mutex status_m
Mutex associated with the state machine of the modem.
int n_rx_failed
Number of failed receptions up to now.
static uint MAX_N_STATUS_QUERIES
Maximum number of time to query the modem transmission status before to discard the transmitted packe...
bool initLUT_
Flag that tells whether the TX duration LUT is loaded or not.
TransmissionMode tx_mode
Either burst or im.
TransmissionState tx_status
Variable holding the current transmission status of the modem.
void setFailedTx(Packet *p)
Method that allows to set the error flag on the packet to notify upper layers about un-tranmsitted pa...
virtual void recv(Packet *p)
Method that handles the reception of packets arriving from upper layers of the network simulator.
std::atomic< bool > transmitting
Atomic boolean variable that controls the transmitting looping thread.
std::condition_variable status_cv
Condition variable to wait for ModemState::AVAILABLE.
std::atomic< bool > im_status_updated
Atomic boolean variable controlling if the modem had responded to ATDI.
int pend_source_level
Pending source level, requested but not set.
std::condition_variable tx_status_cv
Condition variable to wait for TransmissionState::TX_IDLE.
void updateStatus(UwInterpreterS2C::Response cmd)
Method that updates the status of the modem State Machine: state change is triggered by reception of ...
void createRxPacket(Packet *p)
Method that fills up a packet with the needed header and payload and makes it ready to be sent to the...
std::thread rx_thread
Object with the rx thread.
UwEvoLogicsS2CModem()
Constructor of the UwEvoLogicsS2CModem class.
std::mutex tx_queue_m
Mutex associated with the transmission queue.
virtual void transmittingData()
Method that detach a thread devoted to sending packets found in tx_queue.
virtual void initializeLUT()
Method that loads the TX LUT into a map.
static const std::chrono::seconds WAIT_DELIVERY_BURST
Time interval tu wait for a burst message tobe confirmed through a DELIVERED response.
bool source_level_change
Flag that tells a new SL value to be applied.
virtual void stop()
Method that stops the driver operations.
static const std::chrono::milliseconds MODEM_TIMEOUT
Maximum time to wait for modem to become ModemState::AVAILABLE.
bool ack_mode
Set to true to enable IM ack.
std::string rx_payload
String that is updated witn each new received messsage.
std::atomic< bool > receiving
Atomic boolean variable that controls the receiving looping thread.
Config
Enum listing the availbale configuration settings.
TransmissionMode
Transmission mode: either IM or BURST See the EvoLogics S2C manuals or reach for www....
TransmissionState
Transmission state: controls the flow of execution for sending commands to the S2C device.
virtual void startRx(Packet *p)
Method that starts a packet reception.
std::condition_variable tx_queue_cv
Condition variable that is linked with the transmitting queue.
virtual void receivingData()
Mehod that detach a thread devoted to receiving data from the connector.
virtual void endRx(Packet *p)
Method that ends a packet reception.
char txdur_token_separator_
TX duration LUT separator.
virtual void start()
Method that starts the driver operations.
ModemState status
Variable holding the current status of the modem.
virtual ~UwEvoLogicsS2CModem()
Destructor of the UwEvoLogicsS2CModem class.
TransmissionDurationLUT size2dur_
Map from size [byte] to TX duration [s].
int curr_source_level
Current source level already set in device.
std::string txdur_file_name_
TX duration LUT file name.
virtual bool configure(Config cmd)
Method that sends a written configuration the the EvoLgoics modem.
static const std::chrono::milliseconds WAIT_DELIVERY_IM
Time interval to wait for the modem notifying that there no more IM in its queue and a new IM can be ...
virtual double getTxDuration(Packet *p)
Method that return the duration of a given transmitted packet.
virtual int command(int argc, const char *const *argv)
Tcl command interpreter: Method that maps Tcl commands into C++ methods.
std::unique_ptr< UwInterpreterS2C > p_interpreter
Pointer to Interpreter object to parse device syntax.
std::mutex tx_status_m
Mutex associated with the transmission state machine of the modem.
std::thread tx_thread
Object with the tx thread.
virtual int recvSyncClMsg(ClMessage *m)
Cross-Layer messages synchronous interpreter.
std::unique_ptr< UwConnector > p_connector
Pointer to Connector object that interfaces with the device.
virtual void startTx(Packet *p)
Method that triggers the transmission of a packet through a specified modem.
Class to create the Otcl shadow object for an object of the class UwEvoLogicsS2CModem.
TclObject * create(int args, const char *const *argv)
Response
Enum listing the types of commands that could be received or sent by a S2C device; See the EvoLogics ...
Class that implements the interface to DESERT, as used through Tcl scripts.
Definition uwmodem.h:62
void realTxEnded(Packet *p)
Method to call endTx from end of real packet transmission.
Definition uwmodem.h:219
friend class CheckTimer
Definition uwmodem.h:63
std::string modem_address
String containing the address needed to connect to the device In case of socket, it may be expressed ...
Definition uwmodem.h:252
virtual void recv(Packet *p)=0
Method that handles the reception of packets arriving from the upper layers of the network simulator.
std::queue< ModemEvent > event_q
Queue of events that are scheduled for NS2 to execute (callbacks)
Definition uwmodem.h:269
int MAX_READ_BYTES
Maximum number of bytes to be read by a single dump of data.
Definition uwmodem.h:245
CheckTimer * checkTimer
Pointer to an object to schedule the "check-modem" events.
Definition uwmodem.h:265
std::queue< Packet * > tx_queue
Modem's transmission queue: holds packets that are to be transmitted.
Definition uwmodem.h:234
void printOnLog(LogLevel log_level, string module, string message)
Function that, given the appropriate level of log, prints to the set log file the provided log messag...
Definition uwmodem.cpp:102
unsigned int DATA_BUFFER_LEN
Size of the buffer that holds data.
Definition uwmodem.h:242
virtual int getModulationType(Packet *P)
Method that should return the modulation type used for the packet being transmitted.
Definition uwmodem.h:152
virtual int command(int argc, const char *const *argv)
Tcl command interpreter: Method that maps Tcl commands into C++ methods.
Definition uwmodem.cpp:127
std::vector< char > data_buffer
Char buffer (vector) that holds data read from the modem (unparsed data) Main container for data rece...
Definition uwmodem.h:231
int modemID
Number used for identification purposes: not specified.
Definition uwmodem.h:225
double period
Checking period of the modem's buffer.
Definition uwmodem.h:267
Class that implements serial port connection.
Definition uwserial.h:53
Class that implements a TCP or UDP socket.
Definition uwsocket.h:59
Header of the class providing the Uwal header's description.
#define HDR_UWAL(p)
Definition hdr-uwal.h:43
hdr_uwal describes the packet header used by Uwal objects.
Definition hdr-uwal.h:52
char * binPkt()
Return to the binPkt_ array pointer.
Definition hdr-uwal.h:141
uint32_t & binPktLength()
Reference to the binPktLength_ variable.
Definition hdr-uwal.h:150
Header of the main class that implements the adaptation layer between ns2/NS-Miracle and binary data ...
UwEvoLogicsS2C_TclClass class_evologicss2c
Header of the main class that implements the drivers to manage the EvoLogics S2C line of devices....
ModemState
Enum containing the possible statuses of the driver.
Definition of ClMsgUwMmac class.
This implements a generic serial connector .
Class that implements a connector and, specifically, the socket connector. BSD sockets are used,...