Wireless interface using LoRa technology
Dependencies: AlohaTransceiver RingBuffer SX1276Lib_inAir SerialInterfaceProtocol mbed L3PDU
main.cpp@4:9151697dfa70, 2016-07-17 (annotated)
- 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?
User | Revision | Line number | New 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 | } |