Basic MAC data interface for LoRa transceiver

Dependencies:   L2Frame crc

Dependents:   LoRaBaseStation LoRaTerminal

Committer:
rba90
Date:
Sat Sep 03 03:15:52 2016 +0000
Revision:
30:bccad60351ac
Parent:
29:6c59b0bba861
Child:
31:a0454fda1538
update comment

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 27:463688e3bd12 66 AlohaTxQueue(10)
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 28:2c0e115b4f72 74 // clear flags
rba90 28:2c0e115b4f72 75 flags = 0xff;
rba90 28:2c0e115b4f72 76
rba90 0:e2ccabf3f30c 77 // configure properties
rba90 0:e2ccabf3f30c 78 #if USE_MODEM_LORA == 1
rba90 0:e2ccabf3f30c 79 Settings.Power = TX_OUTPUT_POWER;
rba90 0:e2ccabf3f30c 80 Settings.Bandwidth = LORA_BANDWIDTH;
rba90 0:e2ccabf3f30c 81 Settings.Datarate = LORA_SPREADING_FACTOR;
rba90 0:e2ccabf3f30c 82 Settings.Coderate = LORA_CODINGRATE;
rba90 0:e2ccabf3f30c 83 Settings.PreambleLen = LORA_PREAMBLE_LENGTH;
rba90 0:e2ccabf3f30c 84 Settings.SymbolTimeout = LORA_SYMBOL_TIMEOUT;
rba90 0:e2ccabf3f30c 85 Settings.FixLen = LORA_FIX_LENGTH_PAYLOAD_ON;
rba90 0:e2ccabf3f30c 86 Settings.PayloadLen = 0;
rba90 0:e2ccabf3f30c 87 Settings.CrcOn = LORA_CRC_ENABLED;
rba90 0:e2ccabf3f30c 88 Settings.FreqHopOn = LORA_FHSS_ENABLED;
rba90 0:e2ccabf3f30c 89 Settings.HopPeriod = LORA_NB_SYMB_HOP;
rba90 0:e2ccabf3f30c 90 Settings.IqInverted = LORA_IQ_INVERSION_ON;
rba90 0:e2ccabf3f30c 91 Settings.RxContinuous = true;
rba90 0:e2ccabf3f30c 92 Settings.TxTimeout = TX_TIMEOUT_VALUE;
rba90 0:e2ccabf3f30c 93
rba90 0:e2ccabf3f30c 94 #elif USE_MODEM_FSK == 1
rba90 0:e2ccabf3f30c 95 // TODO: Complete settings for FSK mode
rba90 0:e2ccabf3f30c 96 #error "FSK not implemented"
rba90 0:e2ccabf3f30c 97 #else
rba90 0:e2ccabf3f30c 98 #error "Please define a modem in the compiler options."
rba90 0:e2ccabf3f30c 99 #endif
rba90 0:e2ccabf3f30c 100 }
rba90 0:e2ccabf3f30c 101
rba90 0:e2ccabf3f30c 102 AlohaTransceiver::~AlohaTransceiver()
rba90 0:e2ccabf3f30c 103 {
rba90 0:e2ccabf3f30c 104
rba90 0:e2ccabf3f30c 105 }
rba90 0:e2ccabf3f30c 106
rba90 6:f545f5aa7de3 107 void AlohaTransceiver::boardInit()
rba90 0:e2ccabf3f30c 108 {
rba90 0:e2ccabf3f30c 109 // configure callback functions
rba90 0:e2ccabf3f30c 110 RadioEvents.TxDone = OnTxDone;
rba90 0:e2ccabf3f30c 111 RadioEvents.RxDone = OnRxDone;
rba90 0:e2ccabf3f30c 112 RadioEvents.RxError = OnRxError;
rba90 0:e2ccabf3f30c 113 RadioEvents.TxTimeout = OnTxTimeout;
rba90 0:e2ccabf3f30c 114 RadioEvents.RxTimeout = OnRxTimeout;
rba90 0:e2ccabf3f30c 115 Radio.Init( &RadioEvents );
rba90 0:e2ccabf3f30c 116
rba90 0:e2ccabf3f30c 117 // verify the connection with the board
rba90 0:e2ccabf3f30c 118 while( Radio.Read( REG_VERSION ) == 0x00 )
rba90 0:e2ccabf3f30c 119 {
rba90 18:3e6483550f25 120 #ifdef DEBUG_ALOHA
rba90 18:3e6483550f25 121 debug( "Radio could not be detected!\n\r" );
rba90 18:3e6483550f25 122 #endif
rba90 0:e2ccabf3f30c 123 wait( 1 );
rba90 0:e2ccabf3f30c 124 }
rba90 18:3e6483550f25 125 #ifdef DEBUG_ALOHA
rba90 0:e2ccabf3f30c 126 printf("RadioRegVersion: %d\r\n", Radio.Read( REG_VERSION ));
rba90 18:3e6483550f25 127 #endif
rba90 0:e2ccabf3f30c 128 }
rba90 0:e2ccabf3f30c 129
rba90 0:e2ccabf3f30c 130 void AlohaTransceiver::updateSettings()
rba90 0:e2ccabf3f30c 131 {
rba90 6:f545f5aa7de3 132 Radio.SetChannel( RF_FREQUENCY );
rba90 0:e2ccabf3f30c 133 #if USE_MODEM_LORA == 1
rba90 0:e2ccabf3f30c 134
rba90 0:e2ccabf3f30c 135 Radio.SetTxConfig( MODEM_LORA, Settings.Power, 0, Settings.Bandwidth,
rba90 0:e2ccabf3f30c 136 Settings.Datarate, Settings.Coderate,
rba90 0:e2ccabf3f30c 137 Settings.PreambleLen, Settings.FixLen,
rba90 0:e2ccabf3f30c 138 Settings.CrcOn, Settings.FreqHopOn, Settings.HopPeriod,
rba90 0:e2ccabf3f30c 139 Settings.IqInverted, Settings.TxTimeout );
rba90 0:e2ccabf3f30c 140
rba90 0:e2ccabf3f30c 141 Radio.SetRxConfig( MODEM_LORA, Settings.Bandwidth, Settings.Datarate,
rba90 0:e2ccabf3f30c 142 Settings.Coderate, 0, Settings.PreambleLen,
rba90 0:e2ccabf3f30c 143 Settings.SymbolTimeout, Settings.FixLen, Settings.PayloadLen,
rba90 0:e2ccabf3f30c 144 Settings.CrcOn, Settings.FreqHopOn, Settings.HopPeriod,
rba90 0:e2ccabf3f30c 145 Settings.IqInverted, Settings.RxContinuous );
rba90 0:e2ccabf3f30c 146
rba90 0:e2ccabf3f30c 147 #elif USE_MODEM_FSK == 1
rba90 0:e2ccabf3f30c 148 #error "FSK not implemented"
rba90 0:e2ccabf3f30c 149 #else
rba90 0:e2ccabf3f30c 150 #error "Please define a modem in the compiler options."
rba90 0:e2ccabf3f30c 151 #endif
rba90 0:e2ccabf3f30c 152 }
rba90 0:e2ccabf3f30c 153
rba90 6:f545f5aa7de3 154 void AlohaTransceiver::enable()
rba90 6:f545f5aa7de3 155 {
rba90 6:f545f5aa7de3 156 // entering passive receiver mode
rba90 10:065a4b58c6ff 157 Radio.Rx( 0 );
rba90 6:f545f5aa7de3 158 }
rba90 6:f545f5aa7de3 159
rba90 0:e2ccabf3f30c 160 void AlohaTransceiver::poll()
rba90 0:e2ccabf3f30c 161 {
rba90 0:e2ccabf3f30c 162 switch( State )
rba90 0:e2ccabf3f30c 163 {
rba90 0:e2ccabf3f30c 164 case RX:
rba90 5:c3741633dc6f 165 {
rba90 27:463688e3bd12 166 // process packet if received
rba90 30:bccad60351ac 167 // it is noticed that the rx handler does not queue the received packet
rba90 30:bccad60351ac 168 // due to the hardware limitation
rba90 27:463688e3bd12 169 while (AlohaRxQueue.getCounter() > 0)
rba90 25:bcd1cee4e5a8 170 {
rba90 27:463688e3bd12 171 // pop from queue
rba90 27:463688e3bd12 172 AlohaFrame *frame = AlohaRxQueue.dequeue();
rba90 27:463688e3bd12 173
rba90 27:463688e3bd12 174 // check destination
rba90 27:463688e3bd12 175 // if the destination is the device id, then processing, otherwise drop the packet and continue
rba90 27:463688e3bd12 176 // listening
rba90 27:463688e3bd12 177 if (frame->getDestinationAddress() == (deviceId & 0x0f))
rba90 26:e87c8d345644 178 {
rba90 27:463688e3bd12 179 uint8_t type = frame->getType();
rba90 27:463688e3bd12 180
rba90 27:463688e3bd12 181 // schedule the ack frame immediatly after the data frame is received
rba90 27:463688e3bd12 182 if (type == AlohaFrame::Aloha_Data)
rba90 29:6c59b0bba861 183 {
rba90 29:6c59b0bba861 184 #ifdef DEBUG_ALOHA
rba90 29:6c59b0bba861 185 printf("\r\nRXDATA::SRC_ADDR:0x%x,SEQID:0x%x\r\n", frame->getSourceAddress(), frame->getSequenceID());
rba90 29:6c59b0bba861 186 #endif
rba90 27:463688e3bd12 187 sendAck(frame);
rba90 27:463688e3bd12 188 }
rba90 27:463688e3bd12 189 else if (type == AlohaFrame::Aloha_ACK)
rba90 27:463688e3bd12 190 {
rba90 26:e87c8d345644 191 #ifdef DEBUG_ALOHA
rba90 29:6c59b0bba861 192 printf("\r\nRXACK::SRC_ADDR:0x%x,SEQID:0x%x\r\n", frame->getSourceAddress(), frame->getSequenceID());
rba90 26:e87c8d345644 193 #endif
rba90 27:463688e3bd12 194 }
rba90 27:463688e3bd12 195
rba90 27:463688e3bd12 196 // check registered callback function
rba90 27:463688e3bd12 197 // execute callback functions if registered
rba90 27:463688e3bd12 198 if (AlohaTypeCallbackTable[type] != NULL)
rba90 27:463688e3bd12 199 {
rba90 27:463688e3bd12 200 uint8_t payload_length = frame->getPayloadLength();
rba90 27:463688e3bd12 201 uint8_t payload[payload_length];
rba90 27:463688e3bd12 202 uint8_t src_addr = frame->getSourceAddress();
rba90 27:463688e3bd12 203
rba90 27:463688e3bd12 204 // extract payload
rba90 27:463688e3bd12 205 for (uint8_t i = 0; i < payload_length; i++)
rba90 27:463688e3bd12 206 {
rba90 27:463688e3bd12 207 payload[i] = frame->getPayload(i);
rba90 27:463688e3bd12 208 }
rba90 27:463688e3bd12 209
rba90 27:463688e3bd12 210 // execute callback function
rba90 27:463688e3bd12 211 AlohaTypeCallbackTable[type](payload, payload_length, src_addr);
rba90 27:463688e3bd12 212 }
rba90 26:e87c8d345644 213 }
rba90 17:c6e2e2cd6e5f 214
rba90 27:463688e3bd12 215 // free memory
rba90 27:463688e3bd12 216 delete frame;
rba90 0:e2ccabf3f30c 217 }
rba90 0:e2ccabf3f30c 218
rba90 10:065a4b58c6ff 219 Radio.Rx( 0 );
rba90 0:e2ccabf3f30c 220 State = LOWPOWER;
rba90 0:e2ccabf3f30c 221 break;
rba90 0:e2ccabf3f30c 222 }
rba90 0:e2ccabf3f30c 223 case TX:
rba90 0:e2ccabf3f30c 224 {
rba90 28:2c0e115b4f72 225 // set tx to done, allow next transmission
rba90 28:2c0e115b4f72 226 setTxDoneFlag();
rba90 28:2c0e115b4f72 227
rba90 10:065a4b58c6ff 228 Radio.Rx( 0 );
rba90 0:e2ccabf3f30c 229 State = LOWPOWER;
rba90 0:e2ccabf3f30c 230 break;
rba90 0:e2ccabf3f30c 231 }
rba90 0:e2ccabf3f30c 232 case RX_TIMEOUT:
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 RX_ERROR:
rba90 0:e2ccabf3f30c 239 {
rba90 10:065a4b58c6ff 240 Radio.Rx( 0 );
rba90 0:e2ccabf3f30c 241 State = LOWPOWER;
rba90 0:e2ccabf3f30c 242 break;
rba90 0:e2ccabf3f30c 243 }
rba90 0:e2ccabf3f30c 244 case TX_TIMEOUT:
rba90 0:e2ccabf3f30c 245 {
rba90 29:6c59b0bba861 246 // set tx to done, allow next transmission
rba90 29:6c59b0bba861 247 setTxDoneFlag();
rba90 29:6c59b0bba861 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 LOWPOWER:
rba90 0:e2ccabf3f30c 254 {
rba90 22:2e39f382f782 255 // transmit packet when the radio is free
rba90 28:2c0e115b4f72 256 if (getTxDoneFlag() && AlohaTxQueue.getCounter() > 0)
rba90 22:2e39f382f782 257 {
rba90 22:2e39f382f782 258 AlohaFrame *frame = AlohaTxQueue.dequeue();
rba90 22:2e39f382f782 259
rba90 22:2e39f382f782 260 // create a buffer for transmit
rba90 22:2e39f382f782 261 uint8_t frame_length = frame->getPayloadLength() + FIXED_BYTE;
rba90 22:2e39f382f782 262 uint8_t buffer[frame_length]; // 4 fix fields
rba90 22:2e39f382f782 263 memset(buffer, 0x0, sizeof(buffer));
rba90 22:2e39f382f782 264
rba90 22:2e39f382f782 265 // copy content to buffer
rba90 22:2e39f382f782 266 frame->serialize(buffer);
rba90 22:2e39f382f782 267
rba90 22:2e39f382f782 268 // send to radio
rba90 22:2e39f382f782 269 Radio.Send(buffer, frame_length);
rba90 22:2e39f382f782 270
rba90 28:2c0e115b4f72 271 // block the next transmission until previous transmission is done
rba90 28:2c0e115b4f72 272 clearTxDoneFlag();
rba90 28:2c0e115b4f72 273
rba90 22:2e39f382f782 274 // free memory
rba90 22:2e39f382f782 275 delete frame;
rba90 22:2e39f382f782 276 }
rba90 0:e2ccabf3f30c 277 break;
rba90 0:e2ccabf3f30c 278 }
rba90 0:e2ccabf3f30c 279 default:
rba90 0:e2ccabf3f30c 280 {
rba90 0:e2ccabf3f30c 281 State = LOWPOWER;
rba90 0:e2ccabf3f30c 282 break;
rba90 0:e2ccabf3f30c 283 }
rba90 0:e2ccabf3f30c 284 }
rba90 0:e2ccabf3f30c 285 }
rba90 0:e2ccabf3f30c 286
rba90 24:8f31c33c7675 287 bool AlohaTransceiver::send(BasicPacket *packet)
rba90 24:8f31c33c7675 288 {
rba90 24:8f31c33c7675 289 // for the reason that we only transmit basic packet format, the
rba90 24:8f31c33c7675 290 // length is always 8
rba90 24:8f31c33c7675 291 uint8_t payload_length = 8;
rba90 24:8f31c33c7675 292
rba90 24:8f31c33c7675 293 // get destination address
rba90 24:8f31c33c7675 294 uint8_t destination_address = findNextHop(packet->getDestinationID());
rba90 24:8f31c33c7675 295
rba90 24:8f31c33c7675 296 // serialize the packet from upper layer
rba90 24:8f31c33c7675 297 uint8_t buffer[payload_length];
rba90 24:8f31c33c7675 298 memset(buffer, 0x0, sizeof(buffer));
rba90 24:8f31c33c7675 299
rba90 24:8f31c33c7675 300 // copy bytes into buffer
rba90 24:8f31c33c7675 301 packet->serialize(buffer);
rba90 17:c6e2e2cd6e5f 302
rba90 17:c6e2e2cd6e5f 303 // create a new frame
rba90 22:2e39f382f782 304 AlohaFrame *frame = new AlohaFrame();
rba90 17:c6e2e2cd6e5f 305
rba90 22:2e39f382f782 306 // set properfies
rba90 24:8f31c33c7675 307 // set payload as data
rba90 22:2e39f382f782 308 frame->setType(AlohaFrame::Aloha_Data);
rba90 24:8f31c33c7675 309
rba90 24:8f31c33c7675 310 // set payload length (8 bytes for BasicPacket)
rba90 22:2e39f382f782 311 frame->setPayloadLength(payload_length);
rba90 24:8f31c33c7675 312
rba90 24:8f31c33c7675 313 // set mac layer device id
rba90 22:2e39f382f782 314 frame->setSourceAddress(deviceId);
rba90 24:8f31c33c7675 315
rba90 24:8f31c33c7675 316 // set mac layer destination id
rba90 24:8f31c33c7675 317 // for multiple hop system, the destination is the next hop
rba90 24:8f31c33c7675 318 // in this case, we use destination id from upper layer
rba90 24:8f31c33c7675 319 frame->setDestinationAddress(packet->getDestinationID());
rba90 24:8f31c33c7675 320
rba90 24:8f31c33c7675 321 // set full message flag (always true in this case)
rba90 22:2e39f382f782 322 frame->setFullMessageFlag(0x1);
rba90 22:2e39f382f782 323
rba90 24:8f31c33c7675 324 // use dest_addr as key for accessing sequence id
rba90 24:8f31c33c7675 325 // the seqid should increase as it successfully transmit the packet
rba90 24:8f31c33c7675 326 frame->setSequenceID(seqid[destination_address]++);
rba90 24:8f31c33c7675 327
rba90 22:2e39f382f782 328 // set payload
rba90 17:c6e2e2cd6e5f 329 for (uint8_t i = 0; i < payload_length; i++)
rba90 17:c6e2e2cd6e5f 330 {
rba90 24:8f31c33c7675 331 frame->setPayload(i, buffer[i]);
rba90 17:c6e2e2cd6e5f 332 }
rba90 17:c6e2e2cd6e5f 333
rba90 17:c6e2e2cd6e5f 334 // calculate crc
rba90 22:2e39f382f782 335 frame->generateCrc();
rba90 17:c6e2e2cd6e5f 336
rba90 22:2e39f382f782 337 // push frame to the back of queue
rba90 22:2e39f382f782 338 AlohaTxQueue.enqueue(frame);
rba90 27:463688e3bd12 339
rba90 27:463688e3bd12 340 // debug
rba90 27:463688e3bd12 341 #ifdef DEBUG_ALOHA
rba90 29:6c59b0bba861 342 printf("\r\nTXDATA::DEST_ADDR:0x%x,SEQID:0x%x\r\n", frame->getDestinationAddress(), frame->getSequenceID());
rba90 27:463688e3bd12 343 #endif
rba90 17:c6e2e2cd6e5f 344 return true;
rba90 0:e2ccabf3f30c 345 }
rba90 0:e2ccabf3f30c 346
rba90 25:bcd1cee4e5a8 347 void AlohaTransceiver::sendAck(AlohaFrame *inFrame)
rba90 25:bcd1cee4e5a8 348 {
rba90 25:bcd1cee4e5a8 349 // create a new frame by calling it's constructor
rba90 25:bcd1cee4e5a8 350 AlohaFrame *outFrame = new AlohaFrame();
rba90 25:bcd1cee4e5a8 351
rba90 25:bcd1cee4e5a8 352 // set frame type
rba90 25:bcd1cee4e5a8 353 outFrame->setType(AlohaFrame::Aloha_ACK);
rba90 25:bcd1cee4e5a8 354
rba90 25:bcd1cee4e5a8 355 // set payload length (0 byte payload for ack frame)
rba90 25:bcd1cee4e5a8 356 outFrame->setPayloadLength(0);
rba90 25:bcd1cee4e5a8 357
rba90 25:bcd1cee4e5a8 358 // set mac layer device id
rba90 25:bcd1cee4e5a8 359 outFrame->setSourceAddress(deviceId);
rba90 25:bcd1cee4e5a8 360
rba90 25:bcd1cee4e5a8 361 // set mac layer destination id
rba90 25:bcd1cee4e5a8 362 outFrame->setDestinationAddress(inFrame->getSourceAddress());
rba90 25:bcd1cee4e5a8 363
rba90 25:bcd1cee4e5a8 364 // set full message flag
rba90 25:bcd1cee4e5a8 365 outFrame->setFullMessageFlag(0x1);
rba90 25:bcd1cee4e5a8 366
rba90 25:bcd1cee4e5a8 367 // set seqid
rba90 25:bcd1cee4e5a8 368 // the sequence id is always the source id + 1
rba90 25:bcd1cee4e5a8 369 outFrame->setSequenceID(inFrame->getSequenceID() + 1);
rba90 25:bcd1cee4e5a8 370
rba90 25:bcd1cee4e5a8 371 // no payload
rba90 25:bcd1cee4e5a8 372
rba90 25:bcd1cee4e5a8 373 // generate cec
rba90 25:bcd1cee4e5a8 374 outFrame->generateCrc();
rba90 25:bcd1cee4e5a8 375
rba90 25:bcd1cee4e5a8 376 // push frame to the back of queue
rba90 25:bcd1cee4e5a8 377 AlohaTxQueue.enqueue(outFrame);
rba90 25:bcd1cee4e5a8 378
rba90 25:bcd1cee4e5a8 379 // debug
rba90 25:bcd1cee4e5a8 380 #ifdef DEBUG_ALOHA
rba90 29:6c59b0bba861 381 printf("\r\nTXACK::DEST_ADDR:0x%x,SEQID:0x%x\r\n", outFrame->getDestinationAddress(), outFrame->getSequenceID());
rba90 25:bcd1cee4e5a8 382 #endif
rba90 25:bcd1cee4e5a8 383 }
rba90 25:bcd1cee4e5a8 384
rba90 28:2c0e115b4f72 385 bool AlohaTransceiver::getTxDoneFlag()
rba90 28:2c0e115b4f72 386 {
rba90 28:2c0e115b4f72 387 return CHECK_FLAG(flags, 0);
rba90 28:2c0e115b4f72 388 }
rba90 28:2c0e115b4f72 389
rba90 28:2c0e115b4f72 390 void AlohaTransceiver::setTxDoneFlag()
rba90 28:2c0e115b4f72 391 {
rba90 28:2c0e115b4f72 392 SET_FLAG(flags, 0);
rba90 28:2c0e115b4f72 393 }
rba90 28:2c0e115b4f72 394
rba90 28:2c0e115b4f72 395 void AlohaTransceiver::clearTxDoneFlag()
rba90 28:2c0e115b4f72 396 {
rba90 28:2c0e115b4f72 397 CLEAR_FLAG(flags, 0);
rba90 28:2c0e115b4f72 398 }
rba90 28:2c0e115b4f72 399
rba90 0:e2ccabf3f30c 400 void AlohaTransceiver::registerType(AlohaFrame::AlohaType_t type, aloha_callback_func f)
rba90 0:e2ccabf3f30c 401 {
rba90 0:e2ccabf3f30c 402 AlohaTypeCallbackTable[type] = f;
rba90 0:e2ccabf3f30c 403 }
rba90 0:e2ccabf3f30c 404
rba90 0:e2ccabf3f30c 405 void AlohaTransceiver::deRegisterType(AlohaFrame::AlohaType_t type, aloha_callback_func f)
rba90 0:e2ccabf3f30c 406 {
rba90 0:e2ccabf3f30c 407 AlohaTypeCallbackTable[type] = NULL;
rba90 0:e2ccabf3f30c 408 }
rba90 0:e2ccabf3f30c 409
rba90 2:fa264e48d5f7 410 int16_t AlohaTransceiver::getRssi()
rba90 2:fa264e48d5f7 411 {
rba90 2:fa264e48d5f7 412 return RssiValue;
rba90 2:fa264e48d5f7 413 }
rba90 2:fa264e48d5f7 414
rba90 2:fa264e48d5f7 415 int8_t AlohaTransceiver::getSnr()
rba90 2:fa264e48d5f7 416 {
rba90 2:fa264e48d5f7 417 return SnrValue;
rba90 2:fa264e48d5f7 418 }
rba90 2:fa264e48d5f7 419
rba90 17:c6e2e2cd6e5f 420 uint8_t AlohaTransceiver::getDeviceID()
rba90 11:3e1ff29da71a 421 {
rba90 11:3e1ff29da71a 422 return deviceId;
rba90 11:3e1ff29da71a 423 }
rba90 11:3e1ff29da71a 424
rba90 17:c6e2e2cd6e5f 425 void AlohaTransceiver::setDeviceID(uint8_t id)
rba90 11:3e1ff29da71a 426 {
rba90 11:3e1ff29da71a 427 deviceId = id;
rba90 11:3e1ff29da71a 428 }
rba90 11:3e1ff29da71a 429
rba90 24:8f31c33c7675 430 uint8_t AlohaTransceiver::findNextHop(uint8_t addr)
rba90 24:8f31c33c7675 431 {
rba90 24:8f31c33c7675 432 // TODO: maintain a routing lookup table for choosing shortest path
rba90 24:8f31c33c7675 433 return addr;
rba90 24:8f31c33c7675 434 }
rba90 24:8f31c33c7675 435
rba90 8:4bda842f73d4 436 #if USE_MODEM_LORA == 1
rba90 8:4bda842f73d4 437 AlohaTransceiver::LoRaSettings_t *AlohaTransceiver::getSettings()
rba90 8:4bda842f73d4 438 {
rba90 8:4bda842f73d4 439 return &Settings;
rba90 8:4bda842f73d4 440 }
rba90 8:4bda842f73d4 441
rba90 8:4bda842f73d4 442 #elif USE_MODEM_FSK == 1
rba90 8:4bda842f73d4 443 AlohaTransceiver::FskSettings_t *AlohaTransceiver::getSettings()
rba90 8:4bda842f73d4 444 {
rba90 8:4bda842f73d4 445 return &Settings;
rba90 8:4bda842f73d4 446 }
rba90 8:4bda842f73d4 447 #else
rba90 8:4bda842f73d4 448 #error "Please define a modem in the compiler options."
rba90 8:4bda842f73d4 449 #endif
rba90 8:4bda842f73d4 450
rba90 0:e2ccabf3f30c 451 void OnTxDone( void )
rba90 0:e2ccabf3f30c 452 {
rba90 0:e2ccabf3f30c 453 Radio.Sleep( );
rba90 0:e2ccabf3f30c 454 State = TX;
rba90 18:3e6483550f25 455
rba90 18:3e6483550f25 456 #ifdef DEBUG_ALOHA
rba90 28:2c0e115b4f72 457 debug_if(ALLOW_CALLBACK_DEBUG, "> OnTxDone\n\r" );
rba90 18:3e6483550f25 458 #endif
rba90 0:e2ccabf3f30c 459 }
rba90 0:e2ccabf3f30c 460
rba90 0:e2ccabf3f30c 461 void OnRxDone( uint8_t *payload, uint16_t size, int16_t rssi, int8_t snr)
rba90 0:e2ccabf3f30c 462 {
rba90 27:463688e3bd12 463 uint8_t payload_length;
rba90 27:463688e3bd12 464
rba90 0:e2ccabf3f30c 465 Radio.Sleep( );
rba90 0:e2ccabf3f30c 466
rba90 0:e2ccabf3f30c 467 // safeguard: if size exceeded maximum buffer size, it will cause memory overflow
rba90 27:463688e3bd12 468 payload_length = size ? BUFFER_SIZE : size <= BUFFER_SIZE;
rba90 27:463688e3bd12 469
rba90 27:463688e3bd12 470 // create a new frame instance
rba90 27:463688e3bd12 471 AlohaFrame *frame = new AlohaFrame(payload, payload_length);
rba90 27:463688e3bd12 472
rba90 27:463688e3bd12 473 // push onto the end of queue
rba90 27:463688e3bd12 474 AlohaRxQueue.enqueue(frame);
rba90 0:e2ccabf3f30c 475
rba90 0:e2ccabf3f30c 476 RssiValue = rssi;
rba90 0:e2ccabf3f30c 477 SnrValue = snr;
rba90 0:e2ccabf3f30c 478 State = RX;
rba90 18:3e6483550f25 479
rba90 18:3e6483550f25 480 #ifdef DEBUG_ALOHA
rba90 28:2c0e115b4f72 481 debug_if(ALLOW_CALLBACK_DEBUG, "> OnRxDone\n\r" );
rba90 18:3e6483550f25 482 #endif
rba90 0:e2ccabf3f30c 483 }
rba90 0:e2ccabf3f30c 484
rba90 0:e2ccabf3f30c 485 void OnTxTimeout( void )
rba90 0:e2ccabf3f30c 486 {
rba90 0:e2ccabf3f30c 487 Radio.Sleep( );
rba90 0:e2ccabf3f30c 488 State = TX_TIMEOUT;
rba90 18:3e6483550f25 489
rba90 18:3e6483550f25 490 #ifdef DEBUG_ALOHA
rba90 28:2c0e115b4f72 491 debug_if(ALLOW_CALLBACK_DEBUG, "> OnTxTimeout\n\r" );
rba90 18:3e6483550f25 492 #endif
rba90 0:e2ccabf3f30c 493 }
rba90 0:e2ccabf3f30c 494
rba90 0:e2ccabf3f30c 495 void OnRxTimeout( void )
rba90 0:e2ccabf3f30c 496 {
rba90 0:e2ccabf3f30c 497 Radio.Sleep( );
rba90 0:e2ccabf3f30c 498 State = RX_TIMEOUT;
rba90 18:3e6483550f25 499
rba90 18:3e6483550f25 500 #ifdef DEBUG_ALOHA
rba90 28:2c0e115b4f72 501 debug_if(ALLOW_CALLBACK_DEBUG, "> OnRxTimeout\n\r" );
rba90 18:3e6483550f25 502 #endif
rba90 0:e2ccabf3f30c 503 }
rba90 0:e2ccabf3f30c 504
rba90 0:e2ccabf3f30c 505 void OnRxError( void )
rba90 0:e2ccabf3f30c 506 {
rba90 0:e2ccabf3f30c 507 Radio.Sleep( );
rba90 0:e2ccabf3f30c 508 State = RX_ERROR;
rba90 18:3e6483550f25 509
rba90 18:3e6483550f25 510 #ifdef DEBUG_ALOHA
rba90 28:2c0e115b4f72 511 debug_if(ALLOW_CALLBACK_DEBUG, "> OnRxError\n\r" );
rba90 18:3e6483550f25 512 #endif
rba90 0:e2ccabf3f30c 513 }
rba90 24:8f31c33c7675 514