Wireless interface using LoRa technology

Dependencies:   AlohaTransceiver RingBuffer SX1276Lib_inAir SerialInterfaceProtocol mbed L3PDU

Committer:
rba90
Date:
Sun Jul 17 11:24:04 2016 +0000
Revision:
3:7bb50ee42cba
Parent:
2:5a74ae8be594
Child:
4:9151697dfa70
configure radio on the fly (unfinished)

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 3:7bb50ee42cba 86 int configureRadio(uint8_t *payload, uint8_t payload_length, uint8_t *response, uint8_t *response_length)
rba90 3:7bb50ee42cba 87 {
rba90 3:7bb50ee42cba 88 // read settings from radio
rba90 3:7bb50ee42cba 89 #if USE_MODEM_LORA == 1
rba90 3:7bb50ee42cba 90 AlohaTransceiver::LoRaSettings_t *settings = aloha.getSettings();
rba90 3:7bb50ee42cba 91 #elif USE_MODEM_FSK == 1
rba90 3:7bb50ee42cba 92 AlohaTransceiver::FskSettings_t *settings = aloha.getSettings();
rba90 3:7bb50ee42cba 93 #else
rba90 3:7bb50ee42cba 94 #error "Please define a modem in the compiler options."
rba90 3:7bb50ee42cba 95 #endif
rba90 3:7bb50ee42cba 96
rba90 3:7bb50ee42cba 97 if (payload_length < 2)
rba90 3:7bb50ee42cba 98 {
rba90 3:7bb50ee42cba 99 sprintf((char *) response, "Wrong Payload Length\r\n");
rba90 3:7bb50ee42cba 100 *response_length = 22;
rba90 3:7bb50ee42cba 101 return 1;
rba90 3:7bb50ee42cba 102 }
rba90 3:7bb50ee42cba 103
rba90 3:7bb50ee42cba 104 // true is set, false is get
rba90 3:7bb50ee42cba 105 bool isSet = (bool) payload[0];
rba90 3:7bb50ee42cba 106 uint8_t idx = payload[1];
rba90 3:7bb50ee42cba 107
rba90 3:7bb50ee42cba 108 switch(idx)
rba90 3:7bb50ee42cba 109 {
rba90 3:7bb50ee42cba 110 case 0x00: // Power
rba90 3:7bb50ee42cba 111 {
rba90 3:7bb50ee42cba 112 if (isSet)
rba90 3:7bb50ee42cba 113 {
rba90 3:7bb50ee42cba 114 int8_t Power = (int8_t) payload[2];
rba90 3:7bb50ee42cba 115 settings->Power = Power;
rba90 3:7bb50ee42cba 116
rba90 3:7bb50ee42cba 117 return 0;
rba90 3:7bb50ee42cba 118 }
rba90 3:7bb50ee42cba 119 else
rba90 3:7bb50ee42cba 120 {
rba90 3:7bb50ee42cba 121 response[0] = (uint8_t) settings->Power;
rba90 3:7bb50ee42cba 122 *response_length = 1;
rba90 1:101cf4fca4e5 123
rba90 3:7bb50ee42cba 124 return 0;
rba90 3:7bb50ee42cba 125 }
rba90 3:7bb50ee42cba 126 }
rba90 3:7bb50ee42cba 127
rba90 3:7bb50ee42cba 128 case 0x01: // Bandwidth
rba90 3:7bb50ee42cba 129 {
rba90 3:7bb50ee42cba 130 if (isSet)
rba90 3:7bb50ee42cba 131 {
rba90 3:7bb50ee42cba 132 uint32_t Bandwidth = (payload[4]) |
rba90 3:7bb50ee42cba 133 (payload[3] << 8) |
rba90 3:7bb50ee42cba 134 (payload[2] << 16) |
rba90 3:7bb50ee42cba 135 (payload[1] << 24);
rba90 3:7bb50ee42cba 136 settings->Bandwidth = Bandwidth;
rba90 3:7bb50ee42cba 137
rba90 3:7bb50ee42cba 138 return 0;
rba90 3:7bb50ee42cba 139 }
rba90 3:7bb50ee42cba 140 else
rba90 3:7bb50ee42cba 141 {
rba90 3:7bb50ee42cba 142 response[3] = (uint8_t) (settings->Bandwidth);
rba90 3:7bb50ee42cba 143 response[2] = (uint8_t) (settings->Bandwidth >> 8);
rba90 3:7bb50ee42cba 144 response[1] = (uint8_t) (settings->Bandwidth >> 16);
rba90 3:7bb50ee42cba 145 response[0] = (uint8_t) (settings->Bandwidth >> 24);
rba90 3:7bb50ee42cba 146 *response_length = 4;
rba90 3:7bb50ee42cba 147
rba90 3:7bb50ee42cba 148 return 0;
rba90 3:7bb50ee42cba 149 }
rba90 3:7bb50ee42cba 150
rba90 3:7bb50ee42cba 151 }
rba90 3:7bb50ee42cba 152
rba90 3:7bb50ee42cba 153 case 0x02: // Daterate
rba90 3:7bb50ee42cba 154 {
rba90 3:7bb50ee42cba 155 if (isSet)
rba90 3:7bb50ee42cba 156 {
rba90 3:7bb50ee42cba 157 uint32_t Datarate = (payload[4]) |
rba90 3:7bb50ee42cba 158 (payload[3] << 8) |
rba90 3:7bb50ee42cba 159 (payload[2] << 16) |
rba90 3:7bb50ee42cba 160 (payload[1] << 24);
rba90 3:7bb50ee42cba 161 settings->Datarate = Datarate;
rba90 3:7bb50ee42cba 162
rba90 3:7bb50ee42cba 163 return 0;
rba90 3:7bb50ee42cba 164 }
rba90 3:7bb50ee42cba 165 else
rba90 3:7bb50ee42cba 166 {
rba90 3:7bb50ee42cba 167 response[3] = (uint8_t) (settings->Datarate);
rba90 3:7bb50ee42cba 168 response[2] = (uint8_t) (settings->Datarate >> 8);
rba90 3:7bb50ee42cba 169 response[1] = (uint8_t) (settings->Datarate >> 16);
rba90 3:7bb50ee42cba 170 response[0] = (uint8_t) (settings->Datarate >> 24);
rba90 3:7bb50ee42cba 171 *response_length = 4;
rba90 3:7bb50ee42cba 172
rba90 3:7bb50ee42cba 173 return 0;
rba90 3:7bb50ee42cba 174 }
rba90 3:7bb50ee42cba 175 }
rba90 3:7bb50ee42cba 176
rba90 3:7bb50ee42cba 177 case 0x03: // Coderate
rba90 3:7bb50ee42cba 178 {
rba90 3:7bb50ee42cba 179 if (isSet)
rba90 3:7bb50ee42cba 180 {
rba90 3:7bb50ee42cba 181 uint8_t Coderate = payload[1];
rba90 3:7bb50ee42cba 182 settings->Coderate = Coderate;
rba90 3:7bb50ee42cba 183
rba90 3:7bb50ee42cba 184 return 0;
rba90 3:7bb50ee42cba 185 }
rba90 3:7bb50ee42cba 186 else
rba90 3:7bb50ee42cba 187 {
rba90 3:7bb50ee42cba 188 response[0] = (uint8_t) settings->Coderate;
rba90 3:7bb50ee42cba 189 *response_length = 1;
rba90 3:7bb50ee42cba 190
rba90 3:7bb50ee42cba 191 return 0;
rba90 3:7bb50ee42cba 192 }
rba90 3:7bb50ee42cba 193 }
rba90 3:7bb50ee42cba 194
rba90 3:7bb50ee42cba 195 default:
rba90 3:7bb50ee42cba 196 {
rba90 3:7bb50ee42cba 197 break;
rba90 3:7bb50ee42cba 198 }
rba90 3:7bb50ee42cba 199 }
rba90 3:7bb50ee42cba 200
rba90 3:7bb50ee42cba 201
rba90 3:7bb50ee42cba 202 return 0;
rba90 1:101cf4fca4e5 203 }
rba90 1:101cf4fca4e5 204
rba90 1:101cf4fca4e5 205 void AlohaDataHandler(AlohaFrame *frame)
rba90 1:101cf4fca4e5 206 {
rba90 1:101cf4fca4e5 207 // stop the timer to measure round trip time
rba90 1:101cf4fca4e5 208 timer.stop();
rba90 1:101cf4fca4e5 209
rba90 2:5a74ae8be594 210 printf("-----------------------------------------\r\n");
rba90 2:5a74ae8be594 211 printf(">Received Frame\r\n");
rba90 2:5a74ae8be594 212 printf("> Type: 0x%x, PayloadLength: 0x%x\r\n", frame->getType(), frame->getPayloadLength());
rba90 2:5a74ae8be594 213 printf("> SrcAddr: 0x%x, DestAddr: 0x%x\r\n", frame->getSourceAddress(), frame->getDestinationAddress());
rba90 2:5a74ae8be594 214 printf("> FMF: 0x%x, SequenceID: 0x%x\r\n", frame->getFullMessageFlag(), frame->getSequenceID());
rba90 0:7d8e24cb62c1 215 for (uint8_t i = 0; i < frame->getPayloadLength(); i++)
rba90 0:7d8e24cb62c1 216 {
rba90 2:5a74ae8be594 217 printf("> Payload[%d]: 0x%x\r\n", i, frame->getPayload(i));
rba90 0:7d8e24cb62c1 218 }
rba90 2:5a74ae8be594 219 printf("> CRC: 0x%x\r\n", frame->getCrc());
rba90 0:7d8e24cb62c1 220
rba90 1:101cf4fca4e5 221 // decode payload (range test only)
rba90 1:101cf4fca4e5 222 int8_t snr = (int8_t) frame->getPayload(0);
rba90 1:101cf4fca4e5 223
rba90 1:101cf4fca4e5 224 uint16_t rssi_h = frame->getPayload(1);
rba90 1:101cf4fca4e5 225 uint8_t rssi_l = frame->getPayload(2);
rba90 1:101cf4fca4e5 226 int16_t rssi = (int16_t) (rssi_h << 8 | rssi_l);
rba90 0:7d8e24cb62c1 227
rba90 0:7d8e24cb62c1 228
rba90 3:7bb50ee42cba 229 printf(">About this transmission:\r\n");
rba90 3:7bb50ee42cba 230 printf("> Base Station:: Rssi: %d, Snr: %d\r\n", rssi, snr);
rba90 3:7bb50ee42cba 231 printf("> Terminal:: Rssi: %d, Snr: %d\r\n", aloha.getRssi(), aloha.getSnr());
rba90 2:5a74ae8be594 232 printf("> Round trip time: %d ms\r\n", timer.read_ms());
rba90 2:5a74ae8be594 233 printf("-----------------------------------------\r\n");
rba90 0:7d8e24cb62c1 234 }
rba90 0:7d8e24cb62c1 235
rba90 2:5a74ae8be594 236 void automaticPacketTransmit()
rba90 2:5a74ae8be594 237 {
rba90 2:5a74ae8be594 238 SerialInputBuffer.enqueue((uint8_t) '<');
rba90 2:5a74ae8be594 239 SerialInputBuffer.enqueue((uint8_t) '0');
rba90 2:5a74ae8be594 240 SerialInputBuffer.enqueue((uint8_t) '1');
rba90 2:5a74ae8be594 241 SerialInputBuffer.enqueue((uint8_t) '0');
rba90 2:5a74ae8be594 242 SerialInputBuffer.enqueue((uint8_t) '0');
rba90 2:5a74ae8be594 243 SerialInputBuffer.enqueue((uint8_t) 'f');
rba90 2:5a74ae8be594 244 SerialInputBuffer.enqueue((uint8_t) 'f');
rba90 2:5a74ae8be594 245 SerialInputBuffer.enqueue((uint8_t) '>');
rba90 2:5a74ae8be594 246 }
rba90 2:5a74ae8be594 247
rba90 2:5a74ae8be594 248
rba90 0:7d8e24cb62c1 249 int main() {
rba90 0:7d8e24cb62c1 250 // initialize radio module
rba90 3:7bb50ee42cba 251 aloha.boardInit();
rba90 3:7bb50ee42cba 252 aloha.updateSettings();
rba90 3:7bb50ee42cba 253 aloha.enable();
rba90 0:7d8e24cb62c1 254
rba90 0:7d8e24cb62c1 255 // attach serial interrupt handler
rba90 0:7d8e24cb62c1 256 pc.attach(&serialInterruptHandler);
rba90 0:7d8e24cb62c1 257
rba90 0:7d8e24cb62c1 258 // register callback functions for SIP
rba90 0:7d8e24cb62c1 259 SIP.registerCommand(0x00, toggleChecksum);
rba90 1:101cf4fca4e5 260 SIP.registerCommand(0x01, sendMessage);
rba90 3:7bb50ee42cba 261 SIP.registerCommand(0x02, configureRadio);
rba90 0:7d8e24cb62c1 262
rba90 0:7d8e24cb62c1 263 // register callback functions for aloha transceiver
rba90 1:101cf4fca4e5 264 aloha.registerType(AlohaFrame::Aloha_Data, AlohaDataHandler);
rba90 2:5a74ae8be594 265
rba90 2:5a74ae8be594 266 // configure button interrupt
rba90 2:5a74ae8be594 267 button.fall(automaticPacketTransmit);
rba90 0:7d8e24cb62c1 268
rba90 0:7d8e24cb62c1 269 while(1) {
rba90 0:7d8e24cb62c1 270 SIP.poll();
rba90 0:7d8e24cb62c1 271 aloha.poll();
rba90 0:7d8e24cb62c1 272
rba90 0:7d8e24cb62c1 273 while (SerialOutputBuffer.getCounter() > 0)
rba90 0:7d8e24cb62c1 274 {
rba90 0:7d8e24cb62c1 275 uint8_t ch;
rba90 0:7d8e24cb62c1 276 ch = SerialOutputBuffer.dequeue();
rba90 0:7d8e24cb62c1 277 pc.putc(ch);
rba90 0:7d8e24cb62c1 278 }
rba90 0:7d8e24cb62c1 279 }
rba90 0:7d8e24cb62c1 280 }