transfer files from mbed-os block device (i.e. SD card) over LoRa radio.

Dependencies:   sx12xx_hal

radio chip selection

Radio chip driver is not included, allowing choice of radio device.
If you're using SX1272 or SX1276, then import sx127x driver into your program.
if you're using SX1261 or SX1262, then import sx126x driver into your program.
if you're using SX1280, then import sx1280 driver into your program.
If you're using NAmote72 or Murata discovery, then you must import only sx127x driver.

This program uses mbed serial terminal at 115200 8N1.
Files (on SD Card) are transferred between two LoRa devices.
Use ? question mark to see available commands on serial terminal.
Send file to other side using send /fs/somefile, then use cmp /fs/somefile to compare the file on the other side of radio link with local file with same name.
Use cmp to test radio link.

rm command to delete files must not include /fs/ directory prefix, filename only.
send and cmp require /fs/ directory.

sx1280 thruput

bytes/secsf12sf11sf10sf9sf8sf7sf6sf5
1600KHz2764821081188732775365640012000
800KHz5299701720280047666500
400KHz146522654033

sx126x thruput

bytes/secsf12sf11sf10sf9sf8sf7sf6sf5
500KHz2073817061257215435705608
250KHz103193344641111418873064
125KHz971733245479721607

sx127x thruput

sx126x recommended at 500KHz bandwidth.

bytes/secsf12sf11sf10sf9sf8sf7
500KHz11120738569712202050
250KHz48.71031923456321115
125KHz24.24497151313552
62.5KHz12.222.139.486157276

SD Card

SD card driver must be enabled in mbed_app.json with the line "target.components_add": ["SD"]
Pins for SD card connection can be overridden as shown in mbed_app.json.
The default pin configuration for SD card is found in mbed_lib.json in mbed-os/components/storage/blockdevice/COMPONENT_SD/.
If no pin configuration exists in this mbed_lib.json, or needs to be changed, the included mbed_app.json is example pin declaration for SD card.

FAT filesystem is only used in this project for demonstration purpose; for easily copying files to SD card.
However, for production projects, LittleFileSystem needs to be used instead for reliability and wear leveling.

Platforms such as K64F have SD card slot already.
See all boards with arduino shield connector and SD card here. (arduino connector needed for LoRa radio board)
...but if you want to use nucleo board: /media/uploads/dudmuck/nucleo_sdcardqtr.png

Committer:
Wayne Roberts
Date:
Wed Jun 05 09:52:27 2019 -0700
Revision:
1:319ef808aaa4
Parent:
0:c3ecf7b252a3
mbed crashes closing -1 file descriptor

Who changed what in which revision?

