Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
radio_sx128x.cpp
- Committer:
- Wayne Roberts
- Date:
- 2018-11-01
- Revision:
- 3:56fc764dee0a
- Parent:
- 2:ea9245bb1c53
- Child:
- 4:fa31fdf4ec8d
File content as of revision 3:56fc764dee0a:
#include "radio.h"
#ifdef SX128x_H
#include <float.h>
#ifdef TARGET_FF_ARDUINO /* pins of SX126xDVK1xAS board */
#define NRST_PIN A0
SPI spi(D11, D12, D13); // mosi, miso, sclk
// spi, nss, busy, dio1
SX128x Radio::radio(spi, D7, D3, D5, NRST_PIN);
#define LED_ON 1
#define LED_OFF 0
DigitalOut tx_led(A4);
DigitalOut rx_led(A5);
DigitalOut ant_sw(A3);
DigitalOut cps(D6); // SE2436L
bool fe_enable; // SE2436L
void Radio::chipModeChange()
{
if (radio.chipMode == CHIPMODE_NONE) {
cps = 0;
tx_led = LED_OFF;
rx_led = LED_OFF;
} else if (radio.chipMode == CHIPMODE_TX) {
cps = fe_enable;
tx_led = LED_ON;
rx_led = LED_OFF;
} else if (radio.chipMode == CHIPMODE_RX) {
cps = fe_enable;
tx_led = LED_OFF;
rx_led = LED_ON;
}
}
#endif /* TARGET_FF_ARDUINO */
const char* const Radio::chipNum_str = "SX1280";
uint8_t Radio::tx_param_buf[2];
ModulationParams_t Radio::Radio::mpFLRC, Radio::Radio::mpBLE_GFSK, Radio::mpLORA;
PacketParams_t Radio::ppGFSK, Radio::ppFLRC, Radio::ppLORA, Radio::ppBLE;
const RadioEvents_t* Radio::RadioEvents;
LowPowerTimer Radio::lpt;
uint8_t Radio::pktType;
uint16_t Radio::ppg;
const char* const Radio::pktType_strs[] = {
"GFSK ",
"LORA ",
"RANGING",
"FLRC ",
"BLE ",
NULL
};
unsigned Radio::pktType_read(bool fw)
{
return radio.getPacketType();
}
menuMode_e Radio::pktType_write(unsigned idx)
{
radio.setPacketType(idx);
return MENUMODE_REINIT_MENU;
}
const char* Radio::tx_ramp_strs[] = {
"2 ", // 0
"4 ", // 1
"6 ", // 2
"8 ", // 3
"10", // 4
"12", // 5
"16", // 6
"20", // 7
NULL
};
unsigned Radio::tx_ramp_read(bool fw)
{
PaPwrCtrl_t PaPwrCtrl;
PaPwrCtrl.octet = radio.readReg(REG_ADDR_PA_PWR_CTRL, 1);
switch (PaPwrCtrl.bits.ramp_time) {
case 0: tx_param_buf[1] = RADIO_RAMP_02_US; break;
case 1: tx_param_buf[1] = RADIO_RAMP_04_US; break;
case 2: tx_param_buf[1] = RADIO_RAMP_06_US; break;
case 3: tx_param_buf[1] = RADIO_RAMP_08_US; break;
case 4: tx_param_buf[1] = RADIO_RAMP_10_US; break;
case 5: tx_param_buf[1] = RADIO_RAMP_12_US; break;
case 6: tx_param_buf[1] = RADIO_RAMP_16_US; break;
case 7: tx_param_buf[1] = RADIO_RAMP_20_US; break;
}
return PaPwrCtrl.bits.ramp_time;
}
menuMode_e Radio::tx_ramp_write(unsigned val)
{
switch (val) {
case 0: tx_param_buf[1] = RADIO_RAMP_02_US; break;
case 1: tx_param_buf[1] = RADIO_RAMP_04_US; break;
case 2: tx_param_buf[1] = RADIO_RAMP_06_US; break;
case 3: tx_param_buf[1] = RADIO_RAMP_08_US; break;
case 4: tx_param_buf[1] = RADIO_RAMP_10_US; break;
case 5: tx_param_buf[1] = RADIO_RAMP_12_US; break;
case 6: tx_param_buf[1] = RADIO_RAMP_16_US; break;
case 7: tx_param_buf[1] = RADIO_RAMP_20_US; break;
}
radio.xfer(OPCODE_SET_TX_PARAMS, 2, 0, tx_param_buf);
return MENUMODE_REDRAW;
}
#define TX_PWR_OFFSET 18
void Radio::tx_dbm_print()
{
PaPwrCtrl_t PaPwrCtrl;
PaPwrCtrl.octet = radio.readReg(REG_ADDR_PA_PWR_CTRL, 1);
pc.printf("%d", PaPwrCtrl.bits.tx_pwr - TX_PWR_OFFSET);
tx_param_buf[0] = PaPwrCtrl.bits.tx_pwr;
}
bool Radio::tx_dbm_write(const char* str)
{
int dbm;
sscanf(str, "%d", &dbm);
tx_param_buf[0] = dbm + TX_PWR_OFFSET;
radio.xfer(OPCODE_SET_TX_PARAMS, 2, 0, tx_param_buf);
return false;
}
const uint8_t ramp_us[] = {
2, // 0
4, // 1
6, // 2
8, // 3
10, // 4
12, // 5
16, // 6
20 // 7
};
const char* const Radio::opmode_status_strs[] = {
"<0> ", // 0
"<1> ", // 1
"STDBY_RC ", // 2
"STDBY_XOSC", // 3
"FS ", // 4
"RX ", // 5
"TX ", // 6
"<7> ", // 7
NULL
};
const char* const Radio::opmode_select_strs[] = {
"SLEEP ", // 0
"STDBY_RC ", // 1
"STDBY_XOSC", // 2
"FS ", // 3
"RX ", // 4
"TX ", // 5
NULL
};
unsigned Radio::opmode_read(bool forWriting)
{
status_t status;
status.octet = radio.xfer(OPCODE_GET_STATUS, 0, 0, NULL);
if (forWriting) {
/* translate opmode_status_strs to opmode_select_strs */
switch (status.bits.chipMode) {
case 2: return 1; // STDBY_RC
case 3: return 2; //STDBY_XOSC
case 4: return 3; //FS
case 5: return 4; // RX
case 6: return 5; // TX
default: return 0;
}
} else
return status.bits.chipMode;
}
menuMode_e Radio::opmode_write(unsigned sel)
{
switch (sel) {
case 0: // SLEEP
radio.setSleep(true);
break;
case 1: // STDBY_RC
radio.setStandby(STDBY_RC);
break;
case 2: // STDBY_XOSC
radio.setStandby(STDBY_XOSC);
break; case 3: // FS
radio.setFS();
break;
case 4: // RX
radio.start_rx(0);
break;
case 5: // TX
{
uint8_t buf[3];
buf[0] = radio.periodBase;
buf[0] = 0;
buf[1] = 0;
radio.xfer(OPCODE_SET_TX, 3, 0, buf);
}
break;
} // ..switch (menuState.sel_idx)
return MENUMODE_REDRAW;
}
uint8_t Radio::get_payload_length()
{
uint8_t reg8;
pktType = radio.getPacketType();
switch (pktType) {
case PACKET_TYPE_FLRC:
case PACKET_TYPE_GFSK:
reg8 = radio.readReg(REG_ADDR_PAYLOAD_LEN, 1);
ppGFSK.gfskFLRC.PayloadLength = reg8;
ppFLRC.gfskFLRC.PayloadLength = reg8;
return ppFLRC.gfskFLRC.PayloadLength;
case PACKET_TYPE_RANGING:
case PACKET_TYPE_LORA:
ppLORA.lora.PayloadLength = radio.readReg(REG_ADDR_LORA_TX_PAYLOAD_LENGTH, 1);
return ppLORA.lora.PayloadLength;
case PACKET_TYPE_BLE:
return 0; // TODO BLE
}
return 0;
}
void Radio::set_payload_length(uint8_t len)
{
pktType = radio.getPacketType();
switch (pktType) {
case PACKET_TYPE_FLRC:
ppFLRC.gfskFLRC.PayloadLength = len;
ppGFSK.gfskFLRC.PayloadLength = len;
radio.xfer(OPCODE_SET_PACKET_PARAMS, 7, 0, ppFLRC.buf);
break;
case PACKET_TYPE_GFSK:
ppFLRC.gfskFLRC.PayloadLength = len;
ppGFSK.gfskFLRC.PayloadLength = len;
radio.xfer(OPCODE_SET_PACKET_PARAMS, 7, 0, ppGFSK.buf);
break;
case PACKET_TYPE_RANGING:
case PACKET_TYPE_LORA:
ppLORA.lora.PayloadLength = len;
radio.xfer(OPCODE_SET_PACKET_PARAMS, 5, 0, ppLORA.buf);
break;
case PACKET_TYPE_BLE:
// TODO BLE
break;
}
}
void Radio::tx_payload_length_print()
{
pc.printf("%u", get_payload_length());
}
bool Radio::tx_payload_length_write(const char* txt)
{
unsigned len;
sscanf(txt, "%u", &len);
set_payload_length(len);
return false;
}
void Radio::hw_reset()
{
radio.hw_reset();
manualRngDelay = false;
}
void Radio::clearIrqFlags()
{
uint8_t buf[2];
buf[0] = 0xff;
buf[1] = 0xff;
radio.xfer(OPCODE_CLEAR_IRQ_STATUS, 2, 0, buf);
}
void Radio::readChip()
{
uint8_t reg8;
reg8 = radio.readReg(REG_ADDR_PKTCTRL0, 1);
ppGFSK.gfskFLRC.HeaderType = reg8 & 0x20;
ppFLRC.gfskFLRC.HeaderType = reg8 & 0x20;
reg8 = radio.readReg(REG_ADDR_PKTCTRL1, 1);
ppGFSK.gfskFLRC.PreambleLength = reg8 & 0x70;
ppFLRC.gfskFLRC.PreambleLength = reg8 & 0x70;
ppGFSK.gfskFLRC.SyncWordLength = reg8 & 0x0e;
ppFLRC.gfskFLRC.SyncWordLength = reg8 & 0x06;
if (ppFLRC.gfskFLRC.SyncWordLength == 0x06)
ppFLRC.gfskFLRC.SyncWordLength = FLRC_SYNC_WORD_LEN_P32S;
reg8 = radio.readReg(REG_ADDR_PKT_SYNC_ADRS_CTRL, 1);
ppGFSK.gfskFLRC.SyncWordMatch = reg8 & 0x70;
ppFLRC.gfskFLRC.SyncWordMatch = reg8 & 0x70;
reg8 = radio.readReg(REG_ADDR_PAYLOAD_LEN, 1);
ppGFSK.gfskFLRC.PayloadLength = reg8;
ppFLRC.gfskFLRC.PayloadLength = reg8;
reg8 = radio.readReg(REG_ADDR_PKT_TX_HEADER, 1); // TODO hi bit of payload length
ppBLE.ble.ConnectionState = reg8 & 0xe0;
ppBLE.ble.BleTestPayload = reg8 & 0x1c;
reg8 = radio.readReg(REG_ADDR_PKT_BITSTREAM_CTRL, 1);
ppBLE.ble.CrcLength = reg8 & 0x30;
ppBLE.ble.Whitening = reg8 & 0x08;
ppGFSK.gfskFLRC.CRCLength = reg8 & 0x30;
ppFLRC.gfskFLRC.CRCLength = reg8 & 0x30;
ppGFSK.gfskFLRC.Whitening = reg8 & 0x08;
ppFLRC.gfskFLRC.Whitening = reg8 & 0x08;
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;
LoRaPktPar1.octet = radio.readReg(REG_ADDR_LORA_PKTPAR1, 1);
mpLORA.lora.codingRate = LoRaPktPar1.bits.coding_rate;
ppLORA.lora.InvertIQ = LoRaPktPar1.bits.rxinvert_iq ? LORA_IQ_INVERTED : LORA_IQ_STD;
ppLORA.lora.HeaderType = LoRaPktPar1.bits.implicit_header ? IMPLICIT_HEADER : EXPLICIT_HEADER;
// LoRaPktPar1.bits.ppm_offset
}
{
LoRaPreambleReg_t LoRaPreambleReg;
LoRaPreambleReg.octet = radio.readReg(REG_ADDR_LORA_PREAMBLE, 1);
ppLORA.lora.PreambleLength = LoRaPreambleReg.bits.preamble_symb1_nb * (1 << LoRaPreambleReg.bits.preamble_symb_nb_exp);
}
ppLORA.lora.PayloadLength = radio.readReg(REG_ADDR_LORA_TX_PAYLOAD_LENGTH, 1);
{
LoRaLrCtl_t LoRaLrCtl;
LoRaLrCtl.octet = radio.readReg(REG_ADDR_LORA_LRCTL, 1);
ppLORA.lora.crc = LoRaLrCtl.octet & 0x20; // LoRaLrCtl.bits.crc_en
}
{
RegRxBw_t RegRxBw;
unsigned bps;
FloraPreambleHi_t FloraPreambleHi;
float mi, fdev_hz;
unsigned freqDev;
FskModDfH_t FskModDfH;
FskModDfH.octet = radio.readReg(REG_ADDR_FSK_MODDFH, 1);
freqDev = FskModDfH.bits.freqDev;
freqDev <<= 8;
freqDev |= radio.readReg(REG_ADDR_FSK_MODDFL, 1);
//printf("freqDev %x, %x\r\n", freqDev, freqDev);
fdev_hz = freqDev * PLL_STEP_HZ;
//printf("fdev hz:%f\r\n", fdev_hz);
FloraPreambleHi.octet = radio.readReg(REG_ADDR_FLORA_PREAMBLE_HI, 1);
switch (FloraPreambleHi.bits.data_rate) {
case 0:
bps = 2.0e6;
//mpFLRC.flrc.bitrateBandwidth = ??; // 2.6
break;
case 1:
bps = 1.6e6;
//mpFLRC.flrc.bitrateBandwidth = ??; // 2.08
break;
case 2:
bps = 1.0e6;
mpFLRC.flrc.bitrateBandwidth = FLRC_BR_1_300_BW_1_2; // 1.3
break;
case 3:
bps = 0.8e6;
mpFLRC.flrc.bitrateBandwidth = FLRC_BR_1_000_BW_1_2; // 1.04
break;
case 4:
bps = 0.5e6;
mpFLRC.flrc.bitrateBandwidth = FLRC_BR_0_650_BW_0_6; // 0.65
break;
case 5:
bps = 0.4e6;
mpFLRC.flrc.bitrateBandwidth = FLRC_BR_0_520_BW_0_6; // 0.52
break;
case 6:
bps = 0.25e6;
mpFLRC.flrc.bitrateBandwidth = FLRC_BR_0_325_BW_0_3; // 0.325
break;
case 7:
bps = 0.125e6;
mpFLRC.flrc.bitrateBandwidth = FLRC_BR_0_260_BW_0_3; // 0.26
break;
}
mi = (fdev_hz * 2.0) / bps;
if (mi > 0.35) {
mi -= 0.5;
mi /= 0.25;
mpBLE_GFSK.gfskBle.ModulationIndex = ((uint8_t)mi) + 1;
} else
mpBLE_GFSK.gfskBle.ModulationIndex = 0;
RegRxBw.octet = radio.readReg(REG_ADDR_RXBW, 1);
//printf("rx ");
switch (RegRxBw.bits.bw) {
case 0:
//printf("2.4");
if (FloraPreambleHi.bits.data_rate == 0)
mpBLE_GFSK.gfskBle.bitrateBandwidth = GFSK_BLE_BR_2_000_BW_2_4;
if (FloraPreambleHi.bits.data_rate == 1)
mpBLE_GFSK.gfskBle.bitrateBandwidth = GFSK_BLE_BR_1_600_BW_2_4;
if (FloraPreambleHi.bits.data_rate == 2)
mpBLE_GFSK.gfskBle.bitrateBandwidth = GFSK_BLE_BR_1_000_BW_2_4;
if (FloraPreambleHi.bits.data_rate == 3)
mpBLE_GFSK.gfskBle.bitrateBandwidth = GFSK_BLE_BR_0_800_BW_2_4;
break;
case 1:
//printf("1.2");
if (FloraPreambleHi.bits.data_rate == 2)
mpBLE_GFSK.gfskBle.bitrateBandwidth = GFSK_BLE_BR_1_000_BW_1_2;
if (FloraPreambleHi.bits.data_rate == 3)
mpBLE_GFSK.gfskBle.bitrateBandwidth = GFSK_BLE_BR_0_800_BW_1_2;
if (FloraPreambleHi.bits.data_rate == 4)
mpBLE_GFSK.gfskBle.bitrateBandwidth = GFSK_BLE_BR_0_500_BW_1_2;
if (FloraPreambleHi.bits.data_rate == 5)
mpBLE_GFSK.gfskBle.bitrateBandwidth = GFSK_BLE_BR_0_400_BW_1_2;
break;
case 2:
//printf("0.6");
if (FloraPreambleHi.bits.data_rate == 4)
mpBLE_GFSK.gfskBle.bitrateBandwidth = GFSK_BLE_BR_0_500_BW_0_6;
if (FloraPreambleHi.bits.data_rate == 5)
mpBLE_GFSK.gfskBle.bitrateBandwidth = GFSK_BLE_BR_0_400_BW_0_6;
if (FloraPreambleHi.bits.data_rate == 6)
mpBLE_GFSK.gfskBle.bitrateBandwidth = GFSK_BLE_BR_0_250_BW_0_6;
break;
case 3:
//printf("0.3");
if (FloraPreambleHi.bits.data_rate == 6)
mpBLE_GFSK.gfskBle.bitrateBandwidth = GFSK_BLE_BR_0_250_BW_0_3;
if (FloraPreambleHi.bits.data_rate == 7)
mpBLE_GFSK.gfskBle.bitrateBandwidth = GFSK_BLE_BR_0_125_BW_0_3;
break;
}
//printf("MHz bw:%u\r\n", RegRxBw.bits.bw);
mpBLE_GFSK.gfskBle.bitrateBandwidth = reg8;
}
{
FskCfg_t FskCfg;
FskCfg.octet = radio.readReg(REG_ADDR_FSK_CFG, 1);
//printf("gf_bt:%u\r\n", FskCfg.bits.gf_bt);
mpBLE_GFSK.gfskBle.ModulationShaping = FskCfg.bits.gf_bt << 4;
mpFLRC.flrc.ModulationShaping = mpBLE_GFSK.gfskBle.ModulationShaping;
}
{
PktBitStreamCtrl_t PktBitStreamCtrl;
PktBitStreamCtrl.octet = radio.readReg(REG_ADDR_PKT_BITSTREAM_CTRL, 1);
mpFLRC.flrc.CodingRate = PktBitStreamCtrl.octet & 0x06; // PktBitStreamCtrl.bits.flora_coding_rate
}
}
void Radio::rxDone(uint8_t size, const pktStatus_t* pktStatus)
{
float rssi, snr;
if (pktStatus->ble_gfsk_flrc.sync.syncAddrsCode == 0) {
int8_t s = pktStatus->lora.snr;
rssi = -pktStatus->lora.rssiSync / 2.0;
snr = s / 4.0;
} else {
rssi = -pktStatus->ble_gfsk_flrc.rssiSync / 2.0;
snr = FLT_MIN;
}
RadioEvents->RxDone(size, rssi, snr);
}
void Radio::txDoneBottom()
{
if (RadioEvents->TxDone_botHalf)
RadioEvents->TxDone_botHalf();
}
void Radio::cadDone(bool det)
{
log_printf("cadDone ");
if (det)
pc.printf("CadDetected");
pc.printf("\r\n");
}
void Radio::boardInit(const RadioEvents_t* e)
{
hw_reset();
radio.txDone = txDoneBottom;
radio.rxDone = rxDone;
radio.cadDone = cadDone;
radio.chipModeChange = chipModeChange;
readChip();
RadioEvents = e;
fe_enable = true;
lpt.start();
}
void Radio::tx_carrier()
{
radio.xfer(OPCODE_SET_TX_CARRIER, 0, 0, NULL);
radio.chipMode = CHIPMODE_TX;
chipModeChange();
}
void Radio::tx_preamble()
{
radio.xfer(OPCODE_SET_TX_PREAMBLE, 0, 0, NULL);
radio.chipMode = CHIPMODE_TX;
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;
pktType = radio.getPacketType();
switch (pktType) {
case PACKET_TYPE_FLRC:
case PACKET_TYPE_GFSK:
txlen = radio.readReg(REG_ADDR_PAYLOAD_LEN, 1);
break;
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);
}
#define REGBW_2_4MHZ 0
#define REGBW_1_2MHZ 1
#define REGBW_0_6MHZ 2
#define REGBW_0_3MHZ 3
unsigned Radio::gfsk_flrc_bpsbw_read(bool fw)
{
unsigned n = UINT_MAX;
RegRxBw_t RegRxBw;
FloraPreambleHi_t FloraPreambleHi;
pktType = radio.getPacketType();
FloraPreambleHi.octet = radio.readReg(REG_ADDR_FLORA_PREAMBLE_HI, 1);
RegRxBw.octet = radio.readReg(REG_ADDR_RXBW, 1);
if (pktType == PACKET_TYPE_GFSK) {
switch (FloraPreambleHi.bits.data_rate) {
case 0:
n = 0; // 2Mbps, 2.4MHz
break;
case 1:
n = 1; // 1.6Mbps, 2.4MHz
break;
case 2:
if (RegRxBw.bits.bw == REGBW_2_4MHZ)
n = 2;
else if (RegRxBw.bits.bw == REGBW_1_2MHZ)
n = 3;
break;
case 3:
if (RegRxBw.bits.bw == REGBW_2_4MHZ) // 0.8Mbps 2.4 2.4MHz
n = 4;
else if (RegRxBw.bits.bw == REGBW_1_2MHZ) // 0.8Mbps 1.2MHz
n = 5;
break;
case 4:
if (RegRxBw.bits.bw == REGBW_1_2MHZ) // 0.5Mbps 1.2MHz
n = 6;
else if (RegRxBw.bits.bw == REGBW_0_6MHZ) // 0.5Mbps 0.6MHz
n = 7;
break;
case 5:
if (RegRxBw.bits.bw == REGBW_1_2MHZ) // 0.4Mbps 1.2MHz
n = 8;
else if (RegRxBw.bits.bw == REGBW_0_6MHZ) // 0.4Mbps 0.6MHz
n = 9;
break;
case 6:
if (RegRxBw.bits.bw == REGBW_0_6MHZ) // 0.25Mbps 0.6MHz
n = 10;
else if (RegRxBw.bits.bw == REGBW_0_3MHZ) // 0.25Mbps 0.3MHz
n = 11;
break;
case 7:
n = 12; // 0.125Mbps, assume bw=0.3MHz
break;
} // ..switch (FloraPreambleHi.bits.data_rate)
} else if (pktType == PACKET_TYPE_FLRC) {
n = FloraPreambleHi.bits.data_rate;
// datarate, bits 5,6,7.. bw bits 0,1,2
switch (FloraPreambleHi.bits.data_rate) {
case 0:
break;
case 1:
break;
case 2:
mpFLRC.flrc.bitrateBandwidth = FLRC_BR_1_300_BW_1_2;
break;
case 3:
mpFLRC.flrc.bitrateBandwidth = FLRC_BR_1_000_BW_1_2;
break;
case 4:
mpFLRC.flrc.bitrateBandwidth = FLRC_BR_0_650_BW_0_6;
break;
case 5:
mpFLRC.flrc.bitrateBandwidth = FLRC_BR_0_520_BW_0_6;
break;
case 6:
mpFLRC.flrc.bitrateBandwidth = FLRC_BR_0_325_BW_0_3;
break;
case 7:
mpFLRC.flrc.bitrateBandwidth = FLRC_BR_0_260_BW_0_3;
break;
} // ..switch (FloraPreambleHi.bits.data_rate)
}
return n;
}
menuMode_e Radio::gfsk_flrc_bpsbw_write(unsigned sidx)
{
pktType = radio.getPacketType();
if (pktType == PACKET_TYPE_GFSK) {
switch (sidx) {
case 0: mpBLE_GFSK.gfskBle.bitrateBandwidth = GFSK_BLE_BR_2_000_BW_2_4; break;
case 1: mpBLE_GFSK.gfskBle.bitrateBandwidth = GFSK_BLE_BR_1_600_BW_2_4; break;
case 2: mpBLE_GFSK.gfskBle.bitrateBandwidth = GFSK_BLE_BR_1_000_BW_2_4; break;
case 3: mpBLE_GFSK.gfskBle.bitrateBandwidth = GFSK_BLE_BR_1_000_BW_1_2; break;
case 4: mpBLE_GFSK.gfskBle.bitrateBandwidth = GFSK_BLE_BR_0_800_BW_2_4; break;
case 5: mpBLE_GFSK.gfskBle.bitrateBandwidth = GFSK_BLE_BR_0_800_BW_1_2; break;
case 6: mpBLE_GFSK.gfskBle.bitrateBandwidth = GFSK_BLE_BR_0_500_BW_1_2; break;
case 7: mpBLE_GFSK.gfskBle.bitrateBandwidth = GFSK_BLE_BR_0_500_BW_0_6; break;
case 8: mpBLE_GFSK.gfskBle.bitrateBandwidth = GFSK_BLE_BR_0_400_BW_1_2; break;
case 9: mpBLE_GFSK.gfskBle.bitrateBandwidth = GFSK_BLE_BR_0_400_BW_0_6; break;
case 10: mpBLE_GFSK.gfskBle.bitrateBandwidth = GFSK_BLE_BR_0_250_BW_0_6; break;
case 11: mpBLE_GFSK.gfskBle.bitrateBandwidth = GFSK_BLE_BR_0_250_BW_0_3; break;
case 12: mpBLE_GFSK.gfskBle.bitrateBandwidth = GFSK_BLE_BR_0_125_BW_0_3; break;
}
radio.xfer(OPCODE_SET_MODULATION_PARAMS, 3, 0, mpBLE_GFSK.buf);
} else if (pktType == PACKET_TYPE_FLRC) {
switch (sidx) {
case 2: mpFLRC.flrc.bitrateBandwidth = FLRC_BR_1_300_BW_1_2; break;
case 3: mpFLRC.flrc.bitrateBandwidth = FLRC_BR_1_000_BW_1_2; break;
case 4: mpFLRC.flrc.bitrateBandwidth = FLRC_BR_0_650_BW_0_6; break;
case 5: mpFLRC.flrc.bitrateBandwidth = FLRC_BR_0_520_BW_0_6; break;
case 6: mpFLRC.flrc.bitrateBandwidth = FLRC_BR_0_325_BW_0_3; break;
case 7: mpFLRC.flrc.bitrateBandwidth = FLRC_BR_0_260_BW_0_3; break;
default:
return MENUMODE_REDRAW;
}
radio.xfer(OPCODE_SET_MODULATION_PARAMS, 3, 0, mpFLRC.buf);
}
return MENUMODE_REDRAW;
}
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
" 1.0Mbps 1.2MHz", //3 GFSK_BLE_BR_1_000_BW_1_2 0x45 // Mbps:1 bw:1.2MHz
" 0.8Mbps 2.4MHz", //4 GFSK_BLE_BR_0_800_BW_2_4 0x70 // Mbps:0.8 bw:2.4MHz
" 0.8Mbps 1.2MHz", //5 GFSK_BLE_BR_0_800_BW_1_2 0x69 // Mbps:0.8 bw:1.2MHz
" 0.5Mbps 1.2MHz", //6 GFSK_BLE_BR_0_500_BW_1_2 0x8D // Mbps:0.5 bw:1.2MHz
" 0.5Mbps 0.6MHz", //7 GFSK_BLE_BR_0_500_BW_0_6 0x86 // Mbps:0.5 bw:0.6MHz
" 0.4Mbps 1.2MHz", //8 GFSK_BLE_BR_0_400_BW_1_2 0xB1 // Mbps:0.4 bw:1.2MHz
" 0.4Mbps 0.6MHz", //9 GFSK_BLE_BR_0_400_BW_0_6 0xAA // Mbps:0.4 bw:0.6MHz
" 0.25Mbps 0.6MHz", //10 GFSK_BLE_BR_0_250_BW_0_6 0xCE // Mbps:0.25 bw:0.6MHz
" 0.25Mbps 0.3MHz", //11 GFSK_BLE_BR_0_250_BW_0_3 0xC7 // Mbps:0.25 bw:0.3MHz
"0.125Mbps 0.3MHz", //12 GFSK_BLE_BR_0_125_BW_0_3 0xEF // Mbps:0.125 bw:0.3MHz
// 01234567890123456
NULL
};
const dropdown_item_t Radio::gfsk_bitrate_item = { _ITEM_DROPDOWN, gfsk_bpsbw, gfsk_bpsbw, gfsk_flrc_bpsbw_read, gfsk_flrc_bpsbw_write};
void Radio::modindex_print()
{
float mi, Mbps, fdev_hz;
unsigned bps, freqDev;
FskModDfH_t FskModDfH;
FloraPreambleHi_t FloraPreambleHi;
FloraPreambleHi.octet = radio.readReg(REG_ADDR_FLORA_PREAMBLE_HI, 1);
switch (FloraPreambleHi.bits.data_rate) {
case 0: Mbps = 2.0; break;
case 1: Mbps = 1.6; break;
case 2: Mbps = 1.0; break;
case 3: Mbps = 0.8; break;
case 4: Mbps = 0.5; break;
case 5: Mbps = 0.4; break;
case 6: Mbps = 0.25; break;
case 7: Mbps = 0.125; break;
}
FskModDfH.octet = radio.readReg(REG_ADDR_FSK_MODDFH, 1);
freqDev = FskModDfH.bits.freqDev;
freqDev <<= 8;
freqDev |= radio.readReg(REG_ADDR_FSK_MODDFL, 1);
fdev_hz = freqDev * PLL_STEP_HZ;
bps = Mbps * 1e6;
mi = (fdev_hz * 2.0) / bps;
pc.printf("%.2f", mi);
}
bool Radio::modindex_write(const char* valStr)
{
float f;
if (sscanf(valStr, "%f", &f) == 1) {
log_printf("scanned %f from \"%s\"\r\n", f);
if (f > 0.35) {
f -= 0.5;
f /= 0.25;
log_printf("set modindex:%f\r\n", f);
mpBLE_GFSK.gfskBle.ModulationIndex = ((uint8_t)f) + 1;
log_printf("to set %02x\r\n", mpBLE_GFSK.gfskBle.ModulationIndex);
} else
mpBLE_GFSK.gfskBle.ModulationIndex = 0;
radio.xfer(OPCODE_SET_MODULATION_PARAMS, 3, 0, mpBLE_GFSK.buf);
}
return false;
}
const value_item_t Radio::gfsk_modindex_item = { _ITEM_VALUE, 7, modindex_print, modindex_write };
static const char* const gfsk_flrc_bts[] = {
"off",
"1.0",
"0.5",
"0.3",
NULL
};
unsigned Radio::gfsk_flrc_bt_read(bool fw)
{
FskCfg_t FskCfg;
FskCfg.octet = radio.readReg(REG_ADDR_FSK_CFG, 1);
return FskCfg.bits.gf_bt;
}
menuMode_e Radio::gfsk_flrc_bt_write(unsigned sidx)
{
mpBLE_GFSK.gfskBle.ModulationShaping = sidx << 4;
radio.xfer(OPCODE_SET_MODULATION_PARAMS, 3, 0, mpBLE_GFSK.buf);
return MENUMODE_REDRAW;
}
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* const gfsk_flrc_pblLens[] = {
"4",
"8",
"12",
"16",
"20",
"24",
"28",
"32",
NULL,
};
unsigned Radio::gfsk_flrc_pl_read(bool fw)
{
PktCtrl1_t PktCtrl1;
PktCtrl1.octet = radio.readReg(REG_ADDR_PKTCTRL1, 1);
ppFLRC.gfskFLRC.PreambleLength = PktCtrl1.octet & 0x70;
ppGFSK.gfskFLRC.PreambleLength = ppFLRC.gfskFLRC.PreambleLength;
return PktCtrl1.gfsk.preamble_len;
}
menuMode_e Radio::gfsk_flrc_pl_write(unsigned sidx)
{
ppFLRC.gfskFLRC.PreambleLength = sidx << 4;
ppGFSK.gfskFLRC.PreambleLength = ppFLRC.gfskFLRC.PreambleLength;
radio.xfer(OPCODE_SET_PACKET_PARAMS, 7, 0, ppGFSK.buf);
return MENUMODE_REDRAW;
}
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* const gfsk_syncLens[] = {
"1", // 0
"2", // 1
"3", // 2
"4", // 3
"5", // 4
NULL,
};
unsigned Radio::gfsk_synclen_read(bool fw)
{
PktCtrl1_t PktCtrl1;
PktCtrl1.octet = radio.readReg(REG_ADDR_PKTCTRL1, 1);
ppGFSK.gfskFLRC.SyncWordLength = PktCtrl1.octet & 0x0e;
ppFLRC.gfskFLRC.SyncWordLength = PktCtrl1.octet & 0x06;
return PktCtrl1.gfsk.sync_adrs_len;
}
menuMode_e Radio::gfsk_synclen_write(unsigned sidx)
{
ppGFSK.gfskFLRC.SyncWordLength = sidx << 1;
//log_printf("SWL %u %02x\r\n", sidx, ppGFSK.gfskFLRC.SyncWordLength);
radio.xfer(OPCODE_SET_PACKET_PARAMS, 7, 0, ppGFSK.buf);
//return MENUMODE_NONE;
return MENUMODE_REDRAW;
}
const dropdown_item_t Radio::gfsk_synclen_item = { _ITEM_DROPDOWN, gfsk_syncLens, gfsk_syncLens, gfsk_synclen_read, gfsk_synclen_write};
bool Radio::gfsk_flrc_fixvar_read()
{
PktCtrl0_t PktCtrl0;
PktCtrl0.octet = radio.readReg(REG_ADDR_PKTCTRL0, 1);
ppGFSK.gfskFLRC.HeaderType = PktCtrl0.octet & 0x20;
ppFLRC.gfskFLRC.HeaderType = PktCtrl0.octet & 0x20;
return PktCtrl0.bits.pkt_len_format;
}
bool Radio::gfsk_flrc_fixvar_push()
{
PacketParams_t* pp;
pktType = radio.getPacketType();
if (pktType == PACKET_TYPE_FLRC)
pp = &ppFLRC;
else if (pktType == PACKET_TYPE_GFSK)
pp = &ppGFSK;
else
return false;
if (pp->gfskFLRC.HeaderType == RADIO_PACKET_VARIABLE_LENGTH)
pp->gfskFLRC.HeaderType = RADIO_PACKET_FIXED_LENGTH;
else
pp->gfskFLRC.HeaderType = RADIO_PACKET_VARIABLE_LENGTH;
radio.xfer(OPCODE_SET_PACKET_PARAMS, 7, 0, pp->buf);
return pp->gfskFLRC.HeaderType == RADIO_PACKET_VARIABLE_LENGTH;
}
const toggle_item_t Radio::gfsk_flrc_fixvar_item = { _ITEM_TOGGLE,
"fixed ",
"variable",
gfsk_flrc_fixvar_read, gfsk_flrc_fixvar_push
};
static const char* const gfsk_flrc_crclens[] = {
"0 off",
"1 byte",
"2 bytes",
NULL,
};
unsigned Radio::gfsk_flrc_crclen_read(bool fw)
{
PktBitStreamCtrl_t PktBitStreamCtrl;
PktBitStreamCtrl.octet = radio.readReg(REG_ADDR_PKT_BITSTREAM_CTRL, 1);
ppGFSK.gfskFLRC.CRCLength = PktBitStreamCtrl.octet & 0x30;
return PktBitStreamCtrl.bits.crc_mode;
}
menuMode_e Radio::gfsk_flrc_crclen_write(unsigned sidx)
{
pktType = radio.getPacketType();
ppGFSK.gfskFLRC.CRCLength = (sidx & 3) << 4;
ppFLRC.gfskFLRC.CRCLength = (sidx & 3) << 4;
if (pktType == PACKET_TYPE_GFSK)
radio.xfer(OPCODE_SET_PACKET_PARAMS, 7, 0, ppGFSK.buf);
else if (pktType == PACKET_TYPE_FLRC)
radio.xfer(OPCODE_SET_PACKET_PARAMS, 7, 0, ppFLRC.buf);
return MENUMODE_REDRAW;
}
const dropdown_item_t Radio::gfsk_flrc_crclen_item = { _ITEM_DROPDOWN, gfsk_flrc_crclens, gfsk_flrc_crclens, gfsk_flrc_crclen_read, gfsk_flrc_crclen_write};
bool Radio::gfsk_flrc_whit_read()
{
PktBitStreamCtrl_t PktBitStreamCtrl;
PktBitStreamCtrl.octet = radio.readReg(REG_ADDR_PKT_BITSTREAM_CTRL, 1);
ppGFSK.gfskFLRC.Whitening = PktBitStreamCtrl.octet & 0x08;
ppFLRC.gfskFLRC.Whitening = PktBitStreamCtrl.octet & 0x08;
return PktBitStreamCtrl.bits.whit_disable;
}
bool Radio::gfsk_flrc_whit_push()
{
pktType = radio.getPacketType();
if (ppGFSK.gfskFLRC.Whitening == WHITENING_DISABLE)
ppGFSK.gfskFLRC.Whitening = WHITENING_ENABLE;
else
ppGFSK.gfskFLRC.Whitening = WHITENING_DISABLE;
ppFLRC.gfskFLRC.Whitening = ppGFSK.gfskFLRC.Whitening;
if (pktType == PACKET_TYPE_GFSK)
radio.xfer(OPCODE_SET_PACKET_PARAMS, 7, 0, ppGFSK.buf);
else if (pktType == PACKET_TYPE_FLRC)
radio.xfer(OPCODE_SET_PACKET_PARAMS, 7, 0, ppFLRC.buf);
return ppGFSK.gfskFLRC.Whitening == WHITENING_DISABLE;
}
const toggle_item_t Radio::gfsk_flrc_whit_item = { _ITEM_TOGGLE,
"ENABLE ",
"DISABLE",
gfsk_flrc_whit_read, gfsk_flrc_whit_push
};
void Radio::gfsk_flrc_crcinit_print()
{
unsigned val = radio.readReg(0x9c8, 2);
pc.printf("0x%04x", val);
}
bool Radio::gfsk_flrc_crcinit_write(const char* txt)
{
unsigned val;
sscanf(txt, "%x", &val);
radio.writeReg(0x9c8, val, 2);
return false;
}
const value_item_t Radio::gfsk_flrc_crcinit_item = { _ITEM_VALUE, 7, gfsk_flrc_crcinit_print, gfsk_flrc_crcinit_write };
void Radio::gfsk_flrc_crcpoly_print(void)
{
unsigned val = radio.readReg(0x9c6, 2);
pc.printf("0x%04x", val);
}
bool Radio::gfsk_flrc_crcpoly_write(const char* txt)
{
unsigned val;
sscanf(txt, "%x", &val);
radio.writeReg(0x9c6, val, 2);
return false;
}
const value_item_t Radio::gfsk_flrc_crcpoly_item = { _ITEM_VALUE, 7, gfsk_flrc_crcpoly_print, gfsk_flrc_crcpoly_write };
bool Radio::gfsk_flrc_sync1en_read()
{
PktSyncAdrs_t PktSyncAdrs;
PktSyncAdrs.octet = radio.readReg(REG_ADDR_PKT_SYNC_ADRS_CTRL, 1);
ppGFSK.gfskFLRC.SyncWordMatch = PktSyncAdrs.octet & 0x70;
ppFLRC.gfskFLRC.SyncWordMatch = PktSyncAdrs.octet & 0x70;
return PktSyncAdrs.gfskflrc.sync_addr_mask & 1;
}
bool Radio::gfsk_flrc_sync2en_read()
{
PktSyncAdrs_t PktSyncAdrs;
PktSyncAdrs.octet = radio.readReg(REG_ADDR_PKT_SYNC_ADRS_CTRL, 1);
ppGFSK.gfskFLRC.SyncWordMatch = PktSyncAdrs.octet & 0x70;
ppFLRC.gfskFLRC.SyncWordMatch = PktSyncAdrs.octet & 0x70;
return ppGFSK.gfskFLRC.SyncWordMatch & 0x20;
}
bool Radio::gfsk_flrc_sync3en_read()
{
PktSyncAdrs_t PktSyncAdrs;
PktSyncAdrs.octet = radio.readReg(REG_ADDR_PKT_SYNC_ADRS_CTRL, 1);
ppGFSK.gfskFLRC.SyncWordMatch = PktSyncAdrs.octet & 0x70;
ppFLRC.gfskFLRC.SyncWordMatch = PktSyncAdrs.octet & 0x70;
return ppGFSK.gfskFLRC.SyncWordMatch & 0x40;
//return PktSyncAdrs.gfskflrc.sync_addr_mask & 4;
}
bool Radio::gfsk_flrc_sync1en_push()
{
if (ppGFSK.gfskFLRC.SyncWordMatch & 0x10)
ppGFSK.gfskFLRC.SyncWordMatch &= ~0x10;
else
ppGFSK.gfskFLRC.SyncWordMatch |= 0x10;
radio.xfer(OPCODE_SET_PACKET_PARAMS, 7, 0, ppGFSK.buf);
ppFLRC.gfskFLRC.SyncWordMatch = ppGFSK.gfskFLRC.SyncWordMatch;
return ppGFSK.gfskFLRC.SyncWordMatch & 0x10;
}
bool Radio::gfsk_flrc_sync2en_push()
{
if (ppGFSK.gfskFLRC.SyncWordMatch & 0x20)
ppGFSK.gfskFLRC.SyncWordMatch &= ~0x20;
else
ppGFSK.gfskFLRC.SyncWordMatch |= 0x20;
radio.xfer(OPCODE_SET_PACKET_PARAMS, 7, 0, ppGFSK.buf);
ppFLRC.gfskFLRC.SyncWordMatch = ppGFSK.gfskFLRC.SyncWordMatch;
return ppGFSK.gfskFLRC.SyncWordMatch & 0x20;
}
bool Radio::gfsk_flrc_sync3en_push()
{
if (ppGFSK.gfskFLRC.SyncWordMatch & 0x40)
ppGFSK.gfskFLRC.SyncWordMatch &= ~0x40;
else
ppGFSK.gfskFLRC.SyncWordMatch |= 0x40;
radio.xfer(OPCODE_SET_PACKET_PARAMS, 7, 0, ppGFSK.buf);
ppFLRC.gfskFLRC.SyncWordMatch = ppGFSK.gfskFLRC.SyncWordMatch;
return ppGFSK.gfskFLRC.SyncWordMatch & 0x40;
}
const toggle_item_t Radio::gfsk_flrc_sync1en_item = { _ITEM_TOGGLE, "off:", " ON:", gfsk_flrc_sync1en_read, gfsk_flrc_sync1en_push};
const toggle_item_t Radio::gfsk_flrc_sync2en_item = { _ITEM_TOGGLE, "off:", " ON:", gfsk_flrc_sync2en_read, gfsk_flrc_sync2en_push};
const toggle_item_t Radio::gfsk_flrc_sync3en_item = { _ITEM_TOGGLE, "off:", " ON:", gfsk_flrc_sync3en_read, gfsk_flrc_sync3en_push};
void Radio::gfsk_flrc_sync1_print(void)
{
uint64_t val;
uint32_t val32 = radio.readReg(REG_ADDR_PKT_SYNC_ADRS_1+1, 4);
uint32_t upper = radio.readReg(REG_ADDR_PKT_SYNC_ADRS_1, 1);
val = upper;
val <<= 32;
val |= val32;
pc.printf("%llx", val);
}
void Radio::gfsk_flrc_sync2_print(void)
{
uint64_t val;
uint32_t val32 = radio.readReg(REG_ADDR_PKT_SYNC_ADRS_2+1, 4);
uint32_t upper = radio.readReg(REG_ADDR_PKT_SYNC_ADRS_2, 1);
val = upper;
val <<= 32;
val |= val32;
pc.printf("%llx", val);
}
void Radio::gfsk_flrc_sync3_print(void)
{
uint64_t val;
uint32_t val32 = radio.readReg(REG_ADDR_PKT_SYNC_ADRS_3+1, 4);
uint32_t upper = radio.readReg(REG_ADDR_PKT_SYNC_ADRS_3, 1);
val = upper;
val <<= 32;
val |= val32;
pc.printf("%llx", val);
}
bool Radio::gfsk_flrc_sync1_write(const char* txt)
{
uint32_t val32, upper;
uint64_t val;
sscanf(txt, "%llx", &val);
val32 = val;
val >>= 32;
upper = val;
radio.writeReg(REG_ADDR_PKT_SYNC_ADRS_1, upper, 1);
radio.writeReg(REG_ADDR_PKT_SYNC_ADRS_1+1, val32, 4);
return false;
}
bool Radio::gfsk_flrc_sync2_write(const char* txt)
{
uint32_t val32, upper;
uint64_t val;
sscanf(txt, "%llx", &val);
val32 = val;
val >>= 32;
upper = val;
radio.writeReg(REG_ADDR_PKT_SYNC_ADRS_2, upper, 1);
radio.writeReg(REG_ADDR_PKT_SYNC_ADRS_2+1, val32, 4);
return false;
}
bool Radio::gfsk_flrc_sync3_write(const char* txt)
{
uint32_t val32, upper;
uint64_t val;
sscanf(txt, "%llx", &val);
val32 = val;
val >>= 32;
upper = val;
radio.writeReg(REG_ADDR_PKT_SYNC_ADRS_3, upper, 1);
radio.writeReg(REG_ADDR_PKT_SYNC_ADRS_3+1, val32, 4);
return false;
}
const value_item_t Radio::gfsk_flrc_sync1_item = { _ITEM_VALUE, 10, gfsk_flrc_sync1_print, gfsk_flrc_sync1_write };
const value_item_t Radio::gfsk_flrc_sync2_item = { _ITEM_VALUE, 10, gfsk_flrc_sync2_print, gfsk_flrc_sync2_write };
const value_item_t Radio::gfsk_flrc_sync3_item = { _ITEM_VALUE, 10, gfsk_flrc_sync3_print, gfsk_flrc_sync3_write };
const menu_t Radio::gfsk_menu[] = {
{ {FIRST_CHIP_MENU_ROW, 1}, NULL, &gfsk_bitrate_item, FLAG_MSGTYPE_ALL },
{ {FIRST_CHIP_MENU_ROW, 19}, "mod index:", &gfsk_modindex_item, FLAG_MSGTYPE_ALL },
{ {FIRST_CHIP_MENU_ROW, 35}, "BT:", &gfsk_flrc_bt_item, FLAG_MSGTYPE_ALL },
{ {FIRST_CHIP_MENU_ROW, 43}, "PreambleLength:", &gfsk_flrc_preamble_item, FLAG_MSGTYPE_ALL },
{ {FIRST_CHIP_MENU_ROW, 61}, "SyncLength:", &gfsk_synclen_item, FLAG_MSGTYPE_ALL },
{ {FIRST_CHIP_MENU_ROW+1, 1}, "Length:", &gfsk_flrc_fixvar_item, FLAG_MSGTYPE_ALL },
{ {FIRST_CHIP_MENU_ROW+1, 18}, "crcLength:", &gfsk_flrc_crclen_item, FLAG_MSGTYPE_ALL },
{ {FIRST_CHIP_MENU_ROW+1, 37}, "whitening:", &gfsk_flrc_whit_item, FLAG_MSGTYPE_ALL },
{ {FIRST_CHIP_MENU_ROW+1, 57}, "crcInit:", &gfsk_flrc_crcinit_item, FLAG_MSGTYPE_ALL },
{ {FIRST_CHIP_MENU_ROW+1, 72}, "poly:", &gfsk_flrc_crcpoly_item, FLAG_MSGTYPE_ALL },
{ {FIRST_CHIP_MENU_ROW+2, 1}, "sync1 ", &gfsk_flrc_sync1en_item, FLAG_MSGTYPE_ALL },
{ {FIRST_CHIP_MENU_ROW+2, 15}, NULL, &gfsk_flrc_sync1_item, FLAG_MSGTYPE_ALL },
{ {FIRST_CHIP_MENU_ROW+2, 27}, "sync2 ", &gfsk_flrc_sync2en_item, FLAG_MSGTYPE_ALL },
{ {FIRST_CHIP_MENU_ROW+2, 41}, NULL, &gfsk_flrc_sync2_item, FLAG_MSGTYPE_ALL },
{ {FIRST_CHIP_MENU_ROW+2, 53}, "sync3 ", &gfsk_flrc_sync3en_item, FLAG_MSGTYPE_ALL },
{ {FIRST_CHIP_MENU_ROW+2, 65}, NULL, &gfsk_flrc_sync3_item, FLAG_MSGTYPE_ALL },
{ {0, 0}, NULL, NULL }
};
static const char* const flrc_bpsbw[] = {
"2.6",
"2.08",
"1.3Mb/s 1.2MHz",
"1.04Mb/s 1.2MHz",
"0.65Mb/s 0.6MHz",
"0.52Mb/s 0.6MHz",
"0.325Mb/s 0.3MHz",
"0.26Mb/s 0.3MHz",
NULL
};
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* const flrc_crs[] = {
"1/2",
"3/4",
"1 ",
NULL
};
unsigned Radio::flrc_cr_read(bool fw)
{
PktBitStreamCtrl_t PktBitStreamCtrl;
PktBitStreamCtrl.octet = radio.readReg(REG_ADDR_PKT_BITSTREAM_CTRL, 1);
mpFLRC.flrc.CodingRate = PktBitStreamCtrl.octet & 0x06; // PktBitStreamCtrl.bits.flora_coding_rate
return PktBitStreamCtrl.bits.flora_coding_rate;
}
menuMode_e Radio::flrc_cr_write(unsigned sidx)
{
mpFLRC.flrc.CodingRate = sidx << 1;
radio.xfer(OPCODE_SET_MODULATION_PARAMS, 3, 0, mpFLRC.buf);
return MENUMODE_REDRAW;
}
const dropdown_item_t Radio::flrc_cr_item = { _ITEM_DROPDOWN, flrc_crs, flrc_crs, flrc_cr_read, flrc_cr_write};
static const char* const flrc_syncLens[] = {
"SYNC OFF ",
"16BIT SYNC",
"32BIT SYNC",
NULL
};
unsigned Radio::flrc_synclen_read(bool fw)
{
PktCtrl1_t PktCtrl1;
PktCtrl1.octet = radio.readReg(REG_ADDR_PKTCTRL1, 1);
ppFLRC.gfskFLRC.SyncWordLength = PktCtrl1.octet & 0x06;
if (ppFLRC.gfskFLRC.SyncWordLength == 0x06) {
ppFLRC.gfskFLRC.SyncWordLength = FLRC_SYNC_WORD_LEN_P32S;
return 2;
}
return PktCtrl1.flrc.sync_adrs_len;
}
menuMode_e Radio::flrc_synclen_write(unsigned sidx)
{
ppFLRC.gfskFLRC.SyncWordLength = sidx << 1;
radio.xfer(OPCODE_SET_PACKET_PARAMS, 7, 0, ppFLRC.buf);
return MENUMODE_REDRAW;
}
const dropdown_item_t Radio::flrc_synclen_item = { _ITEM_DROPDOWN, flrc_syncLens, flrc_syncLens, flrc_synclen_read, flrc_synclen_write};
const menu_t Radio::flrc_menu[] = {
{ {FIRST_CHIP_MENU_ROW, 1}, NULL, &flrc_bitrate_item, FLAG_MSGTYPE_ALL },
{ {FIRST_CHIP_MENU_ROW, 20}, "cr:", &flrc_cr_item, FLAG_MSGTYPE_ALL },
{ {FIRST_CHIP_MENU_ROW, 27}, "BT:", &gfsk_flrc_bt_item, FLAG_MSGTYPE_ALL },
{ {FIRST_CHIP_MENU_ROW, 34}, "PreambleLength:", &gfsk_flrc_preamble_item, FLAG_MSGTYPE_ALL },
{ {FIRST_CHIP_MENU_ROW, 52}, "SyncLength:", &flrc_synclen_item, FLAG_MSGTYPE_ALL },
{ {FIRST_CHIP_MENU_ROW+1, 1}, "Length:", &gfsk_flrc_fixvar_item, FLAG_MSGTYPE_ALL },
{ {FIRST_CHIP_MENU_ROW+1, 18}, "crcLength:", &gfsk_flrc_crclen_item, FLAG_MSGTYPE_ALL },
{ {FIRST_CHIP_MENU_ROW+1, 38}, "whitening:", &gfsk_flrc_whit_item, FLAG_MSGTYPE_ALL },
{ {FIRST_CHIP_MENU_ROW+1, 58}, "crcInit:", &gfsk_flrc_crcinit_item, FLAG_MSGTYPE_ALL },
{ {FIRST_CHIP_MENU_ROW+1, 73}, "poly:", &gfsk_flrc_crcpoly_item, FLAG_MSGTYPE_ALL },
{ {FIRST_CHIP_MENU_ROW+2, 1}, "sync1 ", &gfsk_flrc_sync1en_item, FLAG_MSGTYPE_ALL },
{ {FIRST_CHIP_MENU_ROW+2, 12}, NULL, &gfsk_flrc_sync1_item, FLAG_MSGTYPE_ALL },
{ {FIRST_CHIP_MENU_ROW+2, 24}, "sync2 ", &gfsk_flrc_sync2en_item, FLAG_MSGTYPE_ALL },
{ {FIRST_CHIP_MENU_ROW+2, 35}, NULL, &gfsk_flrc_sync2_item, FLAG_MSGTYPE_ALL },
{ {FIRST_CHIP_MENU_ROW+2, 47}, "sync3 ", &gfsk_flrc_sync3en_item, FLAG_MSGTYPE_ALL },
{ {FIRST_CHIP_MENU_ROW+2, 59}, NULL, &gfsk_flrc_sync3_item, FLAG_MSGTYPE_ALL },
{ {0, 0}, NULL, NULL }
};
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
" 400KHz", // 3
" 800KHz", // 4
"1600KHz", // 5
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.octet = radio.readReg(REG_ADDR_LORA_PKTPAR0, 1);
return LoRaPktPar0.bits.modem_bw;
}
menuMode_e Radio::lora_bw_write(unsigned sidx)
{
switch (sidx) {
case 0: mpLORA.lora.bandwidth = LORA_BW_50; break;
case 1: mpLORA.lora.bandwidth = LORA_BW_100; break;
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;
}
radio.xfer(OPCODE_SET_MODULATION_PARAMS, 3, 0, mpLORA.buf);
if (pktType == PACKET_TYPE_RANGING) {
manualRngDelay = false;
rngUpdateDelayCal();
}
return MENUMODE_REDRAW;
}
const dropdown_item_t Radio::lora_bw_item = { _ITEM_DROPDOWN, lora_bws, lora_bws, lora_bw_read, lora_bw_write};
void Radio::lora_sf_print()
{
LoRaPktPar0.octet = radio.readReg(REG_ADDR_LORA_PKTPAR0, 1);
pc.printf("%u", LoRaPktPar0.bits.modem_sf);
}
bool Radio::lora_sf_write(const char* str)
{
unsigned n;
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* const lora_crs[] = {
"4/5 ",
"4/6 ",
"4/7 ",
"4/8 ",
"4/5 LI",
"4/6 LI",
"4/7 LI",
NULL
};
unsigned Radio::lora_cr_read(bool fw)
{
LoRaPktPar1_t LoRaPktPar1;
LoRaPktPar1.octet = radio.readReg(REG_ADDR_LORA_PKTPAR1, 1);
mpLORA.lora.codingRate = LoRaPktPar1.bits.coding_rate;
return LoRaPktPar1.bits.coding_rate;
}
menuMode_e Radio::lora_cr_write(unsigned sidx)
{
mpLORA.lora.codingRate = sidx;
radio.xfer(OPCODE_SET_MODULATION_PARAMS, 3, 0, mpLORA.buf);
return MENUMODE_REDRAW;
}
const dropdown_item_t Radio::lora_cr_item = { _ITEM_DROPDOWN, lora_crs, lora_crs, lora_cr_read, lora_cr_write};
void Radio::lora_pblLen_print()
{
LoRaPreambleReg_t LoRaPreambleReg;
LoRaPreambleReg.octet = radio.readReg(REG_ADDR_LORA_PREAMBLE, 1);
ppLORA.lora.PreambleLength = (1 << LoRaPreambleReg.bits.preamble_symb_nb_exp) * LoRaPreambleReg.bits.preamble_symb1_nb;
pc.printf("%u", ppLORA.lora.PreambleLength);
}
bool Radio::lora_pblLen_write(const char* str)
{
unsigned val, exp, mant;
sscanf(str, "%u", &val);
for (exp = 0; exp < 16; exp++) {
mant = val / (1 << exp);
if (mant < 16)
break;
}
ppLORA.lora.PreambleLength = (exp << 4) + mant;
radio.xfer(OPCODE_SET_PACKET_PARAMS, 5, 0, ppLORA.buf);
return false;
}
const value_item_t Radio::lora_pblLen_item = { _ITEM_VALUE, 5, lora_pblLen_print, lora_pblLen_write};
bool Radio::lora_fixlen_read()
{
LoRaPktPar1_t LoRaPktPar1;
LoRaPktPar1.octet = radio.readReg(REG_ADDR_LORA_PKTPAR1, 1);
ppLORA.lora.HeaderType = LoRaPktPar1.bits.implicit_header ? IMPLICIT_HEADER : EXPLICIT_HEADER;
return LoRaPktPar1.bits.implicit_header;
}
bool Radio::lora_fixlen_push()
{
if (ppLORA.lora.HeaderType == EXPLICIT_HEADER)
ppLORA.lora.HeaderType = IMPLICIT_HEADER;
else
ppLORA.lora.HeaderType = EXPLICIT_HEADER;
radio.xfer(OPCODE_SET_PACKET_PARAMS, 5, 0, ppLORA.buf);
return ppLORA.lora.HeaderType == EXPLICIT_HEADER;
}
const toggle_item_t Radio::lora_fixlen_item = { _ITEM_TOGGLE,
"EXPLICIT", // 0
"IMPLICIT", // 1
lora_fixlen_read, lora_fixlen_push
};
bool Radio::lora_crcon_read()
{
LoRaLrCtl_t LoRaLrCtl;
LoRaLrCtl.octet = radio.readReg(REG_ADDR_LORA_LRCTL, 1);
ppLORA.lora.crc = LoRaLrCtl.octet & 0x20; // LoRaLrCtl.bits.crc_en
return LoRaLrCtl.bits.crc_en;
}
bool Radio::lora_crcon_push()
{
if (ppLORA.lora.crc == LORA_CRC_ENABLE)
ppLORA.lora.crc = LORA_CRC_DISABLE;
else
ppLORA.lora.crc = LORA_CRC_ENABLE;
radio.xfer(OPCODE_SET_PACKET_PARAMS, 5, 0, ppLORA.buf);
return ppLORA.lora.crc == LORA_CRC_ENABLE;
}
const toggle_item_t Radio::lora_crcon_item = { _ITEM_TOGGLE,
"CRC_DISABLE", // 0
"CRC_ENABLE ", // 1
lora_crcon_read, lora_crcon_push
};
bool Radio::lora_iqinv_read()
{
LoRaPktPar1_t LoRaPktPar1;
LoRaPktPar1.octet = radio.readReg(REG_ADDR_LORA_PKTPAR1, 1);
ppLORA.lora.InvertIQ = LoRaPktPar1.bits.rxinvert_iq ? LORA_IQ_STD : LORA_IQ_INVERTED;
return LoRaPktPar1.bits.rxinvert_iq ? 0 : 1;
}
bool Radio::lora_iqinv_push()
{
if (ppLORA.lora.InvertIQ == LORA_IQ_STD)
ppLORA.lora.InvertIQ = LORA_IQ_INVERTED;
else
ppLORA.lora.InvertIQ = LORA_IQ_STD;
radio.xfer(OPCODE_SET_PACKET_PARAMS, 5, 0, ppLORA.buf);
return ppLORA.lora.InvertIQ == LORA_IQ_STD;
}
const toggle_item_t Radio::lora_iqinv_item = { _ITEM_TOGGLE,
"IQ_STD", // 0
"IQ_INV", // 1
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();
}
const button_item_t Radio::lora_cad_item = { _ITEM_BUTTON, "CAD", cad_push };
static const char* const lora_cadsymbs[] = {
" 1",
" 2",
" 4",
" 8",
"16",
NULL
};
unsigned Radio::lora_cadsymbs_read(bool forWriting)
{
unsigned n = radio.readReg(REG_ADDR_LORA_FE_GAIN, 1);
return n >> 5;
}
menuMode_e Radio::lora_cadsymbs_write(unsigned sidx)
{
uint8_t buf = sidx << 5;
radio.xfer(OPCODE_SET_CAD_PARAM, 1, 0, &buf);
return MENUMODE_REDRAW;
}
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, &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 },
{ {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 }
};
const menu_t* Radio::get_modem_menu()
{
pktType = radio.getPacketType();
if (pktType == PACKET_TYPE_RANGING || pktType == PACKET_TYPE_LORA) {
return lora_menu;
} else if (pktType == PACKET_TYPE_FLRC) {
return flrc_menu;
} else if (pktType == PACKET_TYPE_GFSK) {
return gfsk_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)
{
static pktStatus_t prevPktStatus;
static IrqFlags_t prevIrqFlags;
IrqFlags_t irqFlags;
bool ret = false;
static us_timestamp_t prev_now;
us_timestamp_t now = lpt.read_us();
radio.service();
if (statusRow > 0 && now-prev_now > 50000) {
int cmp = 0;
pktStatus_t pktStatus;
uint8_t buf[6];
radio.xfer(OPCODE_GET_IRQ_STATUS, 0, 3, buf);
irqFlags.word = buf[1] << 8;
irqFlags.word |= buf[2];
if (rx_led == LED_ON) {
uint8_t slen;
if (pktType == PACKET_TYPE_LORA || pktType == PACKET_TYPE_RANGING)
slen = 3;
else
slen = 6;
radio.xfer(OPCODE_GET_PACKET_STATUS, 0, slen, pktStatus.buf);
cmp = memcmp(prevPktStatus.buf, pktStatus.buf, slen);
}
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) {
if (pktType == PACKET_TYPE_FLRC || pktType == PACKET_TYPE_BLE || pktType == PACKET_TYPE_GFSK) {
if (pktStatus.ble_gfsk_flrc.errors.SyncError)
pc.printf("SyncError ");
if (pktStatus.ble_gfsk_flrc.errors.LengthError)
pc.printf("LengthError ");
if (pktStatus.ble_gfsk_flrc.errors.CrcError)
pc.printf("CrcError ");
if (pktStatus.ble_gfsk_flrc.errors.AbortErr)
pc.printf("AbortErr ");
if (pktStatus.ble_gfsk_flrc.errors.headerReceived)
pc.printf("headerReceived ");
if (pktStatus.ble_gfsk_flrc.errors.packetReceived)
pc.printf("packetReceived ");
if (pktStatus.ble_gfsk_flrc.errors.pktCtrlBusy)
pc.printf("pktCtrlBusy ");
}
memcpy(prevPktStatus.buf, pktStatus.buf, sizeof(pktStatus_t));
pc.printf(" | ");
}
if (irqFlags.bits.TxDone)
pc.printf("TxDone ");
if (irqFlags.bits.RxDone)
pc.printf("RxDone ");
if (irqFlags.bits.SyncWordValid)
pc.printf("SyncWordValid ");
if (irqFlags.bits.SyncWordError)
pc.printf("SyncWordError ");
if (irqFlags.bits.HeaderValid)
pc.printf("HeaderValid ");
if (irqFlags.bits.HeaderError)
pc.printf("HeaderError ");
if (irqFlags.bits.CrcError)
pc.printf("CrcError ");
if (irqFlags.bits.RangingSlaveResponseDone) {
pc.printf("RangingSlaveResponseDone ");
clearIrqFlags.bits.RangingSlaveResponseDone = 1;
} if (irqFlags.bits.RangingSlaveRequestDiscard) {
pc.printf("RangingSlaveRequestDiscard ");
clearIrqFlags.bits.RangingSlaveRequestDiscard = 1;
} if (irqFlags.bits.RangingMasterResultValid) {
pc.printf("RangingMasterResultValid ");
} if (irqFlags.bits.RangingMasterTimeout) {
radio.chipMode = CHIPMODE_NONE;
chipModeChange();
pc.printf("RangingMasterTimeout ");
clearIrqFlags.bits.RangingMasterTimeout = 1;
} if (irqFlags.bits.RangingMasterRequestValid) {
pc.printf("RangingMasterRequestValid ");
clearIrqFlags.bits.RangingMasterRequestValid = 1;
} if (irqFlags.bits.CadDone)
pc.printf("CadDone ");
if (irqFlags.bits.CadDetected)
pc.printf("CadDetected ");
if (irqFlags.bits.RxTxTimeout)
pc.printf("RxTxTimeout ");
if (irqFlags.bits.PreambleDetected)
pc.printf("PreambleDetected ");
pc.printf("\e[K");
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;
}
return ret;
}
void Radio::Rx()
{
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()
{
radio.setFS();
}
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 */