Wireless interface using LoRa technology

Dependencies:   AlohaTransceiver RingBuffer SX1276Lib_inAir SerialInterfaceProtocol mbed L3PDU

Committer:
rba90
Date:
Sun Jul 17 11:29:51 2016 +0000
Revision:
4:9151697dfa70
Parent:
3:7bb50ee42cba
Child:
8:e30610bf6f79
add comments for function

Who changed what in which revision?

UserRevisionLine numberNew contents of line
rba90 0:7d8e24cb62c1 1 #include "mbed.h"
rba90 0:7d8e24cb62c1 2 #include "AlohaTransceiver.h"
rba90 0:7d8e24cb62c1 3 #include "buffer.h"
rba90 0:7d8e24cb62c1 4 #include "SerialInterfaceProtocol.h"
rba90 0:7d8e24cb62c1 5 #include "AlohaFrame.h"
rba90 0:7d8e24cb62c1 6
rba90 0:7d8e24cb62c1 7 Serial pc(USBTX, USBRX);
rba90 0:7d8e24cb62c1 8
rba90 0:7d8e24cb62c1 9 // sip uses two buffer queues
rba90 0:7d8e24cb62c1 10 CircularBuffer<uint8_t> SerialInputBuffer;
rba90 0:7d8e24cb62c1 11 CircularBuffer<uint8_t> SerialOutputBuffer;
rba90 0:7d8e24cb62c1 12 SerialInterfaceProtocol SIP(&SerialInputBuffer, &SerialOutputBuffer);
rba90 0:7d8e24cb62c1 13
rba90 0:7d8e24cb62c1 14 // aloha transceiver
rba90 0:7d8e24cb62c1 15 AlohaTransceiver aloha;
rba90 0:7d8e24cb62c1 16 AlohaFrame txFrame;
rba90 1:101cf4fca4e5 17 Timer timer;
rba90 2:5a74ae8be594 18 InterruptIn button(USER_BUTTON);
rba90 0:7d8e24cb62c1 19
rba90 0:7d8e24cb62c1 20 void serialInterruptHandler() {
rba90 0:7d8e24cb62c1 21 // Note: you need to actually read from the serial to clear the RX interrupt
rba90 0:7d8e24cb62c1 22 int c = pc.getc();
rba90 0:7d8e24cb62c1 23
rba90 0:7d8e24cb62c1 24 // add to buffer
rba90 0:7d8e24cb62c1 25 if (SerialInputBuffer.isLocked())
rba90 0:7d8e24cb62c1 26 {
rba90 0:7d8e24cb62c1 27 printf("Mutex Locked\r\n");
rba90 0:7d8e24cb62c1 28 }
rba90 0:7d8e24cb62c1 29 else
rba90 0:7d8e24cb62c1 30 {
rba90 0:7d8e24cb62c1 31 SerialInputBuffer.enqueue((uint8_t) c);
rba90 0:7d8e24cb62c1 32 }
rba90 0:7d8e24cb62c1 33 }
rba90 0:7d8e24cb62c1 34
rba90 0:7d8e24cb62c1 35 int toggleChecksum(uint8_t *payload, uint8_t payload_length, uint8_t *response, uint8_t *response_length)
rba90 0:7d8e24cb62c1 36 {
rba90 0:7d8e24cb62c1 37 // one payload
rba90 0:7d8e24cb62c1 38 if (payload_length != 1)
rba90 0:7d8e24cb62c1 39 {
rba90 0:7d8e24cb62c1 40 sprintf((char *) response, "Wrong Payload Length\r\n");
rba90 0:7d8e24cb62c1 41 *response_length = 22;
rba90 0:7d8e24cb62c1 42 return 1;
rba90 0:7d8e24cb62c1 43 }
rba90 0:7d8e24cb62c1 44
rba90 0:7d8e24cb62c1 45 if ((bool) payload[0])
rba90 0:7d8e24cb62c1 46 {
rba90 0:7d8e24cb62c1 47 SIP.enableChecksum();
rba90 0:7d8e24cb62c1 48 }
rba90 0:7d8e24cb62c1 49 else
rba90 0:7d8e24cb62c1 50 {
rba90 0:7d8e24cb62c1 51 SIP.disableChecksum();
rba90 0:7d8e24cb62c1 52 }
rba90 0:7d8e24cb62c1 53
rba90 0:7d8e24cb62c1 54 return 0;
rba90 0:7d8e24cb62c1 55 }
rba90 0:7d8e24cb62c1 56
rba90 1:101cf4fca4e5 57 int sendMessage(uint8_t *payload, uint8_t payload_length, uint8_t *response, uint8_t *response_length)
rba90 1:101cf4fca4e5 58 {
rba90 1:101cf4fca4e5 59 static uint8_t seqid = 0;
rba90 1:101cf4fca4e5 60
rba90 1:101cf4fca4e5 61 // prepare for the frame
rba90 1:101cf4fca4e5 62 txFrame.setType(AlohaFrame::Aloha_Data);
rba90 1:101cf4fca4e5 63 txFrame.setPayloadLength(0x0);
rba90 1:101cf4fca4e5 64 txFrame.setSourceAddress(0x1);
rba90 1:101cf4fca4e5 65 txFrame.setDestinationAddress(0x2);
rba90 1:101cf4fca4e5 66 txFrame.setFullMessageFlag(0x1);
rba90 1:101cf4fca4e5 67 txFrame.setSequenceID(seqid);
rba90 1:101cf4fca4e5 68 txFrame.generateCrc();
rba90 1:101cf4fca4e5 69
rba90 1:101cf4fca4e5 70
rba90 1:101cf4fca4e5 71 uint8_t buffer[20];
rba90 1:101cf4fca4e5 72 memset(buffer, 0x0, sizeof(buffer));
rba90 1:101cf4fca4e5 73 txFrame.serialize(buffer);
rba90 1:101cf4fca4e5 74
rba90 3:7bb50ee42cba 75 aloha.send(buffer, 20);
rba90 1:101cf4fca4e5 76
rba90 3:7bb50ee42cba 77 seqid += 1;
rba90 1:101cf4fca4e5 78
rba90 1:101cf4fca4e5 79 // start the timer to measure round trip time
rba90 1:101cf4fca4e5 80 timer.reset();
rba90 1:101cf4fca4e5 81 timer.start();
rba90 1:101cf4fca4e5 82
rba90 3:7bb50ee42cba 83 return 0;
rba90 3:7bb50ee42cba 84 }
rba90 3:7bb50ee42cba 85
rba90 4:9151697dfa70 86 /*
rba90 4:9151697dfa70 87 * Format:
rba90 4:9151697dfa70 88 * < :start flag
rba90 4:9151697dfa70 89 * 02 :command
rba90 4:9151697dfa70 90 * xx :length
rba90 4:9151697dfa70 91 * xx: :00: get, 01: set
rba90 4:9151697dfa70 92 * xx :index for parameters
rba90 4:9151697dfa70 93 * ...
rba90 4:9151697dfa70 94 * ff :checksum
rba90 4:9151697dfa70 95 * > :end flag
rba90 4:9151697dfa70 96 */
rba90 3:7bb50ee42cba 97 int configureRadio(uint8_t *payload, uint8_t payload_length, uint8_t *response, uint8_t *response_length)
rba90 3:7bb50ee42cba 98 {
rba90 3:7bb50ee42cba 99 // read settings from radio
rba90 3:7bb50ee42cba 100 #if USE_MODEM_LORA == 1
rba90 3:7bb50ee42cba 101 AlohaTransceiver::LoRaSettings_t *settings = aloha.getSettings();
rba90 3:7bb50ee42cba 102 #elif USE_MODEM_FSK == 1
rba90 3:7bb50ee42cba 103 AlohaTransceiver::FskSettings_t *settings = aloha.getSettings();
rba90 3:7bb50ee42cba 104 #else
rba90 3:7bb50ee42cba 105 #error "Please define a modem in the compiler options."
rba90 3:7bb50ee42cba 106 #endif
rba90 3:7bb50ee42cba 107
rba90 3:7bb50ee42cba 108 if (payload_length < 2)
rba90 3:7bb50ee42cba 109 {
rba90 3:7bb50ee42cba 110 sprintf((char *) response, "Wrong Payload Length\r\n");
rba90 3:7bb50ee42cba 111 *response_length = 22;
rba90 3:7bb50ee42cba 112 return 1;
rba90 3:7bb50ee42cba 113 }
rba90 3:7bb50ee42cba 114
rba90 3:7bb50ee42cba 115 // true is set, false is get
rba90 3:7bb50ee42cba 116 bool isSet = (bool) payload[0];
rba90 3:7bb50ee42cba 117 uint8_t idx = payload[1];
rba90 3:7bb50ee42cba 118
rba90 3:7bb50ee42cba 119 switch(idx)
rba90 3:7bb50ee42cba 120 {
rba90 3:7bb50ee42cba 121 case 0x00: // Power
rba90 3:7bb50ee42cba 122 {
rba90 3:7bb50ee42cba 123 if (isSet)
rba90 3:7bb50ee42cba 124 {
rba90 3:7bb50ee42cba 125 int8_t Power = (int8_t) payload[2];
rba90 3:7bb50ee42cba 126 settings->Power = Power;
rba90 3:7bb50ee42cba 127
rba90 3:7bb50ee42cba 128 return 0;
rba90 3:7bb50ee42cba 129 }
rba90 3:7bb50ee42cba 130 else
rba90 3:7bb50ee42cba 131 {
rba90 3:7bb50ee42cba 132 response[0] = (uint8_t) settings->Power;
rba90 3:7bb50ee42cba 133 *response_length = 1;
rba90 1:101cf4fca4e5 134
rba90 3:7bb50ee42cba 135 return 0;
rba90 3:7bb50ee42cba 136 }
rba90 3:7bb50ee42cba 137 }
rba90 3:7bb50ee42cba 138
rba90 3:7bb50ee42cba 139 case 0x01: // Bandwidth
rba90 3:7bb50ee42cba 140 {
rba90 3:7bb50ee42cba 141 if (isSet)
rba90 3:7bb50ee42cba 142 {
rba90 3:7bb50ee42cba 143 uint32_t Bandwidth = (payload[4]) |
rba90 3:7bb50ee42cba 144 (payload[3] << 8) |
rba90 3:7bb50ee42cba 145 (payload[2] << 16) |
rba90 3:7bb50ee42cba 146 (payload[1] << 24);
rba90 3:7bb50ee42cba 147 settings->Bandwidth = Bandwidth;
rba90 3:7bb50ee42cba 148
rba90 3:7bb50ee42cba 149 return 0;
rba90 3:7bb50ee42cba 150 }
rba90 3:7bb50ee42cba 151 else
rba90 3:7bb50ee42cba 152 {
rba90 3:7bb50ee42cba 153 response[3] = (uint8_t) (settings->Bandwidth);
rba90 3:7bb50ee42cba 154 response[2] = (uint8_t) (settings->Bandwidth >> 8);
rba90 3:7bb50ee42cba 155 response[1] = (uint8_t) (settings->Bandwidth >> 16);
rba90 3:7bb50ee42cba 156 response[0] = (uint8_t) (settings->Bandwidth >> 24);
rba90 3:7bb50ee42cba 157 *response_length = 4;
rba90 3:7bb50ee42cba 158
rba90 3:7bb50ee42cba 159 return 0;
rba90 3:7bb50ee42cba 160 }
rba90 3:7bb50ee42cba 161
rba90 3:7bb50ee42cba 162 }
rba90 3:7bb50ee42cba 163
rba90 3:7bb50ee42cba 164 case 0x02: // Daterate
rba90 3:7bb50ee42cba 165 {
rba90 3:7bb50ee42cba 166 if (isSet)
rba90 3:7bb50ee42cba 167 {
rba90 3:7bb50ee42cba 168 uint32_t Datarate = (payload[4]) |
rba90 3:7bb50ee42cba 169 (payload[3] << 8) |
rba90 3:7bb50ee42cba 170 (payload[2] << 16) |
rba90 3:7bb50ee42cba 171 (payload[1] << 24);
rba90 3:7bb50ee42cba 172 settings->Datarate = Datarate;
rba90 3:7bb50ee42cba 173
rba90 3:7bb50ee42cba 174 return 0;
rba90 3:7bb50ee42cba 175 }
rba90 3:7bb50ee42cba 176 else
rba90 3:7bb50ee42cba 177 {
rba90 3:7bb50ee42cba 178 response[3] = (uint8_t) (settings->Datarate);
rba90 3:7bb50ee42cba 179 response[2] = (uint8_t) (settings->Datarate >> 8);
rba90 3:7bb50ee42cba 180 response[1] = (uint8_t) (settings->Datarate >> 16);
rba90 3:7bb50ee42cba 181 response[0] = (uint8_t) (settings->Datarate >> 24);
rba90 3:7bb50ee42cba 182 *response_length = 4;
rba90 3:7bb50ee42cba 183
rba90 3:7bb50ee42cba 184 return 0;
rba90 3:7bb50ee42cba 185 }
rba90 3:7bb50ee42cba 186 }
rba90 3:7bb50ee42cba 187
rba90 3:7bb50ee42cba 188 case 0x03: // Coderate
rba90 3:7bb50ee42cba 189 {
rba90 3:7bb50ee42cba 190 if (isSet)
rba90 3:7bb50ee42cba 191 {
rba90 3:7bb50ee42cba 192 uint8_t Coderate = payload[1];
rba90 3:7bb50ee42cba 193 settings->Coderate = Coderate;
rba90 3:7bb50ee42cba 194
rba90 3:7bb50ee42cba 195 return 0;
rba90 3:7bb50ee42cba 196 }
rba90 3:7bb50ee42cba 197 else
rba90 3:7bb50ee42cba 198 {
rba90 3:7bb50ee42cba 199 response[0] = (uint8_t) settings->Coderate;
rba90 3:7bb50ee42cba 200 *response_length = 1;
rba90 3:7bb50ee42cba 201
rba90 3:7bb50ee42cba 202 return 0;
rba90 3:7bb50ee42cba 203 }
rba90 3:7bb50ee42cba 204 }
rba90 3:7bb50ee42cba 205
rba90 3:7bb50ee42cba 206 default:
rba90 3:7bb50ee42cba 207 {
rba90 3:7bb50ee42cba 208 break;
rba90 3:7bb50ee42cba 209 }
rba90 3:7bb50ee42cba 210 }
rba90 3:7bb50ee42cba 211
rba90 3:7bb50ee42cba 212
rba90 3:7bb50ee42cba 213 return 0;
rba90 1:101cf4fca4e5 214 }
rba90 1:101cf4fca4e5 215
rba90 1:101cf4fca4e5 216 void AlohaDataHandler(AlohaFrame *frame)
rba90 1:101cf4fca4e5 217 {
rba90 1:101cf4fca4e5 218 // stop the timer to measure round trip time
rba90 1:101cf4fca4e5 219 timer.stop();
rba90 1:101cf4fca4e5 220
rba90 2:5a74ae8be594 221 printf("-----------------------------------------\r\n");
rba90 2:5a74ae8be594 222 printf(">Received Frame\r\n");
rba90 2:5a74ae8be594 223 printf("> Type: 0x%x, PayloadLength: 0x%x\r\n", frame->getType(), frame->getPayloadLength());
rba90 2:5a74ae8be594 224 printf("> SrcAddr: 0x%x, DestAddr: 0x%x\r\n", frame->getSourceAddress(), frame->getDestinationAddress());
rba90 2:5a74ae8be594 225 printf("> FMF: 0x%x, SequenceID: 0x%x\r\n", frame->getFullMessageFlag(), frame->getSequenceID());
rba90 0:7d8e24cb62c1 226 for (uint8_t i = 0; i < frame->getPayloadLength(); i++)
rba90 0:7d8e24cb62c1 227 {
rba90 2:5a74ae8be594 228 printf("> Payload[%d]: 0x%x\r\n", i, frame->getPayload(i));
rba90 0:7d8e24cb62c1 229 }
rba90 2:5a74ae8be594 230 printf("> CRC: 0x%x\r\n", frame->getCrc());
rba90 0:7d8e24cb62c1 231
rba90 1:101cf4fca4e5 232 // decode payload (range test only)
rba90 1:101cf4fca4e5 233 int8_t snr = (int8_t) frame->getPayload(0);
rba90 1:101cf4fca4e5 234
rba90 1:101cf4fca4e5 235 uint16_t rssi_h = frame->getPayload(1);
rba90 1:101cf4fca4e5 236 uint8_t rssi_l = frame->getPayload(2);
rba90 1:101cf4fca4e5 237 int16_t rssi = (int16_t) (rssi_h << 8 | rssi_l);
rba90 0:7d8e24cb62c1 238
rba90 0:7d8e24cb62c1 239
rba90 3:7bb50ee42cba 240 printf(">About this transmission:\r\n");
rba90 3:7bb50ee42cba 241 printf("> Base Station:: Rssi: %d, Snr: %d\r\n", rssi, snr);
rba90 3:7bb50ee42cba 242 printf("> Terminal:: Rssi: %d, Snr: %d\r\n", aloha.getRssi(), aloha.getSnr());
rba90 2:5a74ae8be594 243 printf("> Round trip time: %d ms\r\n", timer.read_ms());
rba90 2:5a74ae8be594 244 printf("-----------------------------------------\r\n");
rba90 0:7d8e24cb62c1 245 }
rba90 0:7d8e24cb62c1 246
rba90 2:5a74ae8be594 247 void automaticPacketTransmit()
rba90 2:5a74ae8be594 248 {
rba90 2:5a74ae8be594 249 SerialInputBuffer.enqueue((uint8_t) '<');
rba90 2:5a74ae8be594 250 SerialInputBuffer.enqueue((uint8_t) '0');
rba90 2:5a74ae8be594 251 SerialInputBuffer.enqueue((uint8_t) '1');
rba90 2:5a74ae8be594 252 SerialInputBuffer.enqueue((uint8_t) '0');
rba90 2:5a74ae8be594 253 SerialInputBuffer.enqueue((uint8_t) '0');
rba90 2:5a74ae8be594 254 SerialInputBuffer.enqueue((uint8_t) 'f');
rba90 2:5a74ae8be594 255 SerialInputBuffer.enqueue((uint8_t) 'f');
rba90 2:5a74ae8be594 256 SerialInputBuffer.enqueue((uint8_t) '>');
rba90 2:5a74ae8be594 257 }
rba90 2:5a74ae8be594 258
rba90 2:5a74ae8be594 259
rba90 0:7d8e24cb62c1 260 int main() {
rba90 0:7d8e24cb62c1 261 // initialize radio module
rba90 3:7bb50ee42cba 262 aloha.boardInit();
rba90 3:7bb50ee42cba 263 aloha.updateSettings();
rba90 3:7bb50ee42cba 264 aloha.enable();
rba90 0:7d8e24cb62c1 265
rba90 0:7d8e24cb62c1 266 // attach serial interrupt handler
rba90 0:7d8e24cb62c1 267 pc.attach(&serialInterruptHandler);
rba90 0:7d8e24cb62c1 268
rba90 0:7d8e24cb62c1 269 // register callback functions for SIP
rba90 0:7d8e24cb62c1 270 SIP.registerCommand(0x00, toggleChecksum);
rba90 1:101cf4fca4e5 271 SIP.registerCommand(0x01, sendMessage);
rba90 3:7bb50ee42cba 272 SIP.registerCommand(0x02, configureRadio);
rba90 0:7d8e24cb62c1 273
rba90 0:7d8e24cb62c1 274 // register callback functions for aloha transceiver
rba90 1:101cf4fca4e5 275 aloha.registerType(AlohaFrame::Aloha_Data, AlohaDataHandler);
rba90 2:5a74ae8be594 276
rba90 2:5a74ae8be594 277 // configure button interrupt
rba90 2:5a74ae8be594 278 button.fall(automaticPacketTransmit);
rba90 0:7d8e24cb62c1 279
rba90 0:7d8e24cb62c1 280 while(1) {
rba90 0:7d8e24cb62c1 281 SIP.poll();
rba90 0:7d8e24cb62c1 282 aloha.poll();
rba90 0:7d8e24cb62c1 283
rba90 0:7d8e24cb62c1 284 while (SerialOutputBuffer.getCounter() > 0)
rba90 0:7d8e24cb62c1 285 {
rba90 0:7d8e24cb62c1 286 uint8_t ch;
rba90 0:7d8e24cb62c1 287 ch = SerialOutputBuffer.dequeue();
rba90 0:7d8e24cb62c1 288 pc.putc(ch);
rba90 0:7d8e24cb62c1 289 }
rba90 0:7d8e24cb62c1 290 }
rba90 0:7d8e24cb62c1 291 }