Radio Structures in OOP

Dependencies:   mbed mbed-rtos

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