Basic MAC data interface for LoRa transceiver

Dependencies:   L2Frame crc

Dependents:   LoRaBaseStation LoRaTerminal

Committer:
rba90
Date:
Sat Sep 03 04:51:26 2016 +0000
Revision:
32:b7d87c5f647c
Parent:
31:a0454fda1538
Child:
33:810074d10fcf
fix a memory leakage problem

Who changed what in which revision?

UserRevisionLine numberNew contents of line
rba90 0:e2ccabf3f30c 1 #include "AlohaTransceiver.h"
rba90 0:e2ccabf3f30c 2 #include "mbed.h"
rba90 0:e2ccabf3f30c 3 #include "radio.h"
rba90 18:3e6483550f25 4 #include "debug.h"
rba90 0:e2ccabf3f30c 5 #include "AlohaFrame.h"
rba90 15:0dc9df48687a 6 #include "RingBuffer.h"
rba90 0:e2ccabf3f30c 7
rba90 28:2c0e115b4f72 8 #define ALLOW_CALLBACK_DEBUG 0
rba90 18:3e6483550f25 9
rba90 28:2c0e115b4f72 10 #define SET_FLAG(t, x) (t) |= 1 << (x)
rba90 28:2c0e115b4f72 11 #define CLEAR_FLAG(t, x) (t) &= ~(1 << (x))
rba90 28:2c0e115b4f72 12 #define TOGGLE_FLAG(t, x) (t) ^= 1 << (x)
rba90 28:2c0e115b4f72 13 #define CHECK_FLAG(t, x) (t) >> (x) & 1
rba90 27:463688e3bd12 14
rba90 0:e2ccabf3f30c 15 // declear the type of radio state
rba90 0:e2ccabf3f30c 16 typedef enum
rba90 0:e2ccabf3f30c 17 {
rba90 0:e2ccabf3f30c 18 LOWPOWER = 0,
rba90 0:e2ccabf3f30c 19 IDLE,
rba90 0:e2ccabf3f30c 20
rba90 0:e2ccabf3f30c 21 RX,
rba90 0:e2ccabf3f30c 22 RX_TIMEOUT,
rba90 0:e2ccabf3f30c 23 RX_ERROR,
rba90 0:e2ccabf3f30c 24
rba90 0:e2ccabf3f30c 25 TX,
rba90 0:e2ccabf3f30c 26 TX_TIMEOUT,
rba90 0:e2ccabf3f30c 27
rba90 0:e2ccabf3f30c 28 CAD,
rba90 0:e2ccabf3f30c 29 CAD_DONE
rba90 0:e2ccabf3f30c 30 }AppStates_t;
rba90 0:e2ccabf3f30c 31
rba90 0:e2ccabf3f30c 32 // radio driver related variables
rba90 0:e2ccabf3f30c 33 static int16_t RssiValue;
rba90 0:e2ccabf3f30c 34 static int8_t SnrValue;
rba90 0:e2ccabf3f30c 35
rba90 0:e2ccabf3f30c 36 static volatile AppStates_t State;
rba90 0:e2ccabf3f30c 37 static RadioEvents_t RadioEvents;
rba90 0:e2ccabf3f30c 38
rba90 27:463688e3bd12 39 // rx queue
rba90 27:463688e3bd12 40 CircularBuffer<AlohaFrame *> AlohaRxQueue(10);
rba90 17:c6e2e2cd6e5f 41
rba90 0:e2ccabf3f30c 42 // callback functions for radio driver
rba90 0:e2ccabf3f30c 43 void OnTxDone();
rba90 0:e2ccabf3f30c 44 void OnRxDone( uint8_t *payload, uint16_t size, int16_t rssi, int8_t snr );
rba90 0:e2ccabf3f30c 45 void OnTxTimeout();
rba90 0:e2ccabf3f30c 46 void OnRxTimeout();
rba90 0:e2ccabf3f30c 47 void OnRxError();
rba90 0:e2ccabf3f30c 48 void OnFhssChangeChannel( uint8_t channelIndex );
rba90 0:e2ccabf3f30c 49 void OnCadDone();
rba90 0:e2ccabf3f30c 50
rba90 0:e2ccabf3f30c 51 // radio driver
rba90 20:bd26d3cbc0bd 52 #ifdef DRIVER_SX1276
rba90 0:e2ccabf3f30c 53 SX1276MB1xAS Radio( NULL );
rba90 0:e2ccabf3f30c 54 #endif
rba90 0:e2ccabf3f30c 55
rba90 20:bd26d3cbc0bd 56 #ifdef DRIVER_INAIR
rba90 0:e2ccabf3f30c 57 SX1276inAir Radio( NULL );
rba90 0:e2ccabf3f30c 58 #endif
rba90 0:e2ccabf3f30c 59
rba90 0:e2ccabf3f30c 60
rba90 0:e2ccabf3f30c 61 /*
rba90 0:e2ccabf3f30c 62 * Abstract interface for accessing radio driver
rba90 0:e2ccabf3f30c 63 */
rba90 0:e2ccabf3f30c 64
rba90 27:463688e3bd12 65 AlohaTransceiver::AlohaTransceiver(uint8_t id):
rba90 31:a0454fda1538 66 AlohaTxQueue(32)
rba90 0:e2ccabf3f30c 67 {
rba90 11:3e1ff29da71a 68 // store unique device id
rba90 11:3e1ff29da71a 69 deviceId = id;
rba90 11:3e1ff29da71a 70
rba90 17:c6e2e2cd6e5f 71 // initialize sequenceid
rba90 17:c6e2e2cd6e5f 72 memset(seqid, 0x0, sizeof(seqid));
rba90 17:c6e2e2cd6e5f 73
rba90 31:a0454fda1538 74 // clear tx done state
rba90 31:a0454fda1538 75 isTxDone = true;
rba90 31:a0454fda1538 76
rba90 31:a0454fda1538 77 // assume all station is clear to transmit
rba90 31:a0454fda1538 78 isAcked = 0xffff;
rba90 28:2c0e115b4f72 79
rba90 0:e2ccabf3f30c 80 // configure properties
rba90 0:e2ccabf3f30c 81 #if USE_MODEM_LORA == 1
rba90 0:e2ccabf3f30c 82 Settings.Power = TX_OUTPUT_POWER;
rba90 0:e2ccabf3f30c 83 Settings.Bandwidth = LORA_BANDWIDTH;
rba90 0:e2ccabf3f30c 84 Settings.Datarate = LORA_SPREADING_FACTOR;
rba90 0:e2ccabf3f30c 85 Settings.Coderate = LORA_CODINGRATE;
rba90 0:e2ccabf3f30c 86 Settings.PreambleLen = LORA_PREAMBLE_LENGTH;
rba90 0:e2ccabf3f30c 87 Settings.SymbolTimeout = LORA_SYMBOL_TIMEOUT;
rba90 0:e2ccabf3f30c 88 Settings.FixLen = LORA_FIX_LENGTH_PAYLOAD_ON;
rba90 0:e2ccabf3f30c 89 Settings.PayloadLen = 0;
rba90 0:e2ccabf3f30c 90 Settings.CrcOn = LORA_CRC_ENABLED;
rba90 0:e2ccabf3f30c 91 Settings.FreqHopOn = LORA_FHSS_ENABLED;
rba90 0:e2ccabf3f30c 92 Settings.HopPeriod = LORA_NB_SYMB_HOP;
rba90 0:e2ccabf3f30c 93 Settings.IqInverted = LORA_IQ_INVERSION_ON;
rba90 0:e2ccabf3f30c 94 Settings.RxContinuous = true;
rba90 0:e2ccabf3f30c 95 Settings.TxTimeout = TX_TIMEOUT_VALUE;
rba90 0:e2ccabf3f30c 96
rba90 0:e2ccabf3f30c 97 #elif USE_MODEM_FSK == 1
rba90 0:e2ccabf3f30c 98 // TODO: Complete settings for FSK mode
rba90 0:e2ccabf3f30c 99 #error "FSK not implemented"
rba90 0:e2ccabf3f30c 100 #else
rba90 0:e2ccabf3f30c 101 #error "Please define a modem in the compiler options."
rba90 0:e2ccabf3f30c 102 #endif
rba90 0:e2ccabf3f30c 103 }
rba90 0:e2ccabf3f30c 104
rba90 0:e2ccabf3f30c 105 AlohaTransceiver::~AlohaTransceiver()
rba90 0:e2ccabf3f30c 106 {
rba90 0:e2ccabf3f30c 107
rba90 0:e2ccabf3f30c 108 }
rba90 0:e2ccabf3f30c 109
rba90 6:f545f5aa7de3 110 void AlohaTransceiver::boardInit()
rba90 0:e2ccabf3f30c 111 {
rba90 0:e2ccabf3f30c 112 // configure callback functions
rba90 0:e2ccabf3f30c 113 RadioEvents.TxDone = OnTxDone;
rba90 0:e2ccabf3f30c 114 RadioEvents.RxDone = OnRxDone;
rba90 0:e2ccabf3f30c 115 RadioEvents.RxError = OnRxError;
rba90 0:e2ccabf3f30c 116 RadioEvents.TxTimeout = OnTxTimeout;
rba90 0:e2ccabf3f30c 117 RadioEvents.RxTimeout = OnRxTimeout;
rba90 0:e2ccabf3f30c 118 Radio.Init( &RadioEvents );
rba90 0:e2ccabf3f30c 119
rba90 0:e2ccabf3f30c 120 // verify the connection with the board
rba90 0:e2ccabf3f30c 121 while( Radio.Read( REG_VERSION ) == 0x00 )
rba90 0:e2ccabf3f30c 122 {
rba90 18:3e6483550f25 123 #ifdef DEBUG_ALOHA
rba90 18:3e6483550f25 124 debug( "Radio could not be detected!\n\r" );
rba90 18:3e6483550f25 125 #endif
rba90 0:e2ccabf3f30c 126 wait( 1 );
rba90 0:e2ccabf3f30c 127 }
rba90 18:3e6483550f25 128 #ifdef DEBUG_ALOHA
rba90 0:e2ccabf3f30c 129 printf("RadioRegVersion: %d\r\n", Radio.Read( REG_VERSION ));
rba90 18:3e6483550f25 130 #endif
rba90 0:e2ccabf3f30c 131 }
rba90 0:e2ccabf3f30c 132
rba90 0:e2ccabf3f30c 133 void AlohaTransceiver::updateSettings()
rba90 0:e2ccabf3f30c 134 {
rba90 6:f545f5aa7de3 135 Radio.SetChannel( RF_FREQUENCY );
rba90 0:e2ccabf3f30c 136 #if USE_MODEM_LORA == 1
rba90 0:e2ccabf3f30c 137
rba90 0:e2ccabf3f30c 138 Radio.SetTxConfig( MODEM_LORA, Settings.Power, 0, Settings.Bandwidth,
rba90 0:e2ccabf3f30c 139 Settings.Datarate, Settings.Coderate,
rba90 0:e2ccabf3f30c 140 Settings.PreambleLen, Settings.FixLen,
rba90 0:e2ccabf3f30c 141 Settings.CrcOn, Settings.FreqHopOn, Settings.HopPeriod,
rba90 0:e2ccabf3f30c 142 Settings.IqInverted, Settings.TxTimeout );
rba90 0:e2ccabf3f30c 143
rba90 0:e2ccabf3f30c 144 Radio.SetRxConfig( MODEM_LORA, Settings.Bandwidth, Settings.Datarate,
rba90 0:e2ccabf3f30c 145 Settings.Coderate, 0, Settings.PreambleLen,
rba90 0:e2ccabf3f30c 146 Settings.SymbolTimeout, Settings.FixLen, Settings.PayloadLen,
rba90 0:e2ccabf3f30c 147 Settings.CrcOn, Settings.FreqHopOn, Settings.HopPeriod,
rba90 0:e2ccabf3f30c 148 Settings.IqInverted, Settings.RxContinuous );
rba90 0:e2ccabf3f30c 149
rba90 0:e2ccabf3f30c 150 #elif USE_MODEM_FSK == 1
rba90 0:e2ccabf3f30c 151 #error "FSK not implemented"
rba90 0:e2ccabf3f30c 152 #else
rba90 0:e2ccabf3f30c 153 #error "Please define a modem in the compiler options."
rba90 0:e2ccabf3f30c 154 #endif
rba90 0:e2ccabf3f30c 155 }
rba90 0:e2ccabf3f30c 156
rba90 6:f545f5aa7de3 157 void AlohaTransceiver::enable()
rba90 6:f545f5aa7de3 158 {
rba90 6:f545f5aa7de3 159 // entering passive receiver mode
rba90 10:065a4b58c6ff 160 Radio.Rx( 0 );
rba90 6:f545f5aa7de3 161 }
rba90 6:f545f5aa7de3 162
rba90 0:e2ccabf3f30c 163 void AlohaTransceiver::poll()
rba90 0:e2ccabf3f30c 164 {
rba90 0:e2ccabf3f30c 165 switch( State )
rba90 0:e2ccabf3f30c 166 {
rba90 0:e2ccabf3f30c 167 case RX:
rba90 5:c3741633dc6f 168 {
rba90 27:463688e3bd12 169 // process packet if received
rba90 30:bccad60351ac 170 // it is noticed that the rx handler does not queue the received packet
rba90 30:bccad60351ac 171 // due to the hardware limitation
rba90 27:463688e3bd12 172 while (AlohaRxQueue.getCounter() > 0)
rba90 25:bcd1cee4e5a8 173 {
rba90 27:463688e3bd12 174 // pop from queue
rba90 27:463688e3bd12 175 AlohaFrame *frame = AlohaRxQueue.dequeue();
rba90 27:463688e3bd12 176
rba90 27:463688e3bd12 177 // check destination
rba90 27:463688e3bd12 178 // if the destination is the device id, then processing, otherwise drop the packet and continue
rba90 27:463688e3bd12 179 // listening
rba90 27:463688e3bd12 180 if (frame->getDestinationAddress() == (deviceId & 0x0f))
rba90 26:e87c8d345644 181 {
rba90 27:463688e3bd12 182 uint8_t type = frame->getType();
rba90 27:463688e3bd12 183
rba90 27:463688e3bd12 184 // schedule the ack frame immediatly after the data frame is received
rba90 27:463688e3bd12 185 if (type == AlohaFrame::Aloha_Data)
rba90 29:6c59b0bba861 186 {
rba90 29:6c59b0bba861 187 #ifdef DEBUG_ALOHA
rba90 29:6c59b0bba861 188 printf("\r\nRXDATA::SRC_ADDR:0x%x,SEQID:0x%x\r\n", frame->getSourceAddress(), frame->getSequenceID());
rba90 29:6c59b0bba861 189 #endif
rba90 27:463688e3bd12 190 sendAck(frame);
rba90 27:463688e3bd12 191 }
rba90 27:463688e3bd12 192 else if (type == AlohaFrame::Aloha_ACK)
rba90 27:463688e3bd12 193 {
rba90 26:e87c8d345644 194 #ifdef DEBUG_ALOHA
rba90 29:6c59b0bba861 195 printf("\r\nRXACK::SRC_ADDR:0x%x,SEQID:0x%x\r\n", frame->getSourceAddress(), frame->getSequenceID());
rba90 26:e87c8d345644 196 #endif
rba90 31:a0454fda1538 197 // clear the ack state
rba90 31:a0454fda1538 198 uint8_t src_addr = frame->getSourceAddress();
rba90 31:a0454fda1538 199 uint8_t foreign_seqid = frame->getSequenceID();
rba90 31:a0454fda1538 200
rba90 31:a0454fda1538 201 // compare the local sequence id and foreign sequence id for specific host
rba90 31:a0454fda1538 202 // if same then set the flag
rba90 31:a0454fda1538 203 if (seqid[src_addr] == foreign_seqid)
rba90 31:a0454fda1538 204 {
rba90 31:a0454fda1538 205 setAckedFlag(src_addr);
rba90 31:a0454fda1538 206 }
rba90 31:a0454fda1538 207 printf("frame_seqid: %d, local_seqid: %d\r\n", frame->getSequenceID(), seqid[frame->getSourceAddress()]);
rba90 31:a0454fda1538 208
rba90 27:463688e3bd12 209 }
rba90 27:463688e3bd12 210
rba90 27:463688e3bd12 211 // check registered callback function
rba90 27:463688e3bd12 212 // execute callback functions if registered
rba90 27:463688e3bd12 213 if (AlohaTypeCallbackTable[type] != NULL)
rba90 27:463688e3bd12 214 {
rba90 27:463688e3bd12 215 uint8_t payload_length = frame->getPayloadLength();
rba90 27:463688e3bd12 216 uint8_t payload[payload_length];
rba90 27:463688e3bd12 217 uint8_t src_addr = frame->getSourceAddress();
rba90 27:463688e3bd12 218
rba90 27:463688e3bd12 219 // extract payload
rba90 27:463688e3bd12 220 for (uint8_t i = 0; i < payload_length; i++)
rba90 27:463688e3bd12 221 {
rba90 27:463688e3bd12 222 payload[i] = frame->getPayload(i);
rba90 27:463688e3bd12 223 }
rba90 27:463688e3bd12 224
rba90 27:463688e3bd12 225 // execute callback function
rba90 27:463688e3bd12 226 AlohaTypeCallbackTable[type](payload, payload_length, src_addr);
rba90 27:463688e3bd12 227 }
rba90 26:e87c8d345644 228 }
rba90 17:c6e2e2cd6e5f 229
rba90 27:463688e3bd12 230 // free memory
rba90 27:463688e3bd12 231 delete frame;
rba90 0:e2ccabf3f30c 232 }
rba90 0:e2ccabf3f30c 233
rba90 10:065a4b58c6ff 234 Radio.Rx( 0 );
rba90 0:e2ccabf3f30c 235 State = LOWPOWER;
rba90 0:e2ccabf3f30c 236 break;
rba90 0:e2ccabf3f30c 237 }
rba90 0:e2ccabf3f30c 238 case TX:
rba90 0:e2ccabf3f30c 239 {
rba90 28:2c0e115b4f72 240 // set tx to done, allow next transmission
rba90 28:2c0e115b4f72 241 setTxDoneFlag();
rba90 28:2c0e115b4f72 242
rba90 10:065a4b58c6ff 243 Radio.Rx( 0 );
rba90 0:e2ccabf3f30c 244 State = LOWPOWER;
rba90 0:e2ccabf3f30c 245 break;
rba90 0:e2ccabf3f30c 246 }
rba90 0:e2ccabf3f30c 247 case RX_TIMEOUT:
rba90 0:e2ccabf3f30c 248 {
rba90 10:065a4b58c6ff 249 Radio.Rx( 0 );
rba90 0:e2ccabf3f30c 250 State = LOWPOWER;
rba90 0:e2ccabf3f30c 251 break;
rba90 0:e2ccabf3f30c 252 }
rba90 0:e2ccabf3f30c 253 case RX_ERROR:
rba90 0:e2ccabf3f30c 254 {
rba90 10:065a4b58c6ff 255 Radio.Rx( 0 );
rba90 0:e2ccabf3f30c 256 State = LOWPOWER;
rba90 0:e2ccabf3f30c 257 break;
rba90 0:e2ccabf3f30c 258 }
rba90 0:e2ccabf3f30c 259 case TX_TIMEOUT:
rba90 0:e2ccabf3f30c 260 {
rba90 29:6c59b0bba861 261 // set tx to done, allow next transmission
rba90 29:6c59b0bba861 262 setTxDoneFlag();
rba90 29:6c59b0bba861 263
rba90 10:065a4b58c6ff 264 Radio.Rx( 0 );
rba90 0:e2ccabf3f30c 265 State = LOWPOWER;
rba90 0:e2ccabf3f30c 266 break;
rba90 0:e2ccabf3f30c 267 }
rba90 0:e2ccabf3f30c 268 case LOWPOWER:
rba90 0:e2ccabf3f30c 269 {
rba90 22:2e39f382f782 270 // transmit packet when the radio is free
rba90 31:a0454fda1538 271 if (getTxDoneFlag())
rba90 22:2e39f382f782 272 {
rba90 31:a0454fda1538 273 // find next available packet to transmit
rba90 31:a0454fda1538 274 for (size_t i = 0; i < AlohaTxQueue.getCounter(); i++)
rba90 31:a0454fda1538 275 {
rba90 31:a0454fda1538 276 AlohaFrame *frame = AlohaTxQueue.dequeue();
rba90 31:a0454fda1538 277 uint8_t type = frame->getType();
rba90 31:a0454fda1538 278
rba90 31:a0454fda1538 279 // determined by the type of the frame, only data frame need to be cleared before transmitting
rba90 31:a0454fda1538 280 switch (type)
rba90 31:a0454fda1538 281 {
rba90 31:a0454fda1538 282 // ack frame can transmit directly
rba90 31:a0454fda1538 283 case AlohaFrame::Aloha_ACK:
rba90 31:a0454fda1538 284 {
rba90 31:a0454fda1538 285 sendFrame(frame);
rba90 32:b7d87c5f647c 286 delete frame;
rba90 32:b7d87c5f647c 287
rba90 31:a0454fda1538 288 break;
rba90 31:a0454fda1538 289 }
rba90 31:a0454fda1538 290 case AlohaFrame::Aloha_Data:
rba90 31:a0454fda1538 291 {
rba90 31:a0454fda1538 292 uint8_t dest_addr = frame->getDestinationAddress();
rba90 31:a0454fda1538 293
rba90 31:a0454fda1538 294 // depending on the availability of the destination host,
rba90 31:a0454fda1538 295 // the radio will on transmit the packet when acked
rba90 31:a0454fda1538 296 if (getAckedFlag(dest_addr))
rba90 31:a0454fda1538 297 {
rba90 31:a0454fda1538 298 sendFrame(frame);
rba90 31:a0454fda1538 299
rba90 31:a0454fda1538 300 // block the next transmission until previous transmission is done
rba90 31:a0454fda1538 301 clearTxDoneFlag();
rba90 31:a0454fda1538 302
rba90 31:a0454fda1538 303 // block the next transmission of the same host until an acked packet
rba90 31:a0454fda1538 304 // is received
rba90 31:a0454fda1538 305 clearAckedFlag(dest_addr);
rba90 31:a0454fda1538 306
rba90 31:a0454fda1538 307 // free memory
rba90 31:a0454fda1538 308 delete frame;
rba90 31:a0454fda1538 309 }
rba90 31:a0454fda1538 310
rba90 31:a0454fda1538 311 // otherwise put the packet back to the end of queue and wait for its being acked
rba90 31:a0454fda1538 312 else
rba90 31:a0454fda1538 313 {
rba90 31:a0454fda1538 314 AlohaTxQueue.enqueue(frame);
rba90 31:a0454fda1538 315 }
rba90 31:a0454fda1538 316 break;
rba90 31:a0454fda1538 317 }
rba90 31:a0454fda1538 318
rba90 31:a0454fda1538 319 default:
rba90 31:a0454fda1538 320 break;
rba90 31:a0454fda1538 321 }
rba90 31:a0454fda1538 322 }
rba90 22:2e39f382f782 323 }
rba90 0:e2ccabf3f30c 324 break;
rba90 0:e2ccabf3f30c 325 }
rba90 0:e2ccabf3f30c 326 default:
rba90 0:e2ccabf3f30c 327 {
rba90 0:e2ccabf3f30c 328 State = LOWPOWER;
rba90 0:e2ccabf3f30c 329 break;
rba90 0:e2ccabf3f30c 330 }
rba90 0:e2ccabf3f30c 331 }
rba90 0:e2ccabf3f30c 332 }
rba90 0:e2ccabf3f30c 333
rba90 31:a0454fda1538 334 void AlohaTransceiver::sendFrame(AlohaFrame *frame)
rba90 31:a0454fda1538 335 {
rba90 31:a0454fda1538 336 // create a buffer for transmit
rba90 31:a0454fda1538 337 uint8_t frame_length = frame->getPayloadLength() + FIXED_BYTE;
rba90 31:a0454fda1538 338 uint8_t buffer[frame_length]; // 4 fix fields
rba90 31:a0454fda1538 339 memset(buffer, 0x0, sizeof(buffer));
rba90 31:a0454fda1538 340
rba90 31:a0454fda1538 341 // copy content to buffer
rba90 31:a0454fda1538 342 frame->serialize(buffer);
rba90 31:a0454fda1538 343
rba90 31:a0454fda1538 344 // send to radio
rba90 31:a0454fda1538 345 Radio.Send(buffer, frame_length);
rba90 31:a0454fda1538 346 }
rba90 31:a0454fda1538 347
rba90 24:8f31c33c7675 348 bool AlohaTransceiver::send(BasicPacket *packet)
rba90 24:8f31c33c7675 349 {
rba90 24:8f31c33c7675 350 // for the reason that we only transmit basic packet format, the
rba90 24:8f31c33c7675 351 // length is always 8
rba90 24:8f31c33c7675 352 uint8_t payload_length = 8;
rba90 24:8f31c33c7675 353
rba90 24:8f31c33c7675 354 // get destination address
rba90 24:8f31c33c7675 355 uint8_t destination_address = findNextHop(packet->getDestinationID());
rba90 24:8f31c33c7675 356
rba90 24:8f31c33c7675 357 // serialize the packet from upper layer
rba90 24:8f31c33c7675 358 uint8_t buffer[payload_length];
rba90 24:8f31c33c7675 359 memset(buffer, 0x0, sizeof(buffer));
rba90 24:8f31c33c7675 360
rba90 24:8f31c33c7675 361 // copy bytes into buffer
rba90 24:8f31c33c7675 362 packet->serialize(buffer);
rba90 17:c6e2e2cd6e5f 363
rba90 17:c6e2e2cd6e5f 364 // create a new frame
rba90 22:2e39f382f782 365 AlohaFrame *frame = new AlohaFrame();
rba90 17:c6e2e2cd6e5f 366
rba90 22:2e39f382f782 367 // set properfies
rba90 24:8f31c33c7675 368 // set payload as data
rba90 22:2e39f382f782 369 frame->setType(AlohaFrame::Aloha_Data);
rba90 24:8f31c33c7675 370
rba90 24:8f31c33c7675 371 // set payload length (8 bytes for BasicPacket)
rba90 22:2e39f382f782 372 frame->setPayloadLength(payload_length);
rba90 24:8f31c33c7675 373
rba90 24:8f31c33c7675 374 // set mac layer device id
rba90 22:2e39f382f782 375 frame->setSourceAddress(deviceId);
rba90 24:8f31c33c7675 376
rba90 24:8f31c33c7675 377 // set mac layer destination id
rba90 24:8f31c33c7675 378 // for multiple hop system, the destination is the next hop
rba90 24:8f31c33c7675 379 // in this case, we use destination id from upper layer
rba90 24:8f31c33c7675 380 frame->setDestinationAddress(packet->getDestinationID());
rba90 24:8f31c33c7675 381
rba90 24:8f31c33c7675 382 // set full message flag (always true in this case)
rba90 22:2e39f382f782 383 frame->setFullMessageFlag(0x1);
rba90 22:2e39f382f782 384
rba90 24:8f31c33c7675 385 // use dest_addr as key for accessing sequence id
rba90 24:8f31c33c7675 386 // the seqid should increase as it successfully transmit the packet
rba90 24:8f31c33c7675 387 frame->setSequenceID(seqid[destination_address]++);
rba90 24:8f31c33c7675 388
rba90 22:2e39f382f782 389 // set payload
rba90 17:c6e2e2cd6e5f 390 for (uint8_t i = 0; i < payload_length; i++)
rba90 17:c6e2e2cd6e5f 391 {
rba90 24:8f31c33c7675 392 frame->setPayload(i, buffer[i]);
rba90 17:c6e2e2cd6e5f 393 }
rba90 17:c6e2e2cd6e5f 394
rba90 17:c6e2e2cd6e5f 395 // calculate crc
rba90 22:2e39f382f782 396 frame->generateCrc();
rba90 17:c6e2e2cd6e5f 397
rba90 22:2e39f382f782 398 // push frame to the back of queue
rba90 22:2e39f382f782 399 AlohaTxQueue.enqueue(frame);
rba90 27:463688e3bd12 400
rba90 27:463688e3bd12 401 // debug
rba90 27:463688e3bd12 402 #ifdef DEBUG_ALOHA
rba90 29:6c59b0bba861 403 printf("\r\nTXDATA::DEST_ADDR:0x%x,SEQID:0x%x\r\n", frame->getDestinationAddress(), frame->getSequenceID());
rba90 27:463688e3bd12 404 #endif
rba90 17:c6e2e2cd6e5f 405 return true;
rba90 0:e2ccabf3f30c 406 }
rba90 0:e2ccabf3f30c 407
rba90 25:bcd1cee4e5a8 408 void AlohaTransceiver::sendAck(AlohaFrame *inFrame)
rba90 25:bcd1cee4e5a8 409 {
rba90 25:bcd1cee4e5a8 410 // create a new frame by calling it's constructor
rba90 25:bcd1cee4e5a8 411 AlohaFrame *outFrame = new AlohaFrame();
rba90 25:bcd1cee4e5a8 412
rba90 25:bcd1cee4e5a8 413 // set frame type
rba90 25:bcd1cee4e5a8 414 outFrame->setType(AlohaFrame::Aloha_ACK);
rba90 25:bcd1cee4e5a8 415
rba90 25:bcd1cee4e5a8 416 // set payload length (0 byte payload for ack frame)
rba90 25:bcd1cee4e5a8 417 outFrame->setPayloadLength(0);
rba90 25:bcd1cee4e5a8 418
rba90 25:bcd1cee4e5a8 419 // set mac layer device id
rba90 25:bcd1cee4e5a8 420 outFrame->setSourceAddress(deviceId);
rba90 25:bcd1cee4e5a8 421
rba90 25:bcd1cee4e5a8 422 // set mac layer destination id
rba90 25:bcd1cee4e5a8 423 outFrame->setDestinationAddress(inFrame->getSourceAddress());
rba90 25:bcd1cee4e5a8 424
rba90 25:bcd1cee4e5a8 425 // set full message flag
rba90 25:bcd1cee4e5a8 426 outFrame->setFullMessageFlag(0x1);
rba90 25:bcd1cee4e5a8 427
rba90 25:bcd1cee4e5a8 428 // set seqid
rba90 25:bcd1cee4e5a8 429 // the sequence id is always the source id + 1
rba90 25:bcd1cee4e5a8 430 outFrame->setSequenceID(inFrame->getSequenceID() + 1);
rba90 25:bcd1cee4e5a8 431
rba90 25:bcd1cee4e5a8 432 // no payload
rba90 25:bcd1cee4e5a8 433
rba90 25:bcd1cee4e5a8 434 // generate cec
rba90 25:bcd1cee4e5a8 435 outFrame->generateCrc();
rba90 25:bcd1cee4e5a8 436
rba90 25:bcd1cee4e5a8 437 // push frame to the back of queue
rba90 25:bcd1cee4e5a8 438 AlohaTxQueue.enqueue(outFrame);
rba90 25:bcd1cee4e5a8 439
rba90 25:bcd1cee4e5a8 440 // debug
rba90 25:bcd1cee4e5a8 441 #ifdef DEBUG_ALOHA
rba90 29:6c59b0bba861 442 printf("\r\nTXACK::DEST_ADDR:0x%x,SEQID:0x%x\r\n", outFrame->getDestinationAddress(), outFrame->getSequenceID());
rba90 25:bcd1cee4e5a8 443 #endif
rba90 25:bcd1cee4e5a8 444 }
rba90 25:bcd1cee4e5a8 445
rba90 28:2c0e115b4f72 446 bool AlohaTransceiver::getTxDoneFlag()
rba90 28:2c0e115b4f72 447 {
rba90 31:a0454fda1538 448 return isTxDone;
rba90 28:2c0e115b4f72 449 }
rba90 28:2c0e115b4f72 450
rba90 28:2c0e115b4f72 451 void AlohaTransceiver::setTxDoneFlag()
rba90 28:2c0e115b4f72 452 {
rba90 31:a0454fda1538 453 isTxDone = true;
rba90 28:2c0e115b4f72 454 }
rba90 28:2c0e115b4f72 455
rba90 28:2c0e115b4f72 456 void AlohaTransceiver::clearTxDoneFlag()
rba90 28:2c0e115b4f72 457 {
rba90 31:a0454fda1538 458 isTxDone = false;
rba90 31:a0454fda1538 459 }
rba90 31:a0454fda1538 460
rba90 31:a0454fda1538 461 bool AlohaTransceiver::getAckedFlag(uint8_t addr)
rba90 31:a0454fda1538 462 {
rba90 31:a0454fda1538 463 return CHECK_FLAG(isAcked, addr);
rba90 31:a0454fda1538 464 }
rba90 31:a0454fda1538 465
rba90 31:a0454fda1538 466 void AlohaTransceiver::setAckedFlag(uint8_t addr)
rba90 31:a0454fda1538 467 {
rba90 31:a0454fda1538 468 SET_FLAG(isAcked, addr);
rba90 31:a0454fda1538 469 }
rba90 31:a0454fda1538 470
rba90 31:a0454fda1538 471 void AlohaTransceiver::clearAckedFlag(uint8_t addr)
rba90 31:a0454fda1538 472 {
rba90 31:a0454fda1538 473 CLEAR_FLAG(isAcked, addr);
rba90 28:2c0e115b4f72 474 }
rba90 28:2c0e115b4f72 475
rba90 0:e2ccabf3f30c 476 void AlohaTransceiver::registerType(AlohaFrame::AlohaType_t type, aloha_callback_func f)
rba90 0:e2ccabf3f30c 477 {
rba90 0:e2ccabf3f30c 478 AlohaTypeCallbackTable[type] = f;
rba90 0:e2ccabf3f30c 479 }
rba90 0:e2ccabf3f30c 480
rba90 0:e2ccabf3f30c 481 void AlohaTransceiver::deRegisterType(AlohaFrame::AlohaType_t type, aloha_callback_func f)
rba90 0:e2ccabf3f30c 482 {
rba90 0:e2ccabf3f30c 483 AlohaTypeCallbackTable[type] = NULL;
rba90 0:e2ccabf3f30c 484 }
rba90 0:e2ccabf3f30c 485
rba90 2:fa264e48d5f7 486 int16_t AlohaTransceiver::getRssi()
rba90 2:fa264e48d5f7 487 {
rba90 2:fa264e48d5f7 488 return RssiValue;
rba90 2:fa264e48d5f7 489 }
rba90 2:fa264e48d5f7 490
rba90 2:fa264e48d5f7 491 int8_t AlohaTransceiver::getSnr()
rba90 2:fa264e48d5f7 492 {
rba90 2:fa264e48d5f7 493 return SnrValue;
rba90 2:fa264e48d5f7 494 }
rba90 2:fa264e48d5f7 495
rba90 17:c6e2e2cd6e5f 496 uint8_t AlohaTransceiver::getDeviceID()
rba90 11:3e1ff29da71a 497 {
rba90 11:3e1ff29da71a 498 return deviceId;
rba90 11:3e1ff29da71a 499 }
rba90 11:3e1ff29da71a 500
rba90 17:c6e2e2cd6e5f 501 void AlohaTransceiver::setDeviceID(uint8_t id)
rba90 11:3e1ff29da71a 502 {
rba90 11:3e1ff29da71a 503 deviceId = id;
rba90 11:3e1ff29da71a 504 }
rba90 11:3e1ff29da71a 505
rba90 24:8f31c33c7675 506 uint8_t AlohaTransceiver::findNextHop(uint8_t addr)
rba90 24:8f31c33c7675 507 {
rba90 24:8f31c33c7675 508 // TODO: maintain a routing lookup table for choosing shortest path
rba90 24:8f31c33c7675 509 return addr;
rba90 24:8f31c33c7675 510 }
rba90 24:8f31c33c7675 511
rba90 8:4bda842f73d4 512 #if USE_MODEM_LORA == 1
rba90 8:4bda842f73d4 513 AlohaTransceiver::LoRaSettings_t *AlohaTransceiver::getSettings()
rba90 8:4bda842f73d4 514 {
rba90 8:4bda842f73d4 515 return &Settings;
rba90 8:4bda842f73d4 516 }
rba90 8:4bda842f73d4 517
rba90 8:4bda842f73d4 518 #elif USE_MODEM_FSK == 1
rba90 8:4bda842f73d4 519 AlohaTransceiver::FskSettings_t *AlohaTransceiver::getSettings()
rba90 8:4bda842f73d4 520 {
rba90 8:4bda842f73d4 521 return &Settings;
rba90 8:4bda842f73d4 522 }
rba90 8:4bda842f73d4 523 #else
rba90 8:4bda842f73d4 524 #error "Please define a modem in the compiler options."
rba90 8:4bda842f73d4 525 #endif
rba90 8:4bda842f73d4 526
rba90 0:e2ccabf3f30c 527 void OnTxDone( void )
rba90 0:e2ccabf3f30c 528 {
rba90 0:e2ccabf3f30c 529 Radio.Sleep( );
rba90 0:e2ccabf3f30c 530 State = TX;
rba90 18:3e6483550f25 531
rba90 18:3e6483550f25 532 #ifdef DEBUG_ALOHA
rba90 28:2c0e115b4f72 533 debug_if(ALLOW_CALLBACK_DEBUG, "> OnTxDone\n\r" );
rba90 18:3e6483550f25 534 #endif
rba90 0:e2ccabf3f30c 535 }
rba90 0:e2ccabf3f30c 536
rba90 0:e2ccabf3f30c 537 void OnRxDone( uint8_t *payload, uint16_t size, int16_t rssi, int8_t snr)
rba90 0:e2ccabf3f30c 538 {
rba90 27:463688e3bd12 539 uint8_t payload_length;
rba90 27:463688e3bd12 540
rba90 0:e2ccabf3f30c 541 Radio.Sleep( );
rba90 0:e2ccabf3f30c 542
rba90 0:e2ccabf3f30c 543 // safeguard: if size exceeded maximum buffer size, it will cause memory overflow
rba90 27:463688e3bd12 544 payload_length = size ? BUFFER_SIZE : size <= BUFFER_SIZE;
rba90 27:463688e3bd12 545
rba90 27:463688e3bd12 546 // create a new frame instance
rba90 27:463688e3bd12 547 AlohaFrame *frame = new AlohaFrame(payload, payload_length);
rba90 27:463688e3bd12 548
rba90 27:463688e3bd12 549 // push onto the end of queue
rba90 27:463688e3bd12 550 AlohaRxQueue.enqueue(frame);
rba90 0:e2ccabf3f30c 551
rba90 0:e2ccabf3f30c 552 RssiValue = rssi;
rba90 0:e2ccabf3f30c 553 SnrValue = snr;
rba90 0:e2ccabf3f30c 554 State = RX;
rba90 18:3e6483550f25 555
rba90 18:3e6483550f25 556 #ifdef DEBUG_ALOHA
rba90 28:2c0e115b4f72 557 debug_if(ALLOW_CALLBACK_DEBUG, "> OnRxDone\n\r" );
rba90 18:3e6483550f25 558 #endif
rba90 0:e2ccabf3f30c 559 }
rba90 0:e2ccabf3f30c 560
rba90 0:e2ccabf3f30c 561 void OnTxTimeout( void )
rba90 0:e2ccabf3f30c 562 {
rba90 0:e2ccabf3f30c 563 Radio.Sleep( );
rba90 0:e2ccabf3f30c 564 State = TX_TIMEOUT;
rba90 18:3e6483550f25 565
rba90 18:3e6483550f25 566 #ifdef DEBUG_ALOHA
rba90 28:2c0e115b4f72 567 debug_if(ALLOW_CALLBACK_DEBUG, "> OnTxTimeout\n\r" );
rba90 18:3e6483550f25 568 #endif
rba90 0:e2ccabf3f30c 569 }
rba90 0:e2ccabf3f30c 570
rba90 0:e2ccabf3f30c 571 void OnRxTimeout( void )
rba90 0:e2ccabf3f30c 572 {
rba90 0:e2ccabf3f30c 573 Radio.Sleep( );
rba90 0:e2ccabf3f30c 574 State = RX_TIMEOUT;
rba90 18:3e6483550f25 575
rba90 18:3e6483550f25 576 #ifdef DEBUG_ALOHA
rba90 28:2c0e115b4f72 577 debug_if(ALLOW_CALLBACK_DEBUG, "> OnRxTimeout\n\r" );
rba90 18:3e6483550f25 578 #endif
rba90 0:e2ccabf3f30c 579 }
rba90 0:e2ccabf3f30c 580
rba90 0:e2ccabf3f30c 581 void OnRxError( void )
rba90 0:e2ccabf3f30c 582 {
rba90 0:e2ccabf3f30c 583 Radio.Sleep( );
rba90 0:e2ccabf3f30c 584 State = RX_ERROR;
rba90 18:3e6483550f25 585
rba90 18:3e6483550f25 586 #ifdef DEBUG_ALOHA
rba90 28:2c0e115b4f72 587 debug_if(ALLOW_CALLBACK_DEBUG, "> OnRxError\n\r" );
rba90 18:3e6483550f25 588 #endif
rba90 0:e2ccabf3f30c 589 }
rba90 24:8f31c33c7675 590