Basic MAC data interface for LoRa transceiver
Dependents: LoRaBaseStation LoRaTerminal
Diff: AlohaTransceiver.cpp
- Revision:
- 39:0da3ee6a297d
- Parent:
- 38:e7b679acf524
- Child:
- 40:271fa9e98589
diff -r e7b679acf524 -r 0da3ee6a297d AlohaTransceiver.cpp --- a/AlohaTransceiver.cpp Wed Sep 14 06:36:24 2016 +0000 +++ b/AlohaTransceiver.cpp Wed Sep 14 07:47:18 2016 +0000 @@ -6,6 +6,8 @@ #include "RingBuffer.h" #define ALLOW_CALLBACK_DEBUG 1 +#define CSMA_CA_BACKOFF_TIME 1000 // in ms +#define CSMA_CA_CHANNEL_THRESHOLD -80 // in dbm #define SET_FLAG(t, x) (t) |= 1 << (x) #define CLEAR_FLAG(t, x) (t) &= ~(1 << (x)) @@ -78,6 +80,12 @@ // assume all station is clear to transmit isAcked = 0xffff; + // reset CSMA backoff timer + CSMABackoffTimer.reset(); + + // reset CSMA backoff state + isBackoff = false; + // configure properties #if USE_MODEM_LORA == 1 @@ -206,7 +214,7 @@ setAckedFlag(src_addr); } #ifdef DEBUG_ALOHA - printf("frame_seqid: %d, local_seqid: %d\r\n", frame->getSequenceID(), seqid[frame->getSourceAddress()]); + printf("ACK::frame_seqid: %d, local_seqid: %d\r\n", frame->getSequenceID(), seqid[frame->getSourceAddress()]); #endif } @@ -273,57 +281,86 @@ if (getTxDoneFlag()) { // find next available packet to transmit - for (size_t i = 0; i < AlohaTxQueue.getCounter(); i++) + while( AlohaTxQueue.getCounter() > 0) { - AlohaFrame *frame = AlohaTxQueue.dequeue(); - - // determined by the type of the frame, only data frame need to be cleared before transmitting - switch (frame->getType()) + // perform CSMA backoff routine + if (isBackoff == true) // if the transceiver is already in the backoff state, then wait until timer expires { - // Data frame need proper clearance - case AlohaFrame::Aloha_Data: + if (CSMABackoffTimer.read_ms() > CSMA_CA_BACKOFF_TIME) + { + isBackoff = false; + CSMABackoffTimer.stop(); + } + } + + + if (isBackoff == false) // if the transceiver is not in backoff state, then attempt to transmit + { + if (Radio.IsChannelFree(MODEM_LORA, RF_FREQUENCY, CSMA_CA_CHANNEL_THRESHOLD)) { - uint8_t dest_addr = frame->getDestinationAddress(); - - // depending on the availability of the destination host, - // the radio will on transmit the packet when acked. - // - // in the test build, we are not going to enable this feature - // if (getAckedFlag(dest_addr)) - if (true) +#ifdef DEBUG_ALOHA + printf(" CSMA/CA::Channel is free, ready to transmit\r\n"); +#endif + AlohaFrame *frame = AlohaTxQueue.dequeue(); + + // determined by the type of the frame, only data frame need to be cleared before transmitting + switch (frame->getType()) { - sendFrame(frame); - - // block the next transmission until previous transmission is done - clearTxDoneFlag(); + // Data frame need proper clearance + 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. + // + // in the test build, we are not going to enable this feature + // if (getAckedFlag(dest_addr)) + if (true) + { + 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; + } - // 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); + default: + { + sendFrame(frame); + + // block the next transmission until previous transmission is done + clearTxDoneFlag(); + + // free memory + delete frame; + + break; + } } - break; } - - default: + else // if channel if not free, then start the timer, set the backoff state to true { - sendFrame(frame); - - // block the next transmission until previous transmission is done - clearTxDoneFlag(); - - // free memory - delete frame; - - break; +#ifdef DEBUG_ALOHA + printf("CSMA/CA::Channel is not free, wait for 1s\r\n"); +#endif + isBackoff = true; + CSMABackoffTimer.reset(); + CSMABackoffTimer.start(); } } } @@ -537,7 +574,7 @@ State = TX; #ifdef DEBUG_ALOHA - debug_if(ALLOW_CALLBACK_DEBUG, "> OnTxDone\n\r" ); + debug_if(ALLOW_CALLBACK_DEBUG, "RADIO::OnTxDone\n\r" ); #endif } @@ -561,7 +598,7 @@ State = RX; #ifdef DEBUG_ALOHA - debug_if(ALLOW_CALLBACK_DEBUG, "> OnRxDone, RSSI=%d, SNR=%d\n\r", rssi, snr ); + debug_if(ALLOW_CALLBACK_DEBUG, "RADIO::OnRxDone, RSSI=%d, SNR=%d\n\r", rssi, snr ); #endif } @@ -571,7 +608,7 @@ State = TX_TIMEOUT; #ifdef DEBUG_ALOHA - debug_if(ALLOW_CALLBACK_DEBUG, "> OnTxTimeout\n\r" ); + debug_if(ALLOW_CALLBACK_DEBUG, "RADIO::OnTxTimeout\r\n" ); #endif } @@ -581,7 +618,7 @@ State = RX_TIMEOUT; #ifdef DEBUG_ALOHA - debug_if(ALLOW_CALLBACK_DEBUG, "> OnRxTimeout\n\r" ); + debug_if(ALLOW_CALLBACK_DEBUG, "RADIO::OnRxTimeout\r\n" ); #endif } @@ -591,7 +628,7 @@ State = RX_ERROR; #ifdef DEBUG_ALOHA - debug_if(ALLOW_CALLBACK_DEBUG, "> OnRxError\n\r" ); + debug_if(ALLOW_CALLBACK_DEBUG, "RADIO::OnRxError\r\n" ); #endif }