UserRevisionLine numberNew contents of line
Wayne Roberts 0:c3ecf7b252a3 1 #include "lorachip.h"
Wayne Roberts 0:c3ecf7b252a3 2 #ifdef SX127x_H
Wayne Roberts 0:c3ecf7b252a3 3
Wayne Roberts 0:c3ecf7b252a3 4 #if defined(TARGET_FF_ARDUINO) && defined(TARGET_FF_MORPHO) && !defined(TARGET_DISCO_L072CZ_LRWAN1)
Wayne Roberts 0:c3ecf7b252a3 5 void tx_dbm_print()
Wayne Roberts 0:c3ecf7b252a3 6 {
Wayne Roberts 0:c3ecf7b252a3 7 int dbm;
Wayne Roberts 0:c3ecf7b252a3 8 RegPdsTrim1_t pds_trim;
Wayne Roberts 0:c3ecf7b252a3 9 uint8_t adr, pa_test_adr;
Wayne Roberts 0:c3ecf7b252a3 10
Wayne Roberts 0:c3ecf7b252a3 11 if (Radio::radio.type == SX1276) {
Wayne Roberts 0:c3ecf7b252a3 12 adr = REG_PDSTRIM1_SX1276;
Wayne Roberts 0:c3ecf7b252a3 13 pa_test_adr = REG_PATEST_SX1276;
Wayne Roberts 0:c3ecf7b252a3 14 } else {
Wayne Roberts 0:c3ecf7b252a3 15 adr = REG_PDSTRIM1_SX1272;
Wayne Roberts 0:c3ecf7b252a3 16 pa_test_adr = REG_PATEST_SX1272;
Wayne Roberts 0:c3ecf7b252a3 17 }
Wayne Roberts 0:c3ecf7b252a3 18
Wayne Roberts 0:c3ecf7b252a3 19 if (Radio::radio.read_reg(pa_test_adr) & 0x20) {
Wayne Roberts 0:c3ecf7b252a3 20 pds_trim.octet = Radio::radio.read_reg(adr);
Wayne Roberts 0:c3ecf7b252a3 21
Wayne Roberts 0:c3ecf7b252a3 22 Radio::radio.RegPaConfig.octet = Radio::radio.read_reg(REG_PACONFIG);
Wayne Roberts 0:c3ecf7b252a3 23 if (Radio::radio.RegPaConfig.bits.PaSelect) {
Wayne Roberts 0:c3ecf7b252a3 24 dbm = Radio::radio.RegPaConfig.bits.OutputPower + pds_trim.bits.prog_txdac - 2;
Wayne Roberts 0:c3ecf7b252a3 25 } else {
Wayne Roberts 0:c3ecf7b252a3 26 dbm = Radio::radio.RegPaConfig.bits.OutputPower - 1;
Wayne Roberts 0:c3ecf7b252a3 27 }
Wayne Roberts 0:c3ecf7b252a3 28 } else {
Wayne Roberts 0:c3ecf7b252a3 29 dbm = PA_OFF_DBM;
Wayne Roberts 0:c3ecf7b252a3 30 }
Wayne Roberts 0:c3ecf7b252a3 31 pc.printf("%ddBm ", dbm);
Wayne Roberts 0:c3ecf7b252a3 32 }
Wayne Roberts 0:c3ecf7b252a3 33 #endif /* ...sx127x shield */
Wayne Roberts 0:c3ecf7b252a3 34
Wayne Roberts 0:c3ecf7b252a3 35 static const float lora_bws_1276[] = {
Wayne Roberts 0:c3ecf7b252a3 36 7.8, // 0
Wayne Roberts 0:c3ecf7b252a3 37 10.4, // 1
Wayne Roberts 0:c3ecf7b252a3 38 15.6, // 2
Wayne Roberts 0:c3ecf7b252a3 39 20.8, // 3
Wayne Roberts 0:c3ecf7b252a3 40 31.25, // 4
Wayne Roberts 0:c3ecf7b252a3 41 41.7, // 5
Wayne Roberts 0:c3ecf7b252a3 42 62.5, // 6
Wayne Roberts 0:c3ecf7b252a3 43 125, // 7
Wayne Roberts 0:c3ecf7b252a3 44 250, // 8
Wayne Roberts 0:c3ecf7b252a3 45 500 // 9
Wayne Roberts 0:c3ecf7b252a3 46 };
Wayne Roberts 0:c3ecf7b252a3 47
Wayne Roberts 0:c3ecf7b252a3 48 static const float lora_bws_1272[] = {
Wayne Roberts 0:c3ecf7b252a3 49 125, // 0
Wayne Roberts 0:c3ecf7b252a3 50 250, // 1
Wayne Roberts 0:c3ecf7b252a3 51 500 // 2
Wayne Roberts 0:c3ecf7b252a3 52 };
Wayne Roberts 0:c3ecf7b252a3 53
Wayne Roberts 0:c3ecf7b252a3 54 void printLoraIrqs(bool clear)
Wayne Roberts 0:c3ecf7b252a3 55 {
Wayne Roberts 0:c3ecf7b252a3 56 //in radio class -- RegIrqFlags_t RegIrqFlags;
Wayne Roberts 0:c3ecf7b252a3 57
Wayne Roberts 0:c3ecf7b252a3 58 //already read RegIrqFlags.octet = radio.read_reg(REG_LR_IRQFLAGS);
Wayne Roberts 0:c3ecf7b252a3 59 pc.printf("\r\nIrqFlags:");
Wayne Roberts 0:c3ecf7b252a3 60 if (Radio::lora.RegIrqFlags.bits.CadDetected)
Wayne Roberts 0:c3ecf7b252a3 61 pc.printf("CadDetected ");
Wayne Roberts 0:c3ecf7b252a3 62 if (Radio::lora.RegIrqFlags.bits.FhssChangeChannel) {
Wayne Roberts 0:c3ecf7b252a3 63 //radio.RegHopChannel.octet = radio.read_reg(REG_LR_HOPCHANNEL);
Wayne Roberts 0:c3ecf7b252a3 64 pc.printf("FhssChangeChannel:%d ", Radio::lora.RegHopChannel.bits.FhssPresentChannel);
Wayne Roberts 0:c3ecf7b252a3 65 }
Wayne Roberts 0:c3ecf7b252a3 66 if (Radio::lora.RegIrqFlags.bits.CadDone)
Wayne Roberts 0:c3ecf7b252a3 67 pc.printf("CadDone ");
Wayne Roberts 0:c3ecf7b252a3 68 if (Radio::lora.RegIrqFlags.bits.TxDone)
Wayne Roberts 0:c3ecf7b252a3 69 pc.printf("TxDone ");
Wayne Roberts 0:c3ecf7b252a3 70 if (Radio::lora.RegIrqFlags.bits.ValidHeader)
Wayne Roberts 0:c3ecf7b252a3 71 pc.printf("ValidHeader ");
Wayne Roberts 0:c3ecf7b252a3 72 if (Radio::lora.RegIrqFlags.bits.PayloadCrcError)
Wayne Roberts 0:c3ecf7b252a3 73 pc.printf("PayloadCrcError ");
Wayne Roberts 0:c3ecf7b252a3 74 if (Radio::lora.RegIrqFlags.bits.RxDone)
Wayne Roberts 0:c3ecf7b252a3 75 pc.printf("RxDone ");
Wayne Roberts 0:c3ecf7b252a3 76 if (Radio::lora.RegIrqFlags.bits.RxTimeout)
Wayne Roberts 0:c3ecf7b252a3 77 pc.printf("RxTimeout ");
Wayne Roberts 0:c3ecf7b252a3 78
Wayne Roberts 0:c3ecf7b252a3 79 pc.printf("\r\n");
Wayne Roberts 0:c3ecf7b252a3 80
Wayne Roberts 0:c3ecf7b252a3 81 if (clear)
Wayne Roberts 0:c3ecf7b252a3 82 Radio::radio.write_reg(REG_LR_IRQFLAGS, Radio::lora.RegIrqFlags.octet);
Wayne Roberts 0:c3ecf7b252a3 83
Wayne Roberts 0:c3ecf7b252a3 84 }
Wayne Roberts 0:c3ecf7b252a3 85
Wayne Roberts 0:c3ecf7b252a3 86 void print_lora_status()
Wayne Roberts 0:c3ecf7b252a3 87 {
Wayne Roberts 0:c3ecf7b252a3 88 float MHz;
Wayne Roberts 0:c3ecf7b252a3 89 const float* bws;
Wayne Roberts 0:c3ecf7b252a3 90 unsigned bw_idx;
Wayne Roberts 0:c3ecf7b252a3 91
Wayne Roberts 0:c3ecf7b252a3 92 tx_dbm_print();
Wayne Roberts 0:c3ecf7b252a3 93 Radio::radio.RegOpMode.octet = Radio::radio.read_reg(REG_OPMODE);
Wayne Roberts 0:c3ecf7b252a3 94
Wayne Roberts 0:c3ecf7b252a3 95 switch (Radio::radio.RegOpMode.bits.Mode) {
Wayne Roberts 0:c3ecf7b252a3 96 case 0: pc.printf("SLEEP"); break;
Wayne Roberts 0:c3ecf7b252a3 97 case 1: pc.printf("STANDBY"); break;
Wayne Roberts 0:c3ecf7b252a3 98 case 2: pc.printf("FS_TX"); break;
Wayne Roberts 0:c3ecf7b252a3 99 case 3: pc.printf("TX"); break;
Wayne Roberts 0:c3ecf7b252a3 100 case 4: pc.printf("FS_RX"); break;
Wayne Roberts 0:c3ecf7b252a3 101 case 5: pc.printf("RX"); break;
Wayne Roberts 0:c3ecf7b252a3 102 case 6: pc.printf("RX_SINGLE"); break;
Wayne Roberts 0:c3ecf7b252a3 103 case 7: pc.printf("CAD"); break;
Wayne Roberts 0:c3ecf7b252a3 104 }
Wayne Roberts 0:c3ecf7b252a3 105
Wayne Roberts 0:c3ecf7b252a3 106 Radio::lora.RegIrqFlags.octet = Radio::radio.read_reg(REG_LR_IRQFLAGS);
Wayne Roberts 0:c3ecf7b252a3 107 printLoraIrqs(false);
Wayne Roberts 0:c3ecf7b252a3 108
Wayne Roberts 0:c3ecf7b252a3 109 if (Radio::radio.type == SX1276)
Wayne Roberts 0:c3ecf7b252a3 110 bws = lora_bws_1276;
Wayne Roberts 0:c3ecf7b252a3 111 else if (Radio::radio.type == SX1272)
Wayne Roberts 0:c3ecf7b252a3 112 bws = lora_bws_1272;
Wayne Roberts 0:c3ecf7b252a3 113 else
Wayne Roberts 0:c3ecf7b252a3 114 return;
Wayne Roberts 0:c3ecf7b252a3 115
Wayne Roberts 0:c3ecf7b252a3 116 bw_idx = Radio::lora.getBw();
Wayne Roberts 0:c3ecf7b252a3 117 pc.printf("sf%u %.1fKHz ", Radio::lora.getSf(), bws[bw_idx]);
Wayne Roberts 0:c3ecf7b252a3 118 MHz = Radio::radio.get_frf_MHz();
Wayne Roberts 0:c3ecf7b252a3 119 pc.printf(" %.3fMHz\r\n", MHz);
Wayne Roberts 0:c3ecf7b252a3 120
Wayne Roberts 0:c3ecf7b252a3 121 }
Wayne Roberts 0:c3ecf7b252a3 122
Wayne Roberts 0:c3ecf7b252a3 123 void cmd_sf(uint8_t argsAt)
Wayne Roberts 0:c3ecf7b252a3 124 {
Wayne Roberts 0:c3ecf7b252a3 125 unsigned sf;
Wayne Roberts 0:c3ecf7b252a3 126
Wayne Roberts 0:c3ecf7b252a3 127 if (sscanf(pcbuf + argsAt, "%u", &sf) == 1) {
Wayne Roberts 0:c3ecf7b252a3 128 Radio::lora.setSf(sf);
Wayne Roberts 0:c3ecf7b252a3 129 current.sf = sf;
Wayne Roberts 0:c3ecf7b252a3 130 set_symb_timeout();
Wayne Roberts 0:c3ecf7b252a3 131 }
Wayne Roberts 0:c3ecf7b252a3 132
Wayne Roberts 0:c3ecf7b252a3 133 pc.printf("sf%u\r\n", Radio::lora.getSf());
Wayne Roberts 0:c3ecf7b252a3 134 }
Wayne Roberts 0:c3ecf7b252a3 135
Wayne Roberts 0:c3ecf7b252a3 136 void cmd_frf(uint8_t argsAt)
Wayne Roberts 0:c3ecf7b252a3 137 {
Wayne Roberts 0:c3ecf7b252a3 138 float MHz;
Wayne Roberts 0:c3ecf7b252a3 139
Wayne Roberts 0:c3ecf7b252a3 140 if (sscanf(pcbuf + argsAt, "%f", &MHz) == 1) {
Wayne Roberts 0:c3ecf7b252a3 141 Radio::radio.set_frf_MHz(MHz);
Wayne Roberts 0:c3ecf7b252a3 142 }
Wayne Roberts 0:c3ecf7b252a3 143 MHz = Radio::radio.get_frf_MHz();
Wayne Roberts 0:c3ecf7b252a3 144 pc.printf("%.3fMHz\r\n", MHz);
Wayne Roberts 0:c3ecf7b252a3 145 }
Wayne Roberts 0:c3ecf7b252a3 146
Wayne Roberts 0:c3ecf7b252a3 147 void cmd_bw(uint8_t argsAt)
Wayne Roberts 0:c3ecf7b252a3 148 {
Wayne Roberts 0:c3ecf7b252a3 149 const float* bws;
Wayne Roberts 0:c3ecf7b252a3 150 unsigned khz;
Wayne Roberts 0:c3ecf7b252a3 151 unsigned bw_idx;
Wayne Roberts 0:c3ecf7b252a3 152
Wayne Roberts 0:c3ecf7b252a3 153 if (sscanf(pcbuf + argsAt, "%u", &khz) == 1) {
Wayne Roberts 0:c3ecf7b252a3 154 Radio::Standby();
Wayne Roberts 0:c3ecf7b252a3 155 wait(0.02);
Wayne Roberts 0:c3ecf7b252a3 156
Wayne Roberts 0:c3ecf7b252a3 157 Radio::lora.setBw_KHz(khz);
Wayne Roberts 0:c3ecf7b252a3 158
Wayne Roberts 0:c3ecf7b252a3 159 wait(0.02);
Wayne Roberts 0:c3ecf7b252a3 160 Radio::Rx(0);
Wayne Roberts 0:c3ecf7b252a3 161
Wayne Roberts 0:c3ecf7b252a3 162 current.bwKHz = khz;
Wayne Roberts 0:c3ecf7b252a3 163 set_symb_timeout();
Wayne Roberts 0:c3ecf7b252a3 164 }
Wayne Roberts 0:c3ecf7b252a3 165
Wayne Roberts 0:c3ecf7b252a3 166 if (Radio::radio.type == SX1276)
Wayne Roberts 0:c3ecf7b252a3 167 bws = lora_bws_1276;
Wayne Roberts 0:c3ecf7b252a3 168 else if (Radio::radio.type == SX1272)
Wayne Roberts 0:c3ecf7b252a3 169 bws = lora_bws_1272;
Wayne Roberts 0:c3ecf7b252a3 170 else
Wayne Roberts 0:c3ecf7b252a3 171 return;
Wayne Roberts 0:c3ecf7b252a3 172
Wayne Roberts 0:c3ecf7b252a3 173 bw_idx = Radio::lora.getBw();
Wayne Roberts 0:c3ecf7b252a3 174 pc.printf("%.1fKHz\r\n", bws[bw_idx]);
Wayne Roberts 0:c3ecf7b252a3 175 }
Wayne Roberts 0:c3ecf7b252a3 176
Wayne Roberts 0:c3ecf7b252a3 177 void radio_readChip()
Wayne Roberts 0:c3ecf7b252a3 178 {
Wayne Roberts 0:c3ecf7b252a3 179 }
Wayne Roberts 0:c3ecf7b252a3 180
Wayne Roberts 0:c3ecf7b252a3 181 #endif /* SX127x_H */