Jonathan Jones
/
Radios
Radio Structures in OOP
Diff: modules/CommModule/CommModule.cpp
- Revision:
- 3:dc7e9c6bc26c
- Parent:
- 2:7d523bdd2f50
- Child:
- 4:989d51f3e6ef
--- a/modules/CommModule/CommModule.cpp Sun Dec 28 06:05:17 2014 +0000 +++ b/modules/CommModule/CommModule.cpp Sat Jan 03 04:35:32 2015 +0000 @@ -1,5 +1,4 @@ #include "CommModule.h" -#include "ThreadHelper.h" // Set the class's constants for streamlined use in other areas of the code const int CommModule::TX_QUEUE_SIZE = COMM_MODULE_TX_QUEUE_SIZE; @@ -7,57 +6,60 @@ const int CommModule::NBR_PORTS = COMM_MODULE_NBR_PORTS; // Default constructor -CommModule::CommModule() +CommModule::CommModule() : + // [X] - 1.1 - Define the data queues. + // ================= + _txQueueHelper(), + _rxQueueHelper() { - // [X] - 2 - Setup everything for RTP packets - - // [X] - 3 - Set the default radio link - - // [] - 4 - Define the tx/rx task threads and start their operations - - // [] - 4 - Setup the services for all of the ports (sockets) + // [X] - 1.2 - Create the data queues. + // ================= + _txQueue = osMailCreate(_txQueueHelper.def(), NULL); + _rxQueue = osMailCreate(_rxQueueHelper.def(), NULL); - // Define the data queues [THESE ARE MACROS] - osMailQDef(_txQueue_, COMM_MODULE_TX_QUEUE_SIZE, RTP_t); - osMailQDef(_rxQueue_, COMM_MODULE_RX_QUEUE_SIZE, RTP_t); - - // [THIS CURRENTLY CAUSES AN MBED RUNTIME ERROR] - // Create the data queues - //_txQueue = osMailCreate(osMailQ(_txQueue_), NULL); - //_rxQueue = osMailCreate(osMailQ(_rxQueue_), NULL); - - // Outline the thread definitions + // [X] - 2.1 - Define the TX & RX task threads. + // ================= define_thread(_txDef, &CommModule::txThread); define_thread(_rxDef, &CommModule::rxThread); - // Create the thread and pass it a pointer to the created object + // [X] - 2.2 - Create the TX & RX threads - pass them a pointer to the created object. + // ================= _txID = osThreadCreate(&_txDef, (void*)this); _rxID = osThreadCreate(&_rxDef, (void*)this); +} - // Set the default hardware link to nothing - _link = NULL; +CommModule::~CommModule() +{ + if (_open_ports) + delete _open_ports; } void CommModule::txThread(void const *arg) { CommModule *inst = (CommModule*)arg; - + // Only continue past this point once at least one (1) hardware link is initialized - + osSignalWait(COMM_MODULE_SIGNAL_START_THREAD, osWaitForever); + + LOG("TX Ready!\r\n"); + while(1) { + // When a new RTP packet is put in the tx queue, begin operations (does nothing if no new data in queue) osEvent evt = osMailGet(inst->_txQueue, osWaitForever); if (evt.status == osEventMail) { // Get a pointer to the packet's memory location - RTP_t *packet = (RTP_t*)evt.value.p; + RTP_t *p = (RTP_t*)evt.value.p; // Send the packet on the active communication link - inst->_link->sendPacket(packet); + inst->_tx_handles[p->port].call(p); + + EVENT("Transmission: Port: %u Subclass: %u\r\n", p->port, p->subclass); // Release the allocated memory once data is sent - osMailFree(inst->_txQueue, packet); + osMailFree(inst->_txQueue, p); } } } @@ -65,49 +67,166 @@ void CommModule::rxThread(void const *arg) { CommModule *inst = (CommModule*)arg; - + // Only continue past this point once at least one (1) hardware link is initialized + osSignalWait(COMM_MODULE_SIGNAL_START_THREAD, osWaitForever); - // RTP_t p; + LOG("RX Ready!\r\n"); + + RTP_t *p; + osEvent evt; while(1) { // Wait until new data is placed in the class's rxQueue from a CommLink class + evt = osMailGet(inst->_rxQueue, osWaitForever); - /* - // Read a new packet from the active interface - link->receivePacket(&p); + if (evt.status == osEventMail) { + + // get a pointer to where the data is stored + p = (RTP_t*)evt.value.p; - if (p.port) { - // write the received packet to it's respective port's queue - // rxQueue[p.port] - } + /* + if (inst->p.port) { + // write the received packet to it's respective port's queue + inst->rxQueue[p->port] + } + */ - if (callbacks[p.port]) { - // call the respective port's function for executing the correct task - // callbacks[p.port](&p); + // If there is an open socket for the port, call it. + if (std::binary_search(inst->_open_ports->begin(), inst->_open_ports->end(), p->port)) { + inst->_rx_handles[p->port].call(); + } + + EVENT("Reception: \r\n Port: %u\r\n Subclass: %u\r\n", p->port, p->subclass); + + osMailFree(inst->_rxQueue, p); // free memory allocated for mail } - */ - } } -void CommModule::setLink(CommLink *link) +void CommModule::TxHandler(void(*ptr)(RTP_t*), uint8_t portNbr) +{ + ready(); + // if (std::binary_search(_open_ports->begin(), _open_ports->end(), portNbr)) { + // LOG("Port number %u already binded to open socket.\r\n", portNbr); + // } else { + // [X] - 1 - Add the port number to the list of active ports & keep sorted + //_open_ports->push_back(portNbr); + //std::sort(_open_ports->begin(), _open_ports->end()); + + // [X] - 2 - Set the passed communication link object's pointer to the link pointers array. + // ================= + _tx_handles[portNbr].attach(ptr); + + LOG("Port %u ready for TX using static function call.\r\n", portNbr); + // } +} + +template <typename T> +void CommModule::TxHandler(T *tptr, void(T::*mptr)(RTP_t*), uint8_t portNbr) { - // Update the currently active hardware communication link - _link = link; + ready(); + if (std::binary_search(_open_ports->begin(), _open_ports->end(), portNbr)) { + WARNING("Port number %u already binded to open socket.\r\n", portNbr); + } else { + // [X] - 1 - Add the port number to the list of active ports & keep sorted + _open_ports->push_back(portNbr); + std::sort(_open_ports->begin(), _open_ports->end()); + + // [X] - 2 - Set the passed communication link object's pointer to the link pointers array. + // ================= + _tx_handles[portNbr].attach(tprt, mptr); + + LOG("Port %u ready for TX using member function call.\r\n", portNbr); + } +} + +void CommModule::openSocket(CommLink* link, uint8_t portNbr, void(*rx)(void const *arg)) +{ + ready(); + if (std::binary_search(_open_ports->begin(), _open_ports->end(), portNbr)) { + WARNING("Port number %u already binded to open socket.\r\n", portNbr); + } else { + // [X] - 1 - Add the port number to the list of active ports & keep sorted + _open_ports->push_back(portNbr); + std::sort(_open_ports->begin(), _open_ports->end()); + + // [X] - 2 - Set the passed communication link object's pointer to the link pointers array. + // ================= + _link[portNbr] = link; + + // [X] - 3 - Associate the given port number with the passed function pointer. + // ================= + _rx_handles[portNbr].attach(rx); + + LOG("Port %u ready for RX.\r\n", portNbr); + } } -void CommModule::openSocket(uint8_t portNbr, void(*task)(void const *arg)) + +void CommModule::ready(void) { - // [] - 1 - Associate the given port number with the passed function pointer (set this in the class's variables) - - // [] - 2 - The function pointer should be called when a packet of its respective port number is received + static bool isReady = false; + + if (!isReady) { + isReady = true; + + _open_ports = new std::vector<uint8_t>; + + osSignalSet(_txID, COMM_MODULE_SIGNAL_START_THREAD); + osSignalSet(_rxID, COMM_MODULE_SIGNAL_START_THREAD); + } } -void CommModule::send(RTP_t& p) + +void CommModule::send(RTP_t& packet) { - // [] - 1 - Place the passed packet into the txQueue - - // [] - 2 - Ensure that proper threads know that new information is available in the queue + // [X] - 1 - Check to make sure a socket for the port exists + if (std::binary_search(_open_ports->begin(), _open_ports->end(), packet.port)) { + + // [X] - 1.1 - Allocate a block of memory for the data. + // ================= + RTP_t *p = (RTP_t*)osMailAlloc(_txQueue, osWaitForever); + + // [X] - 1.2 - Copy the contents into the allocated memory block + // ================= + p->port = packet.port; + p->subclass = packet.subclass; + + for (int i=0; i<(sizeof(packet)/sizeof(uint8_t)); i++) + p->data[i] = packet.data[i]; + + // [X] - 1.3 - Place the passed packet into the txQueue. + // ================= + osMailPut(_txQueue, p); + } else { + WARNING("There is no open socket for port %u.\r\n", packet.port); + } +} + + +void CommModule::receive(RTP_t& packet) +{ + // [X] - 1 - Check to make sure a socket for the port exists + if (std::binary_search(_open_ports->begin(), _open_ports->end(), packet.port)) { + + // [X] - 1.1 - Allocate a block of memory for the data. + // ================= + RTP_t *p = (RTP_t*)osMailAlloc(_rxQueue, osWaitForever); + + // [X] - 1.2 - Copy the contents into the allocated memory block + // ================= + p->port = packet.port; + p->subclass = packet.subclass; + + for (int i=0; i<(sizeof(packet)/sizeof(uint8_t)); i++) + p->data[i] = packet.data[i]; + + // [X] - 1.3 - Place the passed packet into the txQueue. + // ================= + osMailPut(_rxQueue, p); + } else { + WARNING("Received pack from unopen port %u.\r\n", packet.port); + } } \ No newline at end of file