Basic MAC data interface for LoRa transceiver

Dependencies:   L2Frame crc

Dependents:   LoRaBaseStation LoRaTerminal

Revision:
31:a0454fda1538
Parent:
30:bccad60351ac
Child:
32:b7d87c5f647c
--- a/AlohaTransceiver.cpp	Sat Sep 03 03:15:52 2016 +0000
+++ b/AlohaTransceiver.cpp	Sat Sep 03 04:41:48 2016 +0000
@@ -63,7 +63,7 @@
  */
 
 AlohaTransceiver::AlohaTransceiver(uint8_t id):
-    AlohaTxQueue(10)
+    AlohaTxQueue(32)
 {
     // store unique device id
     deviceId = id;
@@ -71,8 +71,11 @@
     // initialize sequenceid
     memset(seqid, 0x0, sizeof(seqid));
     
-    // clear flags
-    flags = 0xff;
+    // clear tx done state
+    isTxDone = true;
+    
+    // assume all station is clear to transmit
+    isAcked = 0xffff;
     
     // configure properties
 #if USE_MODEM_LORA == 1
@@ -191,6 +194,18 @@
 #ifdef DEBUG_ALOHA
                         printf("\r\nRXACK::SRC_ADDR:0x%x,SEQID:0x%x\r\n", frame->getSourceAddress(), frame->getSequenceID());
 #endif 
+                        // clear the ack state
+                        uint8_t src_addr = frame->getSourceAddress();
+                        uint8_t foreign_seqid = frame->getSequenceID();
+                        
+                        // compare the local sequence id and foreign sequence id for specific host
+                        // if same then set the flag
+                        if (seqid[src_addr] == foreign_seqid)
+                        {
+                            setAckedFlag(src_addr);
+                        }
+                        printf("frame_seqid: %d, local_seqid: %d\r\n", frame->getSequenceID(), seqid[frame->getSourceAddress()]);
+                        
                     }
                 
                     // check registered callback function
@@ -253,26 +268,56 @@
         case LOWPOWER:
         {
             // transmit packet when the radio is free
-            if (getTxDoneFlag() && AlohaTxQueue.getCounter() > 0)
+            if (getTxDoneFlag())
             {
-                AlohaFrame *frame = AlohaTxQueue.dequeue();
-                
-                // create a buffer for transmit
-                uint8_t frame_length = frame->getPayloadLength() + FIXED_BYTE;
-                uint8_t buffer[frame_length];         // 4 fix fields
-                memset(buffer, 0x0, sizeof(buffer));
-                
-                // copy content to buffer
-                frame->serialize(buffer);
-                
-                // send to radio 
-                Radio.Send(buffer, frame_length);
-                
-                // block the next transmission until previous transmission is done
-                clearTxDoneFlag();
-                
-                // free memory
-                delete frame;
+                // find next available packet to transmit
+                for (size_t i = 0; i < AlohaTxQueue.getCounter(); i++)
+                {
+                    AlohaFrame *frame = AlohaTxQueue.dequeue();
+                    uint8_t type = frame->getType();
+                    
+                    // determined by the type of the frame, only data frame need to be cleared before transmitting
+                    switch (type)
+                    {
+                        // ack frame can transmit directly
+                        case AlohaFrame::Aloha_ACK:
+                        {
+                            sendFrame(frame);
+                            break;
+                        }
+                        case AlohaFrame::Aloha_Data:
+                        {
+                            uint8_t dest_addr = frame->getDestinationAddress();
+                            
+                            // depending on the availability of the destination host,
+                            // the radio will on transmit the packet when acked
+                            if (getAckedFlag(dest_addr))
+                            {
+                                sendFrame(frame);
+                                
+                                // block the next transmission until previous transmission is done
+                                clearTxDoneFlag();
+                                
+                                // block the next transmission of the same host until an acked packet
+                                // is received
+                                clearAckedFlag(dest_addr);
+                                
+                                // free memory
+                                delete frame;
+                            }
+                            
+                            // otherwise put the packet back to the end of queue and wait for its being acked
+                            else
+                            {
+                                AlohaTxQueue.enqueue(frame);
+                            }
+                            break;
+                        }
+                        
+                        default:
+                            break;
+                    }
+                }
             }
             break;
         }
@@ -284,6 +329,20 @@
     }
 }
 
+void AlohaTransceiver::sendFrame(AlohaFrame *frame)
+{
+    // create a buffer for transmit
+    uint8_t frame_length = frame->getPayloadLength() + FIXED_BYTE;
+    uint8_t buffer[frame_length];         // 4 fix fields
+    memset(buffer, 0x0, sizeof(buffer));
+    
+    // copy content to buffer
+    frame->serialize(buffer);
+    
+    // send to radio 
+    Radio.Send(buffer, frame_length);
+}
+
 bool AlohaTransceiver::send(BasicPacket *packet)
 {   
     // for the reason that we only transmit basic packet format, the 
@@ -384,17 +443,32 @@
 
 bool AlohaTransceiver::getTxDoneFlag()
 {
-    return CHECK_FLAG(flags, 0);
+    return isTxDone;
 }
 
 void AlohaTransceiver::setTxDoneFlag()
 {
-    SET_FLAG(flags, 0);
+    isTxDone = true;
 }
 
 void AlohaTransceiver::clearTxDoneFlag()
 {
-    CLEAR_FLAG(flags, 0);
+    isTxDone = false;
+}
+
+bool AlohaTransceiver::getAckedFlag(uint8_t addr)
+{
+    return CHECK_FLAG(isAcked, addr);
+}
+
+void AlohaTransceiver::setAckedFlag(uint8_t addr)
+{
+    SET_FLAG(isAcked, addr);
+}
+
+void AlohaTransceiver::clearAckedFlag(uint8_t addr)
+{
+    CLEAR_FLAG(isAcked, addr);
 }
 
 void AlohaTransceiver::registerType(AlohaFrame::AlohaType_t type, aloha_callback_func f)