wayne roberts / Mbed OS utility_sx12xx

Files at this revision

API Documentation at this revision

Comitter:
Wayne Roberts
Date:
Thu Nov 01 13:02:38 2018 -0700
Parent:
2:ea9245bb1c53
Child:
4:fa31fdf4ec8d
Commit message:
add post-preamble gap

Changed in this revision

main.cpp Show annotated file Show diff for this revision Revisions of this file
mbed-os.lib Show annotated file Show diff for this revision Revisions of this file
radio_sx126x.cpp Show annotated file Show diff for this revision Revisions of this file
radio_sx126x_private.h Show annotated file Show diff for this revision Revisions of this file
radio_sx127x.cpp Show annotated file Show diff for this revision Revisions of this file
radio_sx127x_private.h Show annotated file Show diff for this revision Revisions of this file
radio_sx128x.cpp Show annotated file Show diff for this revision Revisions of this file
radio_sx128x_private.h Show annotated file Show diff for this revision Revisions of this file
--- a/main.cpp	Wed Aug 22 09:50:32 2018 -0700
+++ b/main.cpp	Thu Nov 01 13:02:38 2018 -0700
@@ -1256,6 +1256,7 @@
 
         if (menuState.mode == MENUMODE_REDRAW) {
             // erase entire screen, some dropdowns extend to scrolling area
+            pc.printf("\e[%u;%ur", MAX_MENU_ROWS, botRow); // set scrolling region, if terminal started after
             pc.printf("\e[2J");
             //pc.printf("\e[%u;1f\e[1J", MAX_MENU_ROWS);  // erase menu area
 
--- a/mbed-os.lib	Wed Aug 22 09:50:32 2018 -0700
+++ b/mbed-os.lib	Thu Nov 01 13:02:38 2018 -0700
@@ -1,1 +1,1 @@
-https://github.com/ARMmbed/mbed-os/#f8b140f8d7cb226e41486c5df66ac4f3ce699219
+https://github.com/ARMmbed/mbed-os/#e1bea44212b8275f7d8ce7253e758c2e25c57482
--- a/radio_sx126x.cpp	Wed Aug 22 09:50:32 2018 -0700
+++ b/radio_sx126x.cpp	Thu Nov 01 13:02:38 2018 -0700
@@ -45,6 +45,7 @@
 uint8_t Radio::pktType;
 uint8_t Radio::bw_idx;
 uint8_t Radio::cadParams[7];
+uint16_t Radio::ppg;
 
 const char* opModes[] = {
     "SLEEP    ", // 0
@@ -602,7 +603,7 @@
 
 const toggle_item_t Radio::deviceSel_item = { _ITEM_TOGGLE, "SX1262", "SX1261", deviceSel_read, deviceSel_push};
 
-static const char* paDutyCycles[] = {
+static const char* const paDutyCycles[] = {
     "0",
     "1",
     "2",
@@ -631,7 +632,7 @@
 
 const dropdown_item_t Radio::paDutyCycle_item = { _ITEM_DROPDOWN, paDutyCycles, paDutyCycles, paDutyCycle_read, paDutyCycle_write};
 
-static const char* hpMaxs[] = {
+static const char* const hpMaxs[] = {
     "0",
     "1",
     "2",
@@ -694,7 +695,7 @@
     LORA_BW_500
 };
 
-static const char* lora_bwstrs[] = {
+static const char* const lora_bwstrs[] = {
     " 7.81KHz", "10.42KHz", "15.63KHz",
     "20.83KHz", "31.25KHz", "41.67KHz",
     " 62.5KHz", "  125KHz", "  250KHz",
@@ -747,7 +748,7 @@
 
 const value_item_t Radio::lora_sf_item = { _ITEM_VALUE, 3, lora_sf_print, lora_sf_write };
 
-static const char* lora_crs[] = {
+static const char* const lora_crs[] = {
     "4/5   ",
     "4/6   ",
     "4/7   ",
@@ -877,6 +878,30 @@
 
 const toggle_item_t Radio::lora_inviq_item = { _ITEM_TOGGLE, "InvertIQ", NULL, lora_inviq_read, lora_inviq_push};
 
+void Radio::lora_ppg_print()
+{
+    uint8_t val;
+    ppg = radio.readReg(REG_ADDR_LORA_SYNC, 2);
+
+    val = (ppg >> 8) & 0xf0;
+    val |= (ppg & 0xf0) >> 4;
+    pc.printf("%02x", val);
+}
+
+bool Radio::lora_ppg_write(const char* txt)
+{
+    unsigned val;
+    if (sscanf(txt, "%x", &val) == 1) {
+        ppg &= 0x0707;
+        ppg |= (val & 0xf0) << 8;
+        ppg |= (val & 0x0f) << 4;
+        radio.writeReg(REG_ADDR_LORA_SYNC, ppg, 2);
+    }
+    return false;
+}
+
+const value_item_t Radio::lora_ppg_item = { _ITEM_VALUE, 4, lora_ppg_print, lora_ppg_write};
+
 void Radio::cad_push()
 {
     {
@@ -904,7 +929,7 @@
 
 const button_item_t Radio::lora_cad_item = { _ITEM_BUTTON, "CAD", cad_push };
 
-static const char* lora_cadsymbs[] = {
+static const char* const lora_cadsymbs[] = {
     " 1",
     " 2",
     " 4",
@@ -1022,6 +1047,7 @@
     { {FIRST_CHIP_MENU_ROW+2, 22},              NULL, &lora_headerType_item, FLAG_MSGTYPE_ALL },
     { {FIRST_CHIP_MENU_ROW+2, 32},              NULL, &lora_crcon_item, FLAG_MSGTYPE_ALL },
     { {FIRST_CHIP_MENU_ROW+2, 39},              NULL, &lora_inviq_item, FLAG_MSGTYPE_ALL },
+    { {FIRST_CHIP_MENU_ROW+2, 49},            "ppg:", &lora_ppg_item, FLAG_MSGTYPE_ALL },
 
     { {FIRST_CHIP_MENU_ROW+3,  1},          NULL,        &lora_cad_item, FLAG_MSGTYPE_ALL },
     { {FIRST_CHIP_MENU_ROW+3,  5},    "symbols:",   &lora_cadsymbs_item, FLAG_MSGTYPE_ALL },
@@ -1070,7 +1096,7 @@
 
 const value_item_t Radio::gfsk_bitrate_item = { _ITEM_VALUE, 8, gfsk_bitrate_print, gfsk_bitrate_write};
 
-static const char* gfsk_bts[] = {
+static const char* const gfsk_bts[] = {
     "off", // 0
     "0.3", // 1
     "0.5", // 2
@@ -1114,7 +1140,7 @@
     GFSK_RX_BW_467000
 };
 
-static const char* rxbw_str[] = {
+static const char* const rxbw_str[] = {
     "  4.8KHz", "  5.8KHz", "  7.3KHz", "  9.7KHz",
     " 11.7KHz", " 14.6KHz", " 19.5KHz", " 23.4KHz",
     " 29.3KHz", " 39.0KHz", " 46.9KHz", " 58.6KHz",
@@ -1189,7 +1215,7 @@
 
 const value_item_t Radio::gfsk_pblLen_item = { _ITEM_VALUE, 5, gfsk_pblLen_print, gfsk_pblLen_write};
 
-static const char* fsk_detlens[] = {
+static const char* const fsk_detlens[] = {
     " off  ",
     " 8bits",
     "16bits",
@@ -1307,7 +1333,7 @@
 };
 
 
-static const char* addrcomps[] = {
+static const char* const addrcomps[] = {
     "          off        ",
     "NodeAddress          ",
     "NodeAddress+broadcast",
--- a/radio_sx126x_private.h	Wed Aug 22 09:50:32 2018 -0700
+++ b/radio_sx126x_private.h	Thu Nov 01 13:02:38 2018 -0700
@@ -59,6 +59,11 @@
         static bool lora_inviq_push(void);
         static const toggle_item_t lora_inviq_item;
 
+        static void lora_ppg_print(void);
+        static bool lora_ppg_write(const char*);
+        static const value_item_t lora_ppg_item;
+        static uint16_t ppg;
+
         static void cad_push(void);
         static const button_item_t lora_cad_item;
 
--- a/radio_sx127x.cpp	Wed Aug 22 09:50:32 2018 -0700
+++ b/radio_sx127x.cpp	Thu Nov 01 13:02:38 2018 -0700
@@ -552,7 +552,7 @@
 
 const value_item_t Radio::lora_pblLen_item = { _ITEM_VALUE, 5, lora_pblLen_print, lora_pblLen_write};
 
-static const char* lora_fixlen[] = {
+static const char* const lora_fixlen[] = {
     "EXPLICIT", // 0
     "IMPLICIT", // 1
     NULL
@@ -617,6 +617,23 @@
 
 const toggle_item_t Radio::lora_iqinvRX_item = { _ITEM_TOGGLE, "iqInvRX", NULL, lora_iqinvRX_read, lora_iqinvRX_push};
 
+void Radio::lora_ppg_print()
+{
+    pc.printf("%02x", radio.read_reg(REG_LR_SYNC_BYTE));
+}
+
+bool Radio::lora_ppg_write(const char* str)
+{
+    unsigned ppg;
+    sscanf(str, "%x", &ppg);
+
+    radio.write_reg(REG_LR_SYNC_BYTE, ppg);
+
+    return false;
+}
+
+const value_item_t Radio::lora_ppg_item = { _ITEM_VALUE, 4, lora_ppg_print, lora_ppg_write};
+
 void Radio::cadrx_push()
 {
     if (radio.RegDioMapping1.bits.Dio0Mapping != 2 || radio.RegDioMapping1.bits.Dio1Mapping != 2) {
@@ -640,6 +657,7 @@
     { {FIRST_CHIP_MENU_ROW+1, 10}, NULL, &lora_crcon_item, FLAG_MSGTYPE_ALL },
     { {FIRST_CHIP_MENU_ROW+1, 20}, NULL, &lora_iqinvTX_item, FLAG_MSGTYPE_ALL },
     { {FIRST_CHIP_MENU_ROW+1, 30}, NULL, &lora_iqinvRX_item, FLAG_MSGTYPE_ALL },
+    { {FIRST_CHIP_MENU_ROW+1, 40}, "ppg:", &lora_ppg_item, FLAG_MSGTYPE_ALL },
 
     { {FIRST_CHIP_MENU_ROW+2, 1}, NULL, &lora_cadrx_item, FLAG_MSGTYPE_ALL },
 
--- a/radio_sx127x_private.h	Wed Aug 22 09:50:32 2018 -0700
+++ b/radio_sx127x_private.h	Thu Nov 01 13:02:38 2018 -0700
@@ -74,6 +74,10 @@
         static bool lora_iqinvRX_push(void);
         static const toggle_item_t lora_iqinvRX_item;
 
+        static void lora_ppg_print(void);
+        static bool lora_ppg_write(const char*);
+        static const value_item_t lora_ppg_item;
+
         static void pblLen_print(void);
         static bool pblLen_write(const char*);
         static const value_item_t pblLen_item ;
--- a/radio_sx128x.cpp	Wed Aug 22 09:50:32 2018 -0700
+++ b/radio_sx128x.cpp	Thu Nov 01 13:02:38 2018 -0700
@@ -48,6 +48,7 @@
 const RadioEvents_t* Radio::RadioEvents;
 LowPowerTimer Radio::lpt;
 uint8_t Radio::pktType;
+uint16_t Radio::ppg;
 
 const char* const Radio::pktType_strs[] = {
     "GFSK   ",
@@ -292,6 +293,8 @@
 void Radio::hw_reset()
 {
     radio.hw_reset();
+
+    manualRngDelay = false;
 }
 
 void Radio::clearIrqFlags()
@@ -338,17 +341,14 @@
     ppGFSK.gfskFLRC.Whitening = reg8 & 0x08;
     ppFLRC.gfskFLRC.Whitening = reg8 & 0x08;
 
-    {
-        LoRaPktPar0_t LoRaPktPar0;
-        LoRaPktPar0.octet = radio.readReg(REG_ADDR_LORA_PKTPAR0, 1);
-        switch (LoRaPktPar0.bits.modem_bw) {
-            case 2: mpLORA.lora.bandwidth = LORA_BW_200; break;
-            case 3: mpLORA.lora.bandwidth = LORA_BW_400; break;
-            case 4: mpLORA.lora.bandwidth = LORA_BW_800; break;
-            case 5: mpLORA.lora.bandwidth = LORA_BW_1600; break;
-        }
-        mpLORA.lora.spreadingFactor = LoRaPktPar0.bits.modem_sf << 4;
+    LoRaPktPar0.octet = radio.readReg(REG_ADDR_LORA_PKTPAR0, 1);
+    switch (LoRaPktPar0.bits.modem_bw) {
+        case 2: mpLORA.lora.bandwidth = LORA_BW_200; break;
+        case 3: mpLORA.lora.bandwidth = LORA_BW_400; break;
+        case 4: mpLORA.lora.bandwidth = LORA_BW_800; break;
+        case 5: mpLORA.lora.bandwidth = LORA_BW_1600; break;
     }
+    mpLORA.lora.spreadingFactor = LoRaPktPar0.bits.modem_sf << 4;
 
     {
         LoRaPktPar1_t LoRaPktPar1;
@@ -560,12 +560,52 @@
     chipModeChange();
 }
 
+void Radio::rngTx()
+{
+    IrqFlags_t irqEnable;
+    uint8_t buf[8];
+
+    if (!manualRngDelay)
+        rngUpdateDelayCal();
+
+    irqEnable.word = 0;
+    irqEnable.bits.TxDone = 1;
+    irqEnable.bits.RxTxTimeout = 1;
+    irqEnable.bits.RangingMasterTimeout = 1;
+    irqEnable.bits.RangingMasterResultValid = 1;
+    irqEnable.bits.RangingMasterRequestValid = 1;
+
+    buf[0] = irqEnable.word >> 8;    // enable bits
+    buf[1] = irqEnable.word; // enable bits
+
+    irqEnable.bits.RangingMasterTimeout = 0;
+    irqEnable.bits.RangingMasterResultValid = 0;
+    irqEnable.bits.RangingMasterRequestValid = 0;
+    buf[2] = irqEnable.word >> 8;     // dio1
+    buf[3] = irqEnable.word;  // dio1
+
+    buf[4] = 0; // dio2
+    buf[5] = 0; // dio2
+    buf[6] = 0; // dio3
+    buf[7] = 0; // dio3
+    radio.xfer(OPCODE_SET_DIO_IRQ_PARAMS, 8, 0, buf);
+
+    log_printf("rngTx\r\n");
+
+    buf[0] = radio.periodBase;
+    /* no timeout */
+    buf[1] = 0;
+    buf[2] = 0;
+    radio.xfer(OPCODE_SET_TX, 3, 0, buf);
+
+    radio.chipMode = CHIPMODE_TX;
+    chipModeChange();
+}
+
 void Radio::txPkt()
 {
     uint8_t txlen = 0;
 
-    radio.setBufferBase(0, 0);
-
     pktType = radio.getPacketType();
 
     switch (pktType) {
@@ -576,12 +616,16 @@
         case PACKET_TYPE_BLE:
             return; // TODO BLE
         case PACKET_TYPE_RANGING:
+            rngTx();
+            return;
         case PACKET_TYPE_LORA:
             txlen = radio.readReg(REG_ADDR_LORA_TX_PAYLOAD_LENGTH, 1);
             break;
     }
     log_printf("txPkt%u\r\n", txlen);
 
+    radio.setBufferBase(0, 0);
+
     radio.start_tx(txlen, 0);
 
 }
@@ -714,7 +758,7 @@
     return MENUMODE_REDRAW;
 }
 
-static const char* gfsk_bpsbw[] = {
+static const char* const gfsk_bpsbw[] = {
     "  2.0Mbps 2.4MHz", //0 GFSK_BLE_BR_2_000_BW_2_4    0x04 // Mbps:2      bw:2.4MHz
     "  1.6Mbps 2.4MHz", //1 GFSK_BLE_BR_1_600_BW_2_4    0x28 // Mbps:1.6    bw:2.4MHz
     "  1.0Mbps 2.4MHz", //2 GFSK_BLE_BR_1_000_BW_2_4    0x4C // Mbps:1      bw:2.4MHz
@@ -787,7 +831,7 @@
 
 const value_item_t Radio::gfsk_modindex_item = { _ITEM_VALUE, 7, modindex_print, modindex_write };
 
-static const char* gfsk_flrc_bts[] = {
+static const char* const gfsk_flrc_bts[] = {
     "off",
     "1.0",
     "0.5",
@@ -811,7 +855,7 @@
 
 const dropdown_item_t Radio::gfsk_flrc_bt_item = { _ITEM_DROPDOWN, gfsk_flrc_bts, gfsk_flrc_bts, gfsk_flrc_bt_read, gfsk_flrc_bt_write};
 
-static const char* gfsk_flrc_pblLens[] = {
+static const char* const gfsk_flrc_pblLens[] = {
     "4",
     "8",
     "12",
@@ -842,7 +886,7 @@
 
 const dropdown_item_t Radio::gfsk_flrc_preamble_item = { _ITEM_DROPDOWN, gfsk_flrc_pblLens, gfsk_flrc_pblLens, gfsk_flrc_pl_read, gfsk_flrc_pl_write};
 
-static const char* gfsk_syncLens[] = {
+static const char* const gfsk_syncLens[] = {
     "1", // 0
     "2", // 1
     "3", // 2
@@ -912,7 +956,7 @@
     gfsk_flrc_fixvar_read, gfsk_flrc_fixvar_push
 };
 
-static const char* gfsk_flrc_crclens[] = {
+static const char* const gfsk_flrc_crclens[] = {
     "0 off",
     "1 byte",
     "2 bytes",
@@ -1199,7 +1243,7 @@
     { {0, 0}, NULL, NULL }
 };
 
-static const char* flrc_bpsbw[] = {
+static const char* const flrc_bpsbw[] = {
     "2.6",
     "2.08",
     "1.3Mb/s   1.2MHz",
@@ -1213,7 +1257,7 @@
 
 const dropdown_item_t Radio::flrc_bitrate_item = { _ITEM_DROPDOWN, flrc_bpsbw, flrc_bpsbw, gfsk_flrc_bpsbw_read, gfsk_flrc_bpsbw_write};
 
-static const char* flrc_crs[] = {
+static const char* const flrc_crs[] = {
     "1/2",
     "3/4",
     "1  ",
@@ -1238,7 +1282,7 @@
 
 const dropdown_item_t Radio::flrc_cr_item = { _ITEM_DROPDOWN, flrc_crs, flrc_crs, flrc_cr_read, flrc_cr_write};
 
-static const char* flrc_syncLens[] = {
+static const char* const flrc_syncLens[] = {
     "SYNC OFF  ",
     "16BIT SYNC",
     "32BIT SYNC",
@@ -1291,7 +1335,30 @@
     { {0, 0}, NULL, NULL }
 };
 
-static const char* lora_bws[] = {
+bool Radio::manualRngDelay;
+const uint16_t Radio::rngDelays[3][6] = {
+    10299, 10271, 10244, 10242, 10230, 10246,
+    11486, 11474, 11453, 11426, 11417, 11401,
+    13308, 13493, 13528, 13515, 13430, 13376
+};
+
+void Radio::rngUpdateDelayCal()
+{
+    LoRaPktPar0.octet = radio.readReg(REG_ADDR_LORA_PKTPAR0, 1);
+
+    if (LoRaPktPar0.bits.modem_bw > 2 && LoRaPktPar0.bits.modem_sf < 11) {
+        uint32_t delayCal = radio.readReg(REG_ADDR_LORA_DELAY_CAL, 3);
+        delayCal &= ~0x3fffff;
+        delayCal |= rngDelays[LoRaPktPar0.bits.modem_bw-3][LoRaPktPar0.bits.modem_sf-5];
+        /*log_printf("%u = rngDelays[%u][%u]\r\n",
+            rngDelays[LoRaPktPar0.bits.modem_bw-3][LoRaPktPar0.bits.modem_sf-5],
+            LoRaPktPar0.bits.modem_bw-3, LoRaPktPar0.bits.modem_sf-5
+        );*/
+        radio.writeReg(REG_ADDR_LORA_DELAY_CAL, delayCal, 3);
+    }
+}
+
+static const char* const lora_bws[] = {
     "  50KHz", // 0
     " 100KHz", // 1
     " 200KHz", // 2
@@ -1301,9 +1368,12 @@
     NULL
 };
 
+const float Radio::bwMHzs[] = { 0.05, 0.1, 0.2, 0.4, 0.8, 1.6 };
+
+LoRaPktPar0_t Radio::LoRaPktPar0;
+
 unsigned Radio::lora_bw_read(bool fw)
 {
-    LoRaPktPar0_t LoRaPktPar0;
     LoRaPktPar0.octet = radio.readReg(REG_ADDR_LORA_PKTPAR0, 1);
 
     return LoRaPktPar0.bits.modem_bw;
@@ -1321,6 +1391,11 @@
     }
     radio.xfer(OPCODE_SET_MODULATION_PARAMS, 3, 0, mpLORA.buf);
 
+    if (pktType == PACKET_TYPE_RANGING) {
+        manualRngDelay = false;
+        rngUpdateDelayCal();
+    }
+
     return MENUMODE_REDRAW;
 }
 
@@ -1328,7 +1403,6 @@
 
 void Radio::lora_sf_print()
 {
-    LoRaPktPar0_t LoRaPktPar0;
     LoRaPktPar0.octet = radio.readReg(REG_ADDR_LORA_PKTPAR0, 1);
 
     pc.printf("%u", LoRaPktPar0.bits.modem_sf);
@@ -1340,13 +1414,18 @@
     if (sscanf(str, "%u", &n) == 1) {
         mpLORA.lora.spreadingFactor = n << 4;
         radio.xfer(OPCODE_SET_MODULATION_PARAMS, 3, 0, mpLORA.buf);
+
+        if (pktType == PACKET_TYPE_RANGING) {
+            manualRngDelay = false;
+            rngUpdateDelayCal();
+        }
     }
     return false;
 }
 
 const value_item_t Radio::lora_sf_item = { _ITEM_VALUE, 3, lora_sf_print, lora_sf_write };
 
-static const char* lora_crs[] = {
+static const char* const lora_crs[] = {
     "4/5   ",
     "4/6   ",
     "4/7   ",
@@ -1478,6 +1557,30 @@
     lora_iqinv_read, lora_iqinv_push
 };
 
+void Radio::lora_ppg_print()
+{
+    uint8_t val;
+    ppg = radio.readReg(REG_ADDR_LORA_SYNC, 2);
+
+    val = (ppg >> 8) & 0xf0;
+    val |= (ppg & 0xf0) >> 4;
+    pc.printf("%02x", val);
+}
+
+bool Radio::lora_ppg_write(const char* txt)
+{
+    unsigned val;
+    if (sscanf(txt, "%x", &val) == 1) {
+        ppg &= 0x0707;
+        ppg |= (val & 0xf0) << 8;
+        ppg |= (val & 0x0f) << 4;
+        radio.writeReg(REG_ADDR_LORA_SYNC, ppg, 2);
+    }
+    return false;
+}
+
+const value_item_t Radio::lora_ppg_item = { _ITEM_VALUE, 4, lora_ppg_print, lora_ppg_write};
+
 void Radio::cad_push()
 {
     radio.setCAD();
@@ -1485,7 +1588,7 @@
 
 const button_item_t Radio::lora_cad_item = { _ITEM_BUTTON, "CAD", cad_push };
 
-static const char* lora_cadsymbs[] = {
+static const char* const lora_cadsymbs[] = {
     " 1",
     " 2",
     " 4",
@@ -1510,13 +1613,14 @@
 const dropdown_item_t Radio::lora_cadsymbs_item = { _ITEM_DROPDOWN, lora_cadsymbs, lora_cadsymbs, lora_cadsymbs_read, lora_cadsymbs_write};
 
 const menu_t Radio::lora_menu[] = {
-    { {FIRST_CHIP_MENU_ROW  ,  1},              NULL,      &lora_bw_item, FLAG_MSGTYPE_ALL },
-    { {FIRST_CHIP_MENU_ROW  , 12},             "sf:",      &lora_sf_item, FLAG_MSGTYPE_ALL },
-    { {FIRST_CHIP_MENU_ROW  , 20},             "cr:",      &lora_cr_item, FLAG_MSGTYPE_ALL },
-    { {FIRST_CHIP_MENU_ROW  , 30}, "PreambleLength:",  &lora_pblLen_item, FLAG_MSGTYPE_ALL },
-    { {FIRST_CHIP_MENU_ROW+1,  1},              NULL,  &lora_fixlen_item, FLAG_MSGTYPE_ALL },
-    { {FIRST_CHIP_MENU_ROW+1, 12},              NULL,   &lora_crcon_item, FLAG_MSGTYPE_ALL },
-    { {FIRST_CHIP_MENU_ROW+1, 25},              NULL,   &lora_iqinv_item, FLAG_MSGTYPE_ALL },
+    { {FIRST_CHIP_MENU_ROW  ,  1},              NULL,     &lora_bw_item, FLAG_MSGTYPE_ALL, &rng_delay_item},
+    { {FIRST_CHIP_MENU_ROW  , 12},             "sf:",     &lora_sf_item, FLAG_MSGTYPE_ALL, &rng_delay_item},
+    { {FIRST_CHIP_MENU_ROW  , 20},             "cr:",     &lora_cr_item, FLAG_MSGTYPE_ALL },
+    { {FIRST_CHIP_MENU_ROW  , 30}, "PreambleLength:", &lora_pblLen_item, FLAG_MSGTYPE_ALL },
+    { {FIRST_CHIP_MENU_ROW+1,  1},              NULL, &lora_fixlen_item, FLAG_MSGTYPE_ALL },
+    { {FIRST_CHIP_MENU_ROW+1, 12},              NULL,  &lora_crcon_item, FLAG_MSGTYPE_ALL },
+    { {FIRST_CHIP_MENU_ROW+1, 25},              NULL,  &lora_iqinv_item, FLAG_MSGTYPE_ALL },
+    { {FIRST_CHIP_MENU_ROW+1, 35},            "ppg:",    &lora_ppg_item, FLAG_MSGTYPE_ALL },
 
     { {FIRST_CHIP_MENU_ROW+2,  1},          NULL,        &lora_cad_item, FLAG_MSGTYPE_ALL },
     { {FIRST_CHIP_MENU_ROW+2,  5},    "symbols:",   &lora_cadsymbs_item, FLAG_MSGTYPE_ALL },
@@ -1524,6 +1628,199 @@
     { {0, 0}, NULL, NULL }
 };
 
+bool Radio::tmp;
+
+bool Radio::rng_role_read()
+{
+    //RngCfg0_t RngCfg0;
+    //RngCfg0.octet = radio.readReg(REG_ADDR_RNGCFG0, 1);
+
+    //return !RngCfg0.bits.ranging_resp_en;
+    //log_printf("%02x ranging_resp_en: %u\r\n", RngCfg0.octet, RngCfg0.bits.ranging_resp_en);
+    return tmp;
+}
+
+bool Radio::rng_role_push()
+{
+    uint8_t buf;
+/*
+    RngCfg0_t RngCfg0;
+    RngCfg0.octet = radio.readReg(REG_ADDR_RNGCFG0, 1);
+
+    buf = RngCfg0.bits.ranging_resp_en ? 0 : 1;
+    log_printf("role %02x  %u\r\n", RngCfg0.octet, buf);
+    radio.xfer(OPCODE_SET_RANGING_ROLE, 1, 0, &buf);
+    return buf;
+*/
+    tmp ^= true;
+    buf = tmp;
+    radio.xfer(OPCODE_SET_RANGING_ROLE, 1, 0, &buf);
+    return tmp;
+}
+
+const toggle_item_t Radio::rng_role_item = { _ITEM_TOGGLE,
+    " SLAVE", // 0
+    "MASTER", // 1
+    rng_role_read, rng_role_push
+};
+
+void Radio::rng_id_send_print()
+{
+    pc.printf("%08x", radio.readReg(REG_ADDR_LORA_MASTER_REQ_ID, 4));
+}
+
+bool Radio::rng_id_send_write(const char* txt)
+{
+    unsigned n;
+    sscanf(txt, "%x", &n);
+    radio.writeReg(REG_ADDR_LORA_MASTER_REQ_ID, n, 4);
+    return false;
+}
+
+const value_item_t Radio::rng_id_send_item = { _ITEM_VALUE, 9, rng_id_send_print, rng_id_send_write};
+
+void Radio::rng_slave_id_print()
+{
+    pc.printf("%08x", radio.readReg(REG_ADDR_LORA_SLAVE_ID, 4));
+}
+
+bool Radio::rng_slave_id_write(const char* txt)
+{
+    unsigned n;
+    sscanf(txt, "%x", &n);
+    radio.writeReg(REG_ADDR_LORA_SLAVE_ID, n, 4);
+    return false;
+}
+
+const value_item_t Radio::rng_slave_id_item = { _ITEM_VALUE, 9, rng_slave_id_print, rng_slave_id_write};
+
+unsigned Radio::rng_idLength_read(bool forWriting)
+{
+    RngDebTh2_t RngDebTh2;
+    RngDebTh2.octet = radio.readReg(REG_ADDR_LORA_RNGDEBTH2, 1);
+    return RngDebTh2.bits.ranging_id_check_length;
+}
+
+menuMode_e Radio::rng_idLength_write(unsigned sidx)
+{
+    RngDebTh2_t RngDebTh2;
+    RngDebTh2.octet = radio.readReg(REG_ADDR_LORA_RNGDEBTH2, 1);
+    RngDebTh2.bits.ranging_id_check_length = sidx;
+    radio.writeReg(REG_ADDR_LORA_RNGDEBTH2, RngDebTh2.octet, 1);
+    return MENUMODE_REDRAW;
+}
+
+static const char* const rngLens[] = {
+    " 8 bits",
+    "16 bits",
+    "24 bits",
+    "32 bits",
+    NULL
+};
+
+const dropdown_item_t Radio::rng_idLength_item = { _ITEM_DROPDOWN, rngLens, rngLens, rng_idLength_read, rng_idLength_write};
+
+
+void Radio::rng_delay_print(void)
+{
+    if (pktType == PACKET_TYPE_RANGING) {
+        pc.printf("%u", radio.readReg(REG_ADDR_LORA_DELAY_CAL, 3) & 0x3fffff);
+    }
+}
+
+bool Radio::rng_delay_write(const char* txt)
+{
+    unsigned n;
+    uint32_t delayCal = radio.readReg(REG_ADDR_LORA_DELAY_CAL, 3);
+    sscanf(txt, "%u", &n);
+    delayCal &= ~0x3fffff;
+    delayCal |= n;
+    radio.writeReg(REG_ADDR_LORA_DELAY_CAL, delayCal, 3);
+
+    manualRngDelay = true;
+    return false;
+}
+
+const value_item_t Radio::rng_delay_item = { _ITEM_VALUE, 7, rng_delay_print, rng_delay_write };
+
+unsigned Radio::rng_resultMux_read(bool)
+{
+    RngCfg1_t RngCfg1;
+    RngCfg1.octet = radio.readReg(REG_ADDR_RNGCFG1, 1);
+    return RngCfg1.bits.ranging_result_mux_sel;
+}
+
+menuMode_e Radio::rng_resultMux_write(unsigned sidx)
+{
+    RngCfg1_t RngCfg1;
+    RngCfg1.octet = radio.readReg(REG_ADDR_RNGCFG1, 1);
+    RngCfg1.bits.ranging_result_mux_sel = sidx;
+    radio.writeReg(REG_ADDR_RNGCFG1, RngCfg1.octet, 1);
+    return MENUMODE_REDRAW;
+}
+
+static const char* const rngResults[] = {
+    "     raw   ",
+    "  rssiAvg  ",
+    " debiased  ",
+    "finalFilter",
+    NULL
+};
+
+const dropdown_item_t Radio::rng_resultMux_item = { _ITEM_DROPDOWN, rngResults, rngResults, rng_resultMux_read, rng_resultMux_write};
+
+
+void Radio::rng_wndFltSize_print()
+{
+    pc.printf("%u", radio.readReg(REG_ADDR_RNGFLTWNDSIZE, 1));
+}
+
+bool Radio::rng_wndFltSize_write(const char* txt)
+{
+    unsigned n;
+    sscanf(txt, "%u", &n);
+    radio.writeReg(REG_ADDR_RNGFLTWNDSIZE, n, 1);
+    return false;
+}
+
+const value_item_t Radio::rng_wndFltSize_item = { _ITEM_VALUE, 4, rng_wndFltSize_print, rng_wndFltSize_write};
+
+
+
+
+void Radio::rng_rngRssiThresh_print()
+{
+    RngDebTh4H_t RngDebTh4H;
+    RngDebTh4H.octet = radio.readReg(REG_ADDR_RNGDEBTH4H, 1);
+    pc.printf("%u", RngDebTh4H.bits.rng_rssi_threshold);
+}
+
+bool Radio::rng_rngRssiThresh_write(const char* txt)
+{
+    unsigned n;
+    RngDebTh4H_t RngDebTh4H;
+    RngDebTh4H.octet = radio.readReg(REG_ADDR_RNGDEBTH4H, 1);
+    sscanf(txt, "%u", &n);
+    RngDebTh4H.bits.rng_rssi_threshold = n;
+    radio.writeReg(REG_ADDR_RNGDEBTH4H, RngDebTh4H.octet, 1);
+    return false;
+}
+
+const value_item_t Radio::rng_rngRssiThresh_item = { _ITEM_VALUE, 4, rng_rngRssiThresh_print, rng_rngRssiThresh_write};
+
+const menu_t Radio::rng_menu[] = {
+    { {FIRST_CHIP_MENU_ROW+2, 19},          NULL,      &rng_role_item, FLAG_MSGTYPE_ALL },
+    { {FIRST_CHIP_MENU_ROW+2, 28}, "ID to send:",      &rng_id_send_item, FLAG_MSGTYPE_ALL },
+    { {FIRST_CHIP_MENU_ROW+2, 49},  "slave ID:",    &rng_slave_id_item, FLAG_MSGTYPE_ALL },
+    { {FIRST_CHIP_MENU_ROW+2, 67},      NULL,    &rng_idLength_item, FLAG_MSGTYPE_ALL },
+    { {FIRST_CHIP_MENU_ROW+3,  1},  "delay:",    &rng_delay_item, FLAG_MSGTYPE_ALL },
+    { {FIRST_CHIP_MENU_ROW+3, 14}, "resultMux:", &rng_resultMux_item, FLAG_MSGTYPE_ALL },
+    { {FIRST_CHIP_MENU_ROW+3, 37}, "windowFilterSize:", &rng_wndFltSize_item, FLAG_MSGTYPE_ALL },
+    { {FIRST_CHIP_MENU_ROW+3, 59}, "rngRssiThresh:", &rng_rngRssiThresh_item, FLAG_MSGTYPE_ALL },
+
+    { {0, 0}, NULL, NULL }
+};
+
 const menu_t Radio::common_menu[] = {
     { {0, 0}, NULL, NULL }
 };
@@ -1543,7 +1840,13 @@
     return NULL;
 }
 
-const menu_t* Radio::get_modem_sub_menu() { return NULL; }
+const menu_t* Radio::get_modem_sub_menu()
+{
+    if (pktType == PACKET_TYPE_RANGING) {
+        return rng_menu;
+    }
+    return NULL;
+}
 
 bool Radio::service(int8_t statusRow)
 {
@@ -1576,6 +1879,9 @@
         }
 
         if (irqFlags.word != prevIrqFlags.word || cmp) {
+            IrqFlags_t clearIrqFlags;
+            clearIrqFlags.word = 0;
+
             pc.printf("\e[%u;1f", statusRow);  // set (force) cursor to row;column
 
             if (cmp) {
@@ -1613,17 +1919,23 @@
                 pc.printf("HeaderError ");
             if (irqFlags.bits.CrcError)
                 pc.printf("CrcError ");
-            if (irqFlags.bits.RangingSlaveResponseDone)
+            if (irqFlags.bits.RangingSlaveResponseDone) {
                 pc.printf("RangingSlaveResponseDone ");
-            if (irqFlags.bits.RangingSlaveRequestDiscard)
+                clearIrqFlags.bits.RangingSlaveResponseDone = 1;
+            } if (irqFlags.bits.RangingSlaveRequestDiscard) {
                 pc.printf("RangingSlaveRequestDiscard ");
-            if (irqFlags.bits.RangingMasterResultValid)
+                clearIrqFlags.bits.RangingSlaveRequestDiscard = 1;
+            } if (irqFlags.bits.RangingMasterResultValid) {
                 pc.printf("RangingMasterResultValid ");
-            if (irqFlags.bits.RangingMasterTimeout)
+            } if (irqFlags.bits.RangingMasterTimeout) {
+                radio.chipMode = CHIPMODE_NONE;
+                chipModeChange();
                 pc.printf("RangingMasterTimeout ");
-            if (irqFlags.bits.RangingMasterRequestValid)
+                clearIrqFlags.bits.RangingMasterTimeout = 1;
+            } if (irqFlags.bits.RangingMasterRequestValid) {
                 pc.printf("RangingMasterRequestValid ");
-            if (irqFlags.bits.CadDone)
+                clearIrqFlags.bits.RangingMasterRequestValid = 1;
+            } if (irqFlags.bits.CadDone)
                 pc.printf("CadDone ");
             if (irqFlags.bits.CadDetected)
                 pc.printf("CadDetected ");
@@ -1636,7 +1948,33 @@
             ret = true;
 
             prevIrqFlags.word = irqFlags.word;
-        }
+
+            if (irqFlags.bits.RangingMasterResultValid) {
+                float m;
+                unsigned rngResult, rngRssi;
+                radio.chipMode = CHIPMODE_NONE;
+                chipModeChange();
+                rngResult = radio.readReg(REG_ADDR_RNGRESULT, 3);
+                // Distance [m] = RangingResult*150/(2^12*BwMHz)
+                m = rngResult * 150 / (4096*bwMHzs[LoRaPktPar0.bits.modem_bw]);
+                rngRssi = radio.readReg(REG_ADDR_RNGRSSI, 1);
+                log_printf("%u rngResult %.2fm, RngRssi:%u bw%.1f\r\n", rngResult, m, rngRssi, bwMHzs[LoRaPktPar0.bits.modem_bw]);
+                clearIrqFlags.bits.RangingMasterResultValid = 1;
+            }
+
+            if (irqFlags.bits.RangingSlaveResponseDone)
+                log_printf("RangingSlaveResponseDone\r\n");
+            if (irqFlags.bits.RangingSlaveRequestDiscard)
+                log_printf("RangingSlaveRequestDiscard\r\n");
+            if (irqFlags.bits.RangingMasterRequestValid)
+                log_printf("RangingMasterRequestValid\r\n");
+
+            if (clearIrqFlags.word != 0) {
+                buf[0] = clearIrqFlags.word >> 8;
+                buf[1] = (uint8_t)clearIrqFlags.word;
+                radio.xfer(OPCODE_CLEAR_IRQ_STATUS, 2, 0, buf);
+            }
+        } // ..if change
 
         prev_now = now;
     }
@@ -1646,7 +1984,45 @@
 
 void Radio::Rx()
 {
-    radio.start_rx(0);
+    if (pktType == PACKET_TYPE_RANGING) {
+        IrqFlags_t irqEnable;
+        uint8_t buf[8];
+
+        if (!manualRngDelay)
+            rngUpdateDelayCal();
+
+        irqEnable.word = 0;
+        irqEnable.bits.RxDone = 1;
+        irqEnable.bits.RxTxTimeout = 1;
+        irqEnable.bits.RangingSlaveResponseDone = 1;
+        irqEnable.bits.RangingSlaveRequestDiscard = 1;
+        irqEnable.bits.RangingMasterRequestValid = 1;
+
+        buf[0] = irqEnable.word >> 8;    // enable bits
+        buf[1] = irqEnable.word; // enable bits
+
+        irqEnable.bits.RangingSlaveResponseDone = 0;
+        irqEnable.bits.RangingSlaveRequestDiscard = 0;
+        irqEnable.bits.RangingMasterRequestValid = 0;
+        buf[2] = irqEnable.word >> 8;     // dio1
+        buf[3] = irqEnable.word;  // dio1
+
+        buf[4] = 0; // dio2
+        buf[5] = 0; // dio2
+        buf[6] = 0; // dio3
+        buf[7] = 0; // dio3
+        radio.xfer(OPCODE_SET_DIO_IRQ_PARAMS, 8, 0, buf);
+
+        buf[0] = radio.periodBase;
+        /* receive packets forever */
+        buf[1] = 0xff;
+        buf[2] = 0xff;
+        radio.xfer(OPCODE_SET_RX, 3, 0, buf);
+
+        radio.chipMode = CHIPMODE_RX;
+        chipModeChange();
+    } else
+        radio.start_rx(0);
 }
 
 void Radio::setFS()
@@ -1654,6 +2030,21 @@
     radio.setFS();
 }
 
-void Radio::test() { }
+void Radio::test()
+{
+/*
+    RngCfg0_t RngCfg0;
+    RngCfg0.octet = radio.readReg(REG_ADDR_RNGCFG0, 1);
+
+    log_printf("Rngcfg0 %02x\r\n", RngCfg0.octet);*/
+    unsigned a;
+    log_printf("%02x ", radio.readReg(0x910, 1));
+    for (a = 0x911; a < 0x980; a++) {
+        pc.printf("%02x ", radio.readReg(a, 1));
+        if ((a & 0x1f) == 0x1f)
+            pc.printf("\r\n%03x ", a+1);
+    }
+    pc.printf("\r\n");
+}
 
 #endif /* ..SX126x_H */
--- a/radio_sx128x_private.h	Wed Aug 22 09:50:32 2018 -0700
+++ b/radio_sx128x_private.h	Thu Nov 01 13:02:38 2018 -0700
@@ -5,6 +5,7 @@
 
         static const menu_t gfsk_menu[];
         static const menu_t flrc_menu[];
+        static const menu_t rng_menu[];
 
         static void rxDone(uint8_t size, const pktStatus_t*);
 
@@ -29,6 +30,51 @@
 
         /*************************************************/
 
+        static bool rng_role_read(void);
+        static bool rng_role_push(void);
+        static const toggle_item_t rng_role_item;
+
+        static bool tmp;
+
+        static void rng_id_send_print(void);
+        static bool rng_id_send_write(const char*);
+        static const value_item_t rng_id_send_item;
+
+        static void rng_slave_id_print(void);
+        static bool rng_slave_id_write(const char*);
+        static const value_item_t rng_slave_id_item;
+
+        static unsigned rng_idLength_read(bool);
+        static menuMode_e rng_idLength_write(unsigned sidx);
+        static const dropdown_item_t rng_idLength_item;
+
+        static void rng_delay_print(void);
+        static bool rng_delay_write(const char*);
+        static const value_item_t rng_delay_item;
+
+        static void rngTx(void);
+
+        static unsigned rng_resultMux_read(bool);
+        static menuMode_e rng_resultMux_write(unsigned sidx);
+        static const dropdown_item_t rng_resultMux_item;
+
+        static void rng_wndFltSize_print(void);
+        static bool rng_wndFltSize_write(const char*);
+        static const value_item_t rng_wndFltSize_item;
+
+        static void rng_rngRssiThresh_print(void);
+        static bool rng_rngRssiThresh_write(const char*);
+        static const value_item_t rng_rngRssiThresh_item;
+
+        static LoRaPktPar0_t LoRaPktPar0;
+        static const float bwMHzs[];
+
+        static const uint16_t rngDelays[3][6];
+        static void rngUpdateDelayCal(void);
+        static bool manualRngDelay;
+
+        /*************************************************/
+
         static void modindex_print(void);
         static bool modindex_write(const char*);
         static const value_item_t gfsk_modindex_item;
@@ -106,6 +152,11 @@
         static bool lora_iqinv_push(void);
         static const toggle_item_t lora_iqinv_item;
 
+        static void lora_ppg_print(void);
+        static bool lora_ppg_write(const char*);
+        static const value_item_t lora_ppg_item;
+        static uint16_t ppg;
+
         static unsigned flrc_cr_read(bool);
         static menuMode_e flrc_cr_write(unsigned sidx);
         static const dropdown_item_t flrc_cr_item;