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_lr1110.cpp
- Committer:
- dudmuck
- Date:
- 15 months ago
- Revision:
- 15:703ca340d0fb
- Parent:
- 13:8ce61a1897ab
File content as of revision 15:703ca340d0fb:
#include "radio.h"
#ifdef SX1265_H
SPI spi(D11, D12, D13); // mosi, miso, sclk
//spi, nss, busy, dio9, nreset
SX1265 Radio::radio(spi, D7, D3, D5, A0, 0x3ffffcf);
#define DIO_en_IDX 0
#define DIO_stby_IDX 1
#define DIO_rx_IDX 2
#define DIO_tx_IDX 3
#define DIO_txhp_IDX 4
#define DIO_gnss_IDX 6
#define DIO_wifi_IDX 7
#define DIO5_BIT 0x01
#define DIO6_BIT 0x02
#define DIO7_BIT 0x04
#define DIO8_BIT 0x08
#define DIO10_BIT 0x10
uint8_t dioBuf[8];
uint8_t Radio::gfsk_pp_buf[9];
uint8_t Radio::gfsk_mp_buf[10];
uint8_t Radio::lora_pp_buf[6];
uint8_t Radio::lora_mp_buf[4];
const RadioEvents_t* Radio::RadioEvents;
uint8_t Radio::pktType;
uint8_t Radio::tx_param_buf[2];
uint8_t Radio::pa_config_buf[4];
unsigned Radio::recalCnt;
uint32_t gfsk_crc_initValue;
uint32_t gfsk_crc_Poly;
uint8_t wifiScan_buf[9];
uint8_t gnssAutonomous_buf[9];
uint8_t gnssAssisted_buf[7];
bool wifiResultFormatBasic;
uint8_t tcxo_buf[5];
void Radio::hw_reset()
{
radio.hw_reset();
//radio.enable_default_irqs();
initRfSwDIO();
}
void Radio::initRfSwDIO()
{
/* antenna truth table
* V1 V2 port
* 0 0 shutdown
* 1 0 J2 rx RFI
* 0 1 J1 HP tx RFO
* 1 1 J3 LP tx RFO
* DIO5 DIO6
* */
dioBuf[ DIO_en_IDX] = DIO5_BIT | DIO6_BIT;
dioBuf[DIO_stby_IDX] = 0;
dioBuf[ DIO_rx_IDX] = DIO5_BIT;
dioBuf[ DIO_tx_IDX] = DIO5_BIT | DIO6_BIT;
dioBuf[DIO_txhp_IDX] = DIO6_BIT;
dioBuf[DIO_gnss_IDX] = 0;
dioBuf[DIO_wifi_IDX] = 0;
radio.xfer(OPCODE_SET_DIO_AS_RFSWITCH, 8, 0, dioBuf);
}
unsigned Radio::my_round(float x)
{
if (x >= 0)
return (unsigned) (x+0.5);
return (unsigned) (x-0.5);
}
void Radio::readChip()
{
uint32_t u32;
{
txParamsB_t txpb; // txpb.bits.PaSel
txParamsC_t txpc;
radio.memRegRead(REG_ADDR_TX_PARAMS_C, 1, &txpc.dword);
tx_param_buf[1] = txpc.bits.pa_ramp_time;
radio.memRegRead(REG_ADDR_TX_PARAMS_B, 1, &txpb.dword);
if (txpb.bits.PaSel)
tx_param_buf[0] = txpc.bits.tx_dbm - 9;
else
tx_param_buf[0] = txpc.bits.tx_dbm - 17;
}
radio.GetPaConfig(pa_config_buf);
{
dioEnable_t dio;
radio.memRegRead(REG_ADDR_DIO10, 1, &dio.dword);
if (dio.bits.enable)
dioBuf[DIO_en_IDX] |= DIO10_BIT;
else
dioBuf[DIO_en_IDX] &= ~DIO10_BIT;
radio.memRegRead(REG_ADDR_DIO8, 1, &dio.dword);
if (dio.bits.enable)
dioBuf[DIO_en_IDX] |= DIO8_BIT;
else
dioBuf[DIO_en_IDX] &= ~DIO8_BIT;
radio.memRegRead(REG_ADDR_DIO7, 1, &dio.dword);
if (dio.bits.enable)
dioBuf[DIO_en_IDX] |= DIO7_BIT;
else
dioBuf[DIO_en_IDX] &= ~DIO7_BIT;
radio.memRegRead(REG_ADDR_DIO6, 1, &dio.dword);
if (dio.bits.enable)
dioBuf[DIO_en_IDX] |= DIO6_BIT;
else
dioBuf[DIO_en_IDX] &= ~DIO6_BIT;
radio.memRegRead(REG_ADDR_DIO5, 1, &dio.dword);
if (dio.bits.enable)
dioBuf[DIO_en_IDX] |= DIO5_BIT;
else
dioBuf[DIO_en_IDX] &= ~DIO5_BIT;
}
{
gfskConfig4_t cfg4;
gfskConfig2_t cfg2;
gfskConfig1_t cfg1;
gfskConfig3_t cfg3;
gfskConfig5_t cfg5;
radio.memRegRead(REG_ADDR_GFSK_CFG5, 1, &cfg5.dword);
gfsk_pp_buf[8] = cfg5.bits.whitening_enable;
if (cfg5.bits.crc_off)
gfsk_pp_buf[7] |= 1;
else
gfsk_pp_buf[7] &= ~1;
if (cfg5.bits.crc_size)
gfsk_pp_buf[7] |= 2;
else
gfsk_pp_buf[7] &= ~2;
if (cfg5.bits.crc_invert)
gfsk_pp_buf[7] |= 4;
else
gfsk_pp_buf[7] &= ~4;
radio.memRegRead(REG_ADDR_GFSK_PAYLOAD_LENGTH_A, 1, &u32);
gfsk_pp_buf[6] = u32 & 0xff;
radio.memRegRead(REG_ADDR_GFSK_PAYLOAD_LENGTH_B, 1, &cfg4.dword);
gfsk_pp_buf[4] = cfg4.bits.addr_comp;
if (cfg4.bits.payload_length != gfsk_pp_buf[6])
log_printf("length_mismatch_%02x_%02x\r\n", cfg4.bits.payload_length, gfsk_pp_buf[6]);
radio.memRegRead(REG_ADDR_GFSK_CFG3, 1, &cfg3.dword);
gfsk_pp_buf[5] = cfg3.bits.variable_length;
radio.memRegRead(REG_ADDR_GFSK_CFG2, 1, &cfg2.dword);
gfsk_pp_buf[3] = cfg2.bits.sync_word_length;
radio.memRegRead(REG_ADDR_GFSK_CFG1, 1, &cfg1.dword);
radio.to_big_endian16(cfg1.bits.preamble_length, gfsk_pp_buf);
if (cfg1.bits.preamble_det_enable)
gfsk_pp_buf[2] = cfg1.bits.preamble_det_len;
else
gfsk_pp_buf[2] = 0;
{
unsigned hz;
radio.memRegRead(REG_ADDR_GFSK_BITRATE, 1, &u32);
hz = GFSK_BITRATE_NUMERATOR / u32;
radio.to_big_endian32(hz, gfsk_mp_buf);
}
//gfsk_mp_buf[4] = bt;
//gfsk_mp_buf[5] = bwf;
//gfsk_mp_buf[6,7,8,9] = fdevHz;
{
unsigned hz;
radio.memRegRead(REG_ADDR_GFSK_FDEV, 1, &u32);
hz = my_round(u32 * FREQ_STEP);
radio.to_big_endian32(hz, gfsk_mp_buf+6);
}
radio.memRegRead(REG_ADDR_GFSK_CRC_INIT, 1, &gfsk_crc_initValue);
radio.memRegRead(REG_ADDR_GFSK_CRC_POLY, 1, &gfsk_crc_Poly);
}
/**********************************************/
{
uint16_t u16;
loraConfig0_t cfg0;
loraConfigB_t cfgb;
loraConfigC_t cfgc;
radio.GetLoRaModulationParameters(lora_mp_buf);
radio.memRegRead(REG_ADDR_LORA_CONFIGC, 1, &cfgc.dword);
u16 = cfgc.bits.preamble_length;
lora_pp_buf[1] = u16 & 0xff;
u16 >>= 8;
lora_pp_buf[0] = u16;
radio.memRegRead(REG_ADDR_LORA_CONFIG0, 1, &cfg0.dword);
lora_pp_buf[2] = cfg0.bits.implicit_header;
lora_pp_buf[3] = cfg0.bits.payload_length;
lora_pp_buf[4] = cfg0.bits.crc_on;
radio.memRegRead(REG_ADDR_LORA_CONFIGB, 1, &cfgb.dword);
lora_pp_buf[5] = cfgb.bits.invertIQ;
}
{ /* wifi scan defaults */
unsigned chanmask = 0x0421;
unsigned timeout = 0x0046;
wifiScan_buf[0] = 0x01; // wifi type
wifiScan_buf[2] = chanmask; // chanmask-lo
chanmask >>= 8;
wifiScan_buf[1] = chanmask; // chanmask-hi
wifiScan_buf[3] = 0x02; // acqMode
wifiScan_buf[4] = 0x0a; // NbMaxRes
wifiScan_buf[5] = 0x06; // NbScanPerChan
wifiScan_buf[7] = timeout; // Timeout-lo
timeout >>= 8;
wifiScan_buf[6] = timeout; // Timeout-hi
wifiScan_buf[8] = 0x00; // AbortOnTimeout
}
}
void Radio::clearIrqFlags()
{
uint8_t buf[4];
buf[0] = buf[1] = buf[2] = buf[3] = 0xff;
radio.xfer(OPCODE_CLEAR_IRQ, 4, 0, buf);
}
uint8_t Radio::get_payload_length()
{
uint8_t pktType = radio.getPacketType();
if (pktType == PACKET_TYPE_LORA) {
unsigned foo;
loraConfig0_t cfg0;
radio.memRegRead(REG_ADDR_LORA_CONFIG0, 1, &cfg0.dword);
foo = cfg0.dword;
foo >>= 24;
lora_pp_buf[3] = cfg0.bits.payload_length;
return cfg0.bits.payload_length;
} else if (pktType == PACKET_TYPE_GFSK) {
uint32_t u32;
/* TODO: which is rx payloadLength vs tx payloadLength */
//gfskConfig4_t cfg4;
radio.memRegRead(REG_ADDR_GFSK_PAYLOAD_LENGTH_A, 1, &u32);
gfsk_pp_buf[6] = u32 & 0xff;
/*radio.memRegRead(REG_ADDR_GFSK_PAYLOAD_LENGTH_B, 1, buf);
cfg4.dword = radio.from_big_endian32(buf);*/
/*
if ((rb & 0xff) != cfg4.bits.payload_length) {
log_printf("gfsk payload length A:%u B:%u\r\n", rb & 0xff, cfg4.bits.payload_length);
// todo: which is tx-length vs rx-length
}
*/
return u32 & 0xff;
}
return 0;
}
bool Radio::tx_payload_length_write(const char* txt)
{
unsigned len;
sscanf(txt, "%u", &len);
set_payload_length(len);
return false;
}
unsigned Radio::read_register(unsigned addr)
{
uint32_t u32;
radio.memRegRead(addr, 1, &u32);
return u32;
}
void Radio::write_register(unsigned addr, unsigned val)
{
stat_t stat;
uint8_t buf[8];
radio.to_big_endian32(addr, buf);
radio.to_big_endian32(val, buf);
stat.word = radio.xfer(OPCODE_WRITEREGMEM32, 8, 0, buf);
print_stat(stat);
}
void Radio::txTimeout_print()
{
float sec = radio.txTimeout / 32768.0;
printf("%.3f", sec);
}
bool Radio::txTimeout_write(const char *txt)
{
float sec;
if (sscanf(txt, "%f", &sec) == 1) {
radio.txTimeout = sec * 32768;
log_printf("txTimeout:%u\r\n", radio.txTimeout);
}
return false;
}
const value_item_t Radio::txTimeout_item = { _ITEM_VALUE, 6, txTimeout_print, txTimeout_write};
bool regulator_read()
{
regulatorMode_t rm;
Radio::radio.memRegRead(REG_ADDR_REGULATOR_MODE, 1, &rm.dword);
return rm.bits.dcdc_en;
}
bool regulator_push()
{
uint8_t buf = regulator_read() ? 0 : 1;
Radio::radio.xfer(OPCODE_SET_REGULATOR_MODE, 1, 0, &buf);
return buf == 1;
}
const toggle_item_t regulator_item = { _ITEM_TOGGLE,
" LDO ",
"DC-DC",
regulator_read,
regulator_push
};
const char* const tcxovolts_strs[]
{
"1.6", // 0
"1.8", // 1
"1.8", // 2
"2.2", // 3
"2.4", // 4
"2.7", // 5
"3.0", // 6
"3.3", // 7
NULL
};
unsigned tcxovolts_read(bool for_writing)
{
tcxo_t tcxo;
Radio::radio.memRegRead(REG_ADDR_TCXO, 1, &tcxo.dword);
return tcxo.bits.volts;
}
menuMode_e tcxovolts_write(unsigned sidx)
{
tcxo_buf[0] = sidx;
Radio::radio.xfer(OPCODE_SET_TCXO_MODE, 5, 0, tcxo_buf);
return MENUMODE_REDRAW;
}
const dropdown_item_t tcxo_volts_item = { _ITEM_DROPDOWN, tcxovolts_strs, tcxovolts_strs, tcxovolts_read, tcxovolts_write};
void tcxo_delay_print()
{
unsigned ticks = tcxo_buf[1];
ticks <<= 8;
ticks |= tcxo_buf[2];
ticks <<= 8;
ticks |= tcxo_buf[3];
printf("%.1f", ticks / 32.768);
}
bool tcxo_delay_write(const char *txt)
{
float ms;
if (sscanf(txt, "%f", &ms) == 1) {
unsigned ticks = ms * 32.768;
Radio::radio.to_big_endian24(ticks, tcxo_buf+1);
Radio::radio.xfer(OPCODE_SET_TCXO_MODE, 5, 0, tcxo_buf);
}
return false;
}
const value_item_t tcxo_delay_item = { _ITEM_VALUE, 5, tcxo_delay_print, tcxo_delay_write};
void recalibrate_print() { }
bool recalibrate_write(const char *txt)
{
unsigned bits;
uint8_t buf = 0;
if (sscanf(txt, "%x", &bits) == 1) {
buf = bits;
}
Radio::radio.xfer(OPCODE_CALIBRATE, 1, 0, &buf);
return false;
}
const value_item_t recalibrate_item = { _ITEM_VALUE, 5, recalibrate_print, recalibrate_write};
void Radio::rxBuffer_push()
{
uint8_t buf[4];
stat_t stat;
stat.word = radio.xfer(OPCODE_GET_RX_BUFFER_STATUS, 0, 0, NULL);
stat.word = radio.xfer(0x0000, 0, 2, buf);
log_printf("rxBufferStatus:%s\r\n", radio.cmdStatus_toString(stat.bits.cmdStatus));
if (stat.bits.cmdStatus == CMD_DAT) {
uint8_t len = buf[0];
uint8_t offset = buf[1];
buf[0] = offset;
buf[1] = len;
stat.word = radio.xfer(OPCODE_READ_BUFFER8, 2, 0, NULL);
log_printf("len%u ofs:%u readBuffer8cmd:%s\r\n", len, offset, radio.cmdStatus_toString(stat.bits.cmdStatus));
stat.word = radio.xfer(0x0000, 0, len, radio.rx_buf);
log_printf("readBuffer8resp:%s\r\n", radio.cmdStatus_toString(stat.bits.cmdStatus));
printRxPkt(len);
}
}
const button_item_t Radio::rxBufferStatus_item = { _ITEM_BUTTON, "rxbufStat", rxBuffer_push};
void Radio::getStats_push(void)
{
uint8_t buf[8];
stat_t stat;
stat.word = radio.xfer(OPCODE_GET_STATS, 0, 0, NULL);
stat.word = radio.xfer(0x0000, 0, 8, buf);
if (stat.bits.cmdStatus == CMD_DAT) {
uint8_t pktType = radio.getPacketType();
uint16_t data1, data2, nbPktCrcErr, nbPktRx = buf[0];
nbPktRx <<= 8;
nbPktRx |= buf[1];
nbPktCrcErr = buf[2];
nbPktCrcErr <<= 8;
nbPktCrcErr |= buf[3];
data1 = buf[4];
data1 <<= 8;
data1 |= buf[5];
data2 = buf[6];
data2 <<= 8;
data2 |= buf[7];
if (pktType == PACKET_TYPE_LORA) {
log_printf("nbPktRx:%u nbPktCrcErr:%u hdrErr:%u falseSync:%u\r\n", nbPktRx, nbPktCrcErr, data1, data2);
} else if (pktType == PACKET_TYPE_GFSK) {
log_printf("nbPktRx:%u nbPktCrcErr:%u nbLenErr:%u\r\n", nbPktRx, nbPktCrcErr, data1);
}
}
}
const button_item_t Radio::getStats_item = { _ITEM_BUTTON, "getStats", getStats_push};
void Radio::txPkt()
{
uint8_t txlen = get_payload_length();
radio.start_tx(txlen);
}
void Radio::Rx()
{
stat_t stat;
uint8_t buf[3];
unsigned rx_timeout = 0xffffff; // receive until instructed not to
radio.to_big_endian24(rx_timeout, buf);
stat.word = radio.xfer(OPCODE_SET_RX, 3, 0, buf);
print_stat(stat);
}
void Radio::tx_carrier()
{
stat_t stat;
stat.word = radio.xfer(OPCODE_SET_TXCW, 0, 0, NULL);
print_stat(stat);
}
void Radio::tx_preamble()
{
stat_t stat;
stat.word = radio.xfer(OPCODE_SET_TX_PREAMBLE, 0, 0, NULL);
print_stat(stat);
}
void Radio::get_rssi()
{
stat_t stat;
uint8_t buf;
stat.word = radio.xfer(OPCODE_GET_RSSI_INST, 0, 0, NULL);
stat.word = radio.xfer(0x0000, 0, 1, &buf);
log_printf("-%0.1f dBm\r\n", buf/2.0);
}
void Radio::print_stat(stat_t stat)
{
char out[96];
char str[24];
out[0] = 0;
if (stat.bits.rfu)
strcat(out, "\e[41m");
if ((stat.word & 0xff) != 0xff) { // xfer returns 0xff for stat2 if stat2 didnt exist
if (stat.bits.bootloader)
strcat(out, "flash ");
else
strcat(out, "bootloader ");
switch (stat.bits.chipMode) {
case 0: strcat(out, "sleep"); break;
case 1: strcat(out, "stby-rc"); break;
case 2: strcat(out, "stby-xtal"); break;
case 3: strcat(out, "\e[33mfs"); break;
case 4: strcat(out, "\e[32mrx"); break;
case 5: strcat(out, "\e[31mtx"); break;
case 6: strcat(out, "\e[36mwifi/gnss"); break;
default:
sprintf(str, "\e[31mchipmode:%u", stat.bits.chipMode);
strcat(out, str);
break;
}
strcat(out, "\e[0m ");
if (stat.bits.resetStatus) {
strcat(out, "reset:");
switch (stat.bits.resetStatus) {
case 1: strcat(out, "analog"); break;
case 2: strcat(out, "pin"); break;
case 3: strcat(out, "system"); break;
case 4: strcat(out, "watchdog"); break;
case 5: strcat(out, "iocd"); break;
case 6: strcat(out, "rtc"); break;
default:
sprintf(str, "<%u>", stat.bits.resetStatus);
strcat(out, str);
break;
}
strcat(out, " ");
}
} // ..if stat2 exists
sprintf(str, " %s ", radio.cmdStatus_toString(stat.bits.cmdStatus));
strcat(out, str);
if (stat.bits.intActive)
strcat(out, "intActive ");
if (stat.bits.rfu)
strcat(out, "\e[0m");
log_printf("%s\r\n", out);
}
void Radio::set_payload_length(uint8_t len)
{
uint8_t *buf_ptr = NULL;
uint8_t buf_len = 0;
uint8_t pktType = radio.getPacketType();
if (pktType == PACKET_TYPE_LORA) {
buf_len = 6;
buf_ptr = lora_pp_buf;
lora_pp_buf[3] = len;
} else if (pktType == PACKET_TYPE_GFSK) {
buf_len = 9;
buf_ptr = gfsk_pp_buf;
gfsk_pp_buf[6] = len;
}
radio.xfer(OPCODE_SET_PACKET_PARAM, buf_len, 0, buf_ptr);
}
bool Radio::PaSel_read()
{
txParamsB_t txpb;
radio.memRegRead(REG_ADDR_TX_PARAMS_B, 1, &txpb.dword);
pa_config_buf[0] = txpb.bits.PaSel;
return txpb.bits.PaSel;
}
bool Radio::PaSel_push()
{
pa_config_buf[0] ^= 1;
radio.xfer(OPCODE_SET_PA_CONFIG, 4, 0, pa_config_buf);
return pa_config_buf[0] == 1;
}
const toggle_item_t Radio::PaSel_item = { _ITEM_TOGGLE, "PaSel:LP", "PaSel:HP", PaSel_read, PaSel_push};
bool Radio::RegPASupply_read()
{
txParamsA_t tpa;
radio.memRegRead(REG_ADDR_TX_PARAMS_A, 1, &tpa.dword);
pa_config_buf[1] = tpa.bits.RegPASupply;
return tpa.bits.RegPASupply;
}
bool Radio::RegPASupply_push(void)
{
pa_config_buf[1] ^= 1;
radio.xfer(OPCODE_SET_PA_CONFIG, 4, 0, pa_config_buf);
return pa_config_buf[1] == 1;
}
const toggle_item_t Radio::RegPASupply_item = { _ITEM_TOGGLE,
"PASupply:intreg",
"PASupply:vbat ",
RegPASupply_read,
RegPASupply_push
};
void Radio::PaDutyCycle_print()
{
txParamsB_t tpb;
radio.memRegRead(REG_ADDR_TX_PARAMS_B, 1, &tpb.dword);
pa_config_buf[2] = tpb.bits.PaDutyCycle;
printf("%u", tpb.bits.PaDutyCycle);
}
bool Radio::PaDutyCycle_write(const char *txt)
{
unsigned n;
if (sscanf(txt, "%u", &n) == 1) {
pa_config_buf[2] = n;
radio.xfer(OPCODE_SET_PA_CONFIG, 4, 0, pa_config_buf);
}
return false;
}
const value_item_t Radio::PaDutyCycle_item = { _ITEM_VALUE, 3, PaDutyCycle_print, PaDutyCycle_write};
void Radio::PaHPSel_print()
{
txParamsB_t tpb;
radio.memRegRead(REG_ADDR_TX_PARAMS_B, 1, &tpb.dword);
pa_config_buf[3] = tpb.bits.PaHPSel;
printf("%u", tpb.bits.PaHPSel);
}
bool Radio::PaHPSel_write(const char *txt)
{
unsigned n;
if (sscanf(txt, "%u", &n) == 1) {
pa_config_buf[3] = n;
radio.xfer(OPCODE_SET_PA_CONFIG, 4, 0, pa_config_buf);
}
return false;
}
const value_item_t Radio::PaHPSel_item = { _ITEM_VALUE, 3, PaHPSel_print, PaHPSel_write};
void Radio::wifiScan_push()
{
radio.xfer(OPCODE_WIFI_SCAN, 9, 0, wifiScan_buf);
log_printf("wifiScan...\r\n");
}
const char* const wifitype_strs[] =
{
"802.11b", // 1
"802.11g", // 2
"802.11n", // 3
" all ", // 4
NULL
};
unsigned wifitype_read(bool for_writing)
{
return wifiScan_buf[0] - 1;
}
menuMode_e wifitype_write(unsigned sidx)
{
wifiScan_buf[0] = sidx + 1;
return MENUMODE_REDRAW;
}
const dropdown_item_t wifiType_item = { _ITEM_DROPDOWN, wifitype_strs, wifitype_strs, wifitype_read, wifitype_write };
bool wifiAcqMode_read()
{
return wifiScan_buf[3] == 2;
}
bool wifiAcqMode_push()
{
wifiScan_buf[3] == 2 ? wifiScan_buf[3] = 1 : wifiScan_buf[3] = 2;
return wifiScan_buf[3] == 2;
}
const toggle_item_t wifiAcqMode_item = { _ITEM_TOGGLE,
"beacon-only ",
"beacon+Packet",
wifiAcqMode_read,
wifiAcqMode_push
};
void wifiNbMaxRes_print()
{
printf("%u", wifiScan_buf[4]);
}
bool wifiNbMaxRes_write(const char *txt)
{
unsigned n;
sscanf(txt, "%u", &n);
wifiScan_buf[4] = n;
return false;
}
const value_item_t wifiNbMaxRes_item = { _ITEM_VALUE, 3, wifiNbMaxRes_print, wifiNbMaxRes_write};
void wifiNbScanPerChan_print()
{
printf("%u", wifiScan_buf[5]);
}
bool wifiNbScanPerChan_write(const char *txt)
{
unsigned n;
sscanf(txt, "%u", &n);
wifiScan_buf[5] = n;
return false;
}
const value_item_t wifiNbScanPerChan_item = { _ITEM_VALUE, 3, wifiNbScanPerChan_print, wifiNbScanPerChan_write};
const button_item_t Radio::wifiScan_item = { _ITEM_BUTTON, "wifiScan", wifiScan_push };
bool wifi_ch14_read() { return (wifiScan_buf[1] & 0x20) == 0x20; }
bool wifi_ch14_push() { wifiScan_buf[1] ^= 0x20; return wifi_ch14_read(); }
const toggle_item_t wifi_ch14_item = { _ITEM_TOGGLE, "ch14", NULL, wifi_ch14_read, wifi_ch14_push};
bool wifi_ch13_read() { return (wifiScan_buf[1] & 0x10) == 0x10; }
bool wifi_ch13_push() { wifiScan_buf[1] ^= 0x10; return wifi_ch13_read(); }
const toggle_item_t wifi_ch13_item = { _ITEM_TOGGLE, "ch13", NULL, wifi_ch13_read, wifi_ch13_push};
bool wifi_ch12_read() { return (wifiScan_buf[1] & 0x08) == 0x08; }
bool wifi_ch12_push() { wifiScan_buf[1] ^= 0x08; return wifi_ch12_read(); }
const toggle_item_t wifi_ch12_item = { _ITEM_TOGGLE, "ch12", NULL, wifi_ch12_read, wifi_ch12_push};
bool wifi_ch11_read() { return (wifiScan_buf[1] & 0x04) == 0x04; }
bool wifi_ch11_push() { wifiScan_buf[1] ^= 0x08; return wifi_ch11_read(); }
const toggle_item_t wifi_ch11_item = { _ITEM_TOGGLE, "ch11", NULL, wifi_ch11_read, wifi_ch11_push};
bool wifi_ch10_read() { return (wifiScan_buf[1] & 0x02) == 0x02; }
bool wifi_ch10_push() { wifiScan_buf[1] ^= 0x02; return wifi_ch10_read(); }
const toggle_item_t wifi_ch10_item = { _ITEM_TOGGLE, "ch10", NULL, wifi_ch10_read, wifi_ch10_push};
bool wifi_ch9_read() { return (wifiScan_buf[1] & 0x01) == 0x01; }
bool wifi_ch9_push() { wifiScan_buf[1] ^= 0x01; return wifi_ch9_read(); }
const toggle_item_t wifi_ch9_item = { _ITEM_TOGGLE, "ch9", NULL, wifi_ch9_read, wifi_ch9_push};
bool wifi_ch8_read() { return (wifiScan_buf[2] & 0x80) == 0x80; }
bool wifi_ch8_push() { wifiScan_buf[2] ^= 0x80; return wifi_ch8_read(); }
const toggle_item_t wifi_ch8_item = { _ITEM_TOGGLE, "ch8", NULL, wifi_ch8_read, wifi_ch8_push};
bool wifi_ch7_read() { return (wifiScan_buf[2] & 0x40) == 0x40; }
bool wifi_ch7_push() { wifiScan_buf[2] ^= 0x40; return wifi_ch7_read(); }
const toggle_item_t wifi_ch7_item = { _ITEM_TOGGLE, "ch7", NULL, wifi_ch7_read, wifi_ch7_push};
bool wifi_ch6_read() { return (wifiScan_buf[2] & 0x20) == 0x20; }
bool wifi_ch6_push() { wifiScan_buf[2] ^= 0x20; return wifi_ch6_read(); }
const toggle_item_t wifi_ch6_item = { _ITEM_TOGGLE, "ch6", NULL, wifi_ch6_read, wifi_ch6_push};
bool wifi_ch5_read() { return (wifiScan_buf[2] & 0x10) == 0x10; }
bool wifi_ch5_push() { wifiScan_buf[2] ^= 0x10; return wifi_ch5_read(); }
const toggle_item_t wifi_ch5_item = { _ITEM_TOGGLE, "ch5", NULL, wifi_ch5_read, wifi_ch5_push};
bool wifi_ch4_read() { return (wifiScan_buf[2] & 0x08) == 0x08; }
bool wifi_ch4_push() { wifiScan_buf[2] ^= 0x08; return wifi_ch4_read(); }
const toggle_item_t wifi_ch4_item = { _ITEM_TOGGLE, "ch4", NULL, wifi_ch4_read, wifi_ch4_push};
bool wifi_ch3_read() { return (wifiScan_buf[2] & 0x04) == 0x04; }
bool wifi_ch3_push() { wifiScan_buf[2] ^= 0x04; return wifi_ch3_read(); }
const toggle_item_t wifi_ch3_item = { _ITEM_TOGGLE, "ch3", NULL, wifi_ch3_read, wifi_ch3_push};
bool wifi_ch2_read() { return (wifiScan_buf[2] & 0x02) == 0x02; }
bool wifi_ch2_push() { wifiScan_buf[2] ^= 0x02; return wifi_ch2_read(); }
const toggle_item_t wifi_ch2_item = { _ITEM_TOGGLE, "ch2", NULL, wifi_ch2_read, wifi_ch2_push};
bool wifi_ch1_read() { return (wifiScan_buf[2] & 0x01) == 0x01; }
bool wifi_ch1_push() { wifiScan_buf[2] ^= 0x01; return wifi_ch1_read(); }
const toggle_item_t wifi_ch1_item = { _ITEM_TOGGLE, "ch1", NULL, wifi_ch1_read, wifi_ch1_push};
void wifiTimeout_print(void)
{
unsigned t;
t = wifiScan_buf[6];
t <<= 8;
t |= wifiScan_buf[7];
printf("%u", t);
}
bool wifiTimeout_write(const char *txt)
{
unsigned t;
sscanf(txt, "%u", &t);
wifiScan_buf[7] = t;
t >>= 8;
wifiScan_buf[6] = t;
return false;
}
const value_item_t wifiTimeout_item = { _ITEM_VALUE, 6, wifiTimeout_print, wifiTimeout_write};
bool AbortOnTimeout_read()
{
return wifiScan_buf[8] == 1;
}
bool AbortOnTimeout_push()
{
wifiScan_buf[8] ^= 1;
return wifiScan_buf[8] == 1;
}
const toggle_item_t wifiAbort_item = { _ITEM_TOGGLE, "AbortOnTimeout", NULL, AbortOnTimeout_read, AbortOnTimeout_push};
bool wifiResultFormat_read()
{
// false=full, true=basic
return wifiResultFormatBasic;
}
bool wifiResultFormat_push()
{
// false=full, true=basic
wifiResultFormatBasic ^= true;
return wifiResultFormatBasic;
}
const toggle_item_t wifiResultFormat_item = { _ITEM_TOGGLE,
"full ",
"basic",
wifiResultFormat_read,
wifiResultFormat_push
};
void Radio::gnssAutonomous_push()
{
gnssAutonomous_buf[4] = 0; // EffortMode
radio.xfer(OPCODE_GNSS_AUTONOMOUS, 7, 0, gnssAutonomous_buf);
log_printf("gnssAutonomous...\r\n");
}
const button_item_t Radio::gnssAutonomous_item = { _ITEM_BUTTON, "gnssAutonomous", gnssAutonomous_push };
void gnssAutonomous_time_print()
{
unsigned t = Radio::radio.from_big_endian32(gnssAutonomous_buf);
printf("%u", t);
}
bool gnssAutonomous_time_write(const char *txt)
{
unsigned t;
if (sscanf(txt, "%u", &t) == 1) {
Radio::radio.to_big_endian32(t, gnssAutonomous_buf);
}
return false;
}
bool gnssAutoResultTimeStamp_read()
{
return (gnssAutonomous_buf[5] & 0x01) == 0x01;
}
bool gnssAutoResultTimeStamp_push()
{
gnssAutonomous_buf[5] ^= 0x01;
return (gnssAutonomous_buf[5] & 0x01) == 0x01;
}
const toggle_item_t gnssAutoResultTimeStamp_item = { _ITEM_TOGGLE, "timestamp", NULL, gnssAutoResultTimeStamp_read, gnssAutoResultTimeStamp_push};
bool gnssAutoResultDoppler_read()
{
return (gnssAutonomous_buf[5] & 0x02) == 0x02;
}
bool gnssAutoResultDoppler_push()
{
gnssAutonomous_buf[5] ^= 0x02;
return (gnssAutonomous_buf[5] & 0x02) == 0x02;
}
const toggle_item_t gnssAutoResultDoppler_item = { _ITEM_TOGGLE, "doppler", NULL, gnssAutoResultDoppler_read, gnssAutoResultDoppler_push};
bool gnssAutoResultBitChange_read()
{
return (gnssAutonomous_buf[5] & 0x04) == 0x04;
}
bool gnssAutoResultBitChange_push()
{
gnssAutonomous_buf[5] ^= 0x04;
return (gnssAutonomous_buf[5] & 0x04) == 0x04;
}
const toggle_item_t gnssAutoResultBitChange_item = { _ITEM_TOGGLE, "bit change", NULL, gnssAutoResultBitChange_read, gnssAutoResultBitChange_push};
void gnssAutoNbSvMax_print()
{
printf("%u", gnssAutonomous_buf[6]);
}
bool gnssAutoNbSvMax_write(const char *txt)
{
unsigned n;
sscanf(txt, "%u", &n);
gnssAutonomous_buf[6] = n;
return false;
}
const value_item_t gnssAutoNbSvMax_item = { _ITEM_VALUE, 3, gnssAutoNbSvMax_print, gnssAutoNbSvMax_write};
const value_item_t gnssAutonomous_time_item = { _ITEM_VALUE, 9, gnssAutonomous_time_print, gnssAutonomous_time_write};
void Radio::gnssAssisted_push()
{
gnssAssisted_buf[5] = 3; // ResultMask
radio.xfer(OPCODE_GNSS_ASSISTED, 7, 0, gnssAssisted_buf);
log_printf("gnssAssisted...\r\n");
}
const button_item_t Radio::gnssAssisted_item = { _ITEM_BUTTON, "gnssAssisted", gnssAssisted_push};
void gnssAssisted_time_print()
{
unsigned t = Radio::radio.from_big_endian32(gnssAssisted_buf);
printf("%u", t);
}
bool gnssAssisted_time_write(const char *txt)
{
unsigned t;
if (sscanf(txt, "%u", &t) == 1) {
Radio::radio.to_big_endian32(t, gnssAssisted_buf);
}
return false;
}
const value_item_t gnssAssisted_time_item = { _ITEM_VALUE, 9, gnssAssisted_time_print, gnssAssisted_time_write};
bool gnssAssisted_effort_read()
{
return gnssAssisted_buf[4] == 0x01;
}
bool gnssAssisted_effort_push()
{
gnssAssisted_buf[4] ^= 0x01;
return gnssAssisted_buf[4] == 0x01;
}
const toggle_item_t gnssAssisted_effort_item = { _ITEM_TOGGLE,
"lowPower",
"best ",
gnssAssisted_effort_read,
gnssAssisted_effort_push
};
void gnssAssisted_nbsvmax_print()
{
printf("%u", gnssAssisted_buf[6]);
}
bool gnssAssisted_nbsvmax_write(const char *txt)
{
unsigned n;
sscanf(txt, "%u", &n);
gnssAssisted_buf[6] = n;
return false;
}
const value_item_t gnssAssisted_nbsvmax_item = { _ITEM_VALUE, 3, gnssAssisted_nbsvmax_print, gnssAssisted_nbsvmax_write};
bool gnss_const_gps_enable_read()
{
gnssConstellation_t gc;
Radio::radio.memRegRead(REG_ADDR_GNSS_CONST, 1, &gc.dword);
return gc.bits.gps;
}
bool gnss_const_gps_enable_push()
{
uint8_t ConstellationBitMask = 0;
gnssConstellation_t gc;
Radio::radio.memRegRead(REG_ADDR_GNSS_CONST, 1, &gc.dword);
if (gc.bits.gps)
ConstellationBitMask &= ~1;
else
ConstellationBitMask |= 1;
if (gc.bits.beidou)
ConstellationBitMask |= 2;
Radio::radio.xfer(OPCODE_GNSS_SET_CONSTELLATION, 1, 0, &ConstellationBitMask);
return ConstellationBitMask & 1;
}
const toggle_item_t gnss_const_gps_enable_item = { _ITEM_TOGGLE, "GPS", NULL, gnss_const_gps_enable_read, gnss_const_gps_enable_push};
bool gnss_const_beidou_enable_read()
{
gnssConstellation_t gc;
Radio::radio.memRegRead(REG_ADDR_GNSS_CONST, 1, &gc.dword);
return gc.bits.beidou;
}
bool gnss_const_beidou_enable_push()
{
uint8_t ConstellationBitMask = 0;
gnssConstellation_t gc;
Radio::radio.memRegRead(REG_ADDR_GNSS_CONST, 1, &gc.dword);
if (gc.bits.beidou)
ConstellationBitMask &= ~2;
else
ConstellationBitMask |= 2;
if (gc.bits.gps)
ConstellationBitMask |= 1;
Radio::radio.xfer(OPCODE_GNSS_SET_CONSTELLATION, 1, 0, &ConstellationBitMask);
return ConstellationBitMask & 1;
}
const toggle_item_t gnss_const_beidou_enable_item = { _ITEM_TOGGLE, "BEIDOU", NULL, gnss_const_beidou_enable_read, gnss_const_beidou_enable_push};
bool gnssmode_read()
{
gnssMode_t gm;
Radio::radio.memRegRead(REG_ADDR_GNSS_MODE, 1, &gm.dword);
return gm.bits.gnss_scan_single;
}
bool gnssmode_push()
{
uint8_t buf = gnssmode_read(); // GnssSetMode takes 1 for dual-scan
Radio::radio.xfer(OPCODE_GNSS_SET_MODE, 1, 0, &buf);
return buf == 0;
}
const toggle_item_t gnss_mode_item = { _ITEM_TOGGLE,
"dual ",
"single",
gnssmode_read,
gnssmode_push
};
const menu_t Radio::common_menu[] = {
{ {FIRST_CHIP_MENU_ROW, 1}, NULL, &PaSel_item, FLAG_MSGTYPE_ALL, &tx_dbm_item},
{ {FIRST_CHIP_MENU_ROW, 10}, NULL, &RegPASupply_item, FLAG_MSGTYPE_ALL},
{ {FIRST_CHIP_MENU_ROW, 30}, "PaDutyCycle:", &PaDutyCycle_item, FLAG_MSGTYPE_ALL},
{ {FIRST_CHIP_MENU_ROW, 47}, "PaHPSel:", &PaHPSel_item, FLAG_MSGTYPE_ALL},
{ {FIRST_CHIP_MENU_ROW+1, 1}, "regulator:", ®ulator_item, FLAG_MSGTYPE_ALL},
{ {FIRST_CHIP_MENU_ROW+1, 18}, "tcxoVolts:", &tcxo_volts_item, FLAG_MSGTYPE_ALL},
{ {FIRST_CHIP_MENU_ROW+1, 32}, "tcxoDelay(ms):", &tcxo_delay_item, FLAG_MSGTYPE_ALL},
{ {FIRST_CHIP_MENU_ROW+1, 52}, "re-cal(hex):", &recalibrate_item, FLAG_MSGTYPE_ALL},
//012345678901234567890
{ {FIRST_CHIP_MENU_ROW+2, 1}, "txTimeout(sec):", &txTimeout_item, FLAG_MSGTYPE_ALL},
{ {FIRST_CHIP_MENU_ROW+2, 24}, NULL, &rxBufferStatus_item, FLAG_MSGTYPE_ALL},
{ {FIRST_CHIP_MENU_ROW+2, 35}, NULL, &getStats_item, FLAG_MSGTYPE_ALL},
{ {FIRST_CHIP_MENU_ROW+10, 1}, NULL, &wifiScan_item, FLAG_MSGTYPE_ALL},
{ {FIRST_CHIP_MENU_ROW+10, 10}, NULL, &wifiType_item, FLAG_MSGTYPE_ALL},
{ {FIRST_CHIP_MENU_ROW+10, 19}, NULL, &wifiAcqMode_item, FLAG_MSGTYPE_ALL},
{ {FIRST_CHIP_MENU_ROW+10, 35}, "NbMaxRes:", &wifiNbMaxRes_item, FLAG_MSGTYPE_ALL},
{ {FIRST_CHIP_MENU_ROW+10, 48}, "NbScanPerChan:", &wifiNbScanPerChan_item, FLAG_MSGTYPE_ALL},
{ {FIRST_CHIP_MENU_ROW+11, 1}, "timeout(ms):", &wifiTimeout_item, FLAG_MSGTYPE_ALL},
{ {FIRST_CHIP_MENU_ROW+11, 20}, NULL, &wifiAbort_item, FLAG_MSGTYPE_ALL},
{ {FIRST_CHIP_MENU_ROW+11, 45}, "resultFormat:", &wifiResultFormat_item, FLAG_MSGTYPE_ALL},
{ {FIRST_CHIP_MENU_ROW+12, 1}, NULL, &wifi_ch14_item, FLAG_MSGTYPE_ALL},
{ {FIRST_CHIP_MENU_ROW+12, 6}, NULL, &wifi_ch13_item, FLAG_MSGTYPE_ALL},
{ {FIRST_CHIP_MENU_ROW+12, 11}, NULL, &wifi_ch12_item, FLAG_MSGTYPE_ALL},
{ {FIRST_CHIP_MENU_ROW+12, 16}, NULL, &wifi_ch11_item, FLAG_MSGTYPE_ALL},
{ {FIRST_CHIP_MENU_ROW+12, 21}, NULL, &wifi_ch10_item, FLAG_MSGTYPE_ALL},
{ {FIRST_CHIP_MENU_ROW+12, 26}, NULL, &wifi_ch9_item, FLAG_MSGTYPE_ALL},
{ {FIRST_CHIP_MENU_ROW+12, 31}, NULL, &wifi_ch8_item, FLAG_MSGTYPE_ALL},
{ {FIRST_CHIP_MENU_ROW+12, 36}, NULL, &wifi_ch7_item, FLAG_MSGTYPE_ALL},
{ {FIRST_CHIP_MENU_ROW+12, 41}, NULL, &wifi_ch6_item, FLAG_MSGTYPE_ALL},
{ {FIRST_CHIP_MENU_ROW+12, 46}, NULL, &wifi_ch5_item, FLAG_MSGTYPE_ALL},
{ {FIRST_CHIP_MENU_ROW+12, 51}, NULL, &wifi_ch4_item, FLAG_MSGTYPE_ALL},
{ {FIRST_CHIP_MENU_ROW+12, 56}, NULL, &wifi_ch3_item, FLAG_MSGTYPE_ALL},
{ {FIRST_CHIP_MENU_ROW+12, 61}, NULL, &wifi_ch2_item, FLAG_MSGTYPE_ALL},
{ {FIRST_CHIP_MENU_ROW+12, 66}, NULL, &wifi_ch1_item, FLAG_MSGTYPE_ALL},
{ {FIRST_CHIP_MENU_ROW+13, 1}, NULL, &gnss_const_gps_enable_item, FLAG_MSGTYPE_ALL},
{ {FIRST_CHIP_MENU_ROW+13, 5}, NULL, &gnss_const_beidou_enable_item, FLAG_MSGTYPE_ALL},
{ {FIRST_CHIP_MENU_ROW+13, 12}, "scanning:", &gnss_mode_item, FLAG_MSGTYPE_ALL},
{ {FIRST_CHIP_MENU_ROW+14, 1}, NULL, &gnssAutonomous_item, FLAG_MSGTYPE_ALL},
{ {FIRST_CHIP_MENU_ROW+14, 16}, "time:", &gnssAutonomous_time_item, FLAG_MSGTYPE_ALL},
{ {FIRST_CHIP_MENU_ROW+14, 31}, NULL, &gnssAutoResultTimeStamp_item, FLAG_MSGTYPE_ALL},
{ {FIRST_CHIP_MENU_ROW+14, 41}, NULL, &gnssAutoResultDoppler_item, FLAG_MSGTYPE_ALL},
{ {FIRST_CHIP_MENU_ROW+14, 51}, NULL, &gnssAutoResultBitChange_item, FLAG_MSGTYPE_ALL},
{ {FIRST_CHIP_MENU_ROW+14, 63}, "NbSvMax:", &gnssAutoNbSvMax_item, FLAG_MSGTYPE_ALL},
{ {FIRST_CHIP_MENU_ROW+15, 1}, NULL, &gnssAssisted_item, FLAG_MSGTYPE_ALL},
{ {FIRST_CHIP_MENU_ROW+15, 16}, "time:", &gnssAssisted_time_item, FLAG_MSGTYPE_ALL},
{ {FIRST_CHIP_MENU_ROW+15, 30}, "effort:", &gnssAssisted_effort_item, FLAG_MSGTYPE_ALL},
{ {FIRST_CHIP_MENU_ROW+15, 50}, "NbSvMax::", &gnssAssisted_nbsvmax_item, FLAG_MSGTYPE_ALL},
//0123456789012345
{ {0, 0}, NULL, NULL }
};
void Radio::gfsk_bitrate_print()
{
uint32_t u32;
unsigned hz;
radio.memRegRead(REG_ADDR_GFSK_BITRATE, 1, &u32);
hz = GFSK_BITRATE_NUMERATOR / u32;
printf("%u", hz);
radio.to_big_endian32(hz, gfsk_mp_buf);
}
bool Radio::gfsk_bitrate_write(const char* txt)
{
unsigned bps;
if (sscanf(txt, "%u", &bps) == 1) {
radio.to_big_endian32(bps, gfsk_mp_buf);
radio.xfer(OPCODE_SET_MODULATION, 10, 0, gfsk_mp_buf);
}
return false;
}
const value_item_t Radio::gfsk_bitrate_item = { _ITEM_VALUE, 8, gfsk_bitrate_print, gfsk_bitrate_write};
static const char* const gfsk_bts[] = {
"off", // 0
"0.3", // 1
"0.5", // 2
"0.7", // 3
"1.0", // 4
NULL
};
unsigned Radio::gfsk_bt_read(bool forWriting)
{
gfskConfig0_t cfg0;
radio.memRegRead(REG_ADDR_GFSK_CFG0, 1, &cfg0.dword);
if (cfg0.bits.shaping_en) {
switch (cfg0.bits.bt) {
case 0: /* off */ gfsk_mp_buf[4] = GFSK_BT_OFF; break;
case 1: /* 0.3 */ gfsk_mp_buf[4] = GFSK_BT_0_3; break;
case 2: /* 0.5 */ gfsk_mp_buf[4] = GFSK_BT_0_5; break;
case 3: /* 0.7 */ gfsk_mp_buf[4] = GFSK_BT_0_7; break;
case 4: /* 1.0 */ gfsk_mp_buf[4] = GFSK_BT_1_0; break;
}
return cfg0.bits.bt + 1;
} else
return 0;
}
menuMode_e Radio::gfsk_bt_write(unsigned sidx)
{
switch (sidx) {
case 0: gfsk_mp_buf[4] = GFSK_BT_OFF; break;
case 1: gfsk_mp_buf[4] = GFSK_BT_0_3; break;
case 2: gfsk_mp_buf[4] = GFSK_BT_0_5; break;
case 3: gfsk_mp_buf[4] = GFSK_BT_0_7; break;
case 4: gfsk_mp_buf[4] = GFSK_BT_1_0; break;
}
radio.xfer(OPCODE_SET_MODULATION, 10, 0, gfsk_mp_buf);
return MENUMODE_REDRAW;
}
const dropdown_item_t Radio::gfsk_bt_item = { _ITEM_DROPDOWN, gfsk_bts, gfsk_bts, gfsk_bt_read, gfsk_bt_write};
void Radio::gfsk_rxbw_print()
{
unsigned n;
uint8_t bwf;
gfskBW_t bw_reg;
radio.memRegRead(REG_ADDR_GFSK_BWF, 1, &bw_reg.dword);
bwf = bw_reg.bits.bwf_hi;
bwf <<= 3;
bwf |= bw_reg.bits.bwf_lo;
gfsk_mp_buf[5] = bwf;
for (n = 0; n < NB_RXBW; n++) {
if (rxbws[n].bwf == bwf) {
printf("%u", rxbws[n].hz);
break;
}
}
}
rxbw_t Radio::rxbws[] = {
/* 0 */ { 4800, GFSK_RX_BW_4800 },
/* 1 */ { 5800, GFSK_RX_BW_5800 },
/* 2 */ { 7300, GFSK_RX_BW_7300 },
/* 3 */ { 9700, GFSK_RX_BW_9700 },
/* 4 */ { 11700, GFSK_RX_BW_11700 },
/* 5 */ { 14600, GFSK_RX_BW_14600 },
/* 6 */ { 19500, GFSK_RX_BW_19500 },
/* 7 */ { 23400, GFSK_RX_BW_23400 },
/* 8 */ { 29300, GFSK_RX_BW_29300 },
/* 9 */ { 39000, GFSK_RX_BW_39000 },
/* 10 */ { 46900, GFSK_RX_BW_46900 },
/* 11 */ { 58600, GFSK_RX_BW_58600 },
/* 12 */ { 78200, GFSK_RX_BW_78200 },
/* 13 */ { 93800, GFSK_RX_BW_93800 },
/* 14 */ { 117300, GFSK_RX_BW_117300 },
/* 15 */ { 156200, GFSK_RX_BW_156200 },
/* 16 */ { 187200, GFSK_RX_BW_187200 },
/* 17 */ { 234300, GFSK_RX_BW_234300 },
/* 18 */ { 312000, GFSK_RX_BW_312000 },
/* 19 */ { 373600, GFSK_RX_BW_373600 },
/* 20 */ { 467000, GFSK_RX_BW_467000 }
};
bool Radio::gfsk_rxbw_write(const char* txt)
{
unsigned n, rxbw;
if (sscanf(txt, "%u", &rxbw) == 1) {
for (n = 1; n < NB_RXBW; n++) {
log_printf("%u) %u > %u\r\n", n, rxbw, rxbws[n].hz);
if (rxbw >= rxbws[n-1].hz && rxbw < rxbws[n].hz) {
gfsk_mp_buf[5] = rxbws[n-1].bwf;
log_printf("RXBWset %u<-%u %02x\r\n", rxbws[n-1].hz, rxbw, gfsk_mp_buf[5]);
break;
}
}
radio.xfer(OPCODE_SET_MODULATION, 10, 0, gfsk_mp_buf);
}
return false;
}
const value_item_t Radio::gfsk_rxbw_item = { _ITEM_VALUE, 8, gfsk_rxbw_print, gfsk_rxbw_write};
void Radio::gfsk_fdev_print()
{
unsigned hz;
uint32_t u32;
radio.memRegRead(REG_ADDR_GFSK_FDEV, 1, &u32);
hz = my_round(u32 * FREQ_STEP);
printf("%u", hz);
radio.to_big_endian32(hz, gfsk_mp_buf+6);
}
bool Radio::gfsk_fdev_write(const char* txt)
{
unsigned hz;
if (sscanf(txt, "%u", &hz) == 1) {
radio.to_big_endian32(hz, gfsk_mp_buf+6);
radio.xfer(OPCODE_SET_MODULATION, 10, 0, gfsk_mp_buf);
}
return false;
}
const value_item_t Radio::gfsk_fdev_item = { _ITEM_VALUE, 8, gfsk_fdev_print, gfsk_fdev_write};
void Radio::gfsk_pblLen_print()
{
unsigned n;
gfskConfig1_t cfg1;
radio.memRegRead(REG_ADDR_GFSK_CFG1, 1, &cfg1.dword);
printf("%u", cfg1.bits.preamble_length);
n = cfg1.bits.preamble_length;
gfsk_pp_buf[1] = n;
n >>= 8;
gfsk_pp_buf[0] = n;
}
bool Radio::gfsk_pblLen_write(const char* txt)
{
unsigned n;
if (sscanf(txt, "%u", &n) == 1) {
radio.to_big_endian16(n, gfsk_pp_buf);
radio.xfer(OPCODE_SET_PACKET_PARAM, 9, 0, gfsk_pp_buf);
}
return false;
}
const value_item_t Radio::gfsk_pblLen_item = { _ITEM_VALUE, 5, gfsk_pblLen_print, gfsk_pblLen_write};
static const char* const fsk_detlens[] = {
" off ", // GFSK_PBLDET_LENGTH_OFF 0x00
" 8bits", // GFSK_PBLDET_LENGTH_8 0x04
"16bits", // GFSK_PBLDET_LENGTH_16 0x05
"24bits", // GFSK_PBLDET_LENGTH_24 0x06
"32bits", // GFSK_PBLDET_LENGTH_32 0x07
NULL
};
unsigned Radio::gfsk_pblDetLen_read(bool forWriting)
{
gfskConfig1_t cfg1;
radio.memRegRead(REG_ADDR_GFSK_CFG1, 1, &cfg1.dword);
if (cfg1.bits.preamble_det_enable) {
gfsk_pp_buf[2] = cfg1.bits.preamble_det_len + 4;
return cfg1.bits.preamble_det_len + 1;
} else {
gfsk_pp_buf[2] = 0;
return 0;
}
}
menuMode_e Radio::gfsk_pblDetLen_write(unsigned sidx)
{
if (sidx == 0)
gfsk_pp_buf[2] = 0;
else
gfsk_pp_buf[2] = sidx + 4;
radio.xfer(OPCODE_SET_PACKET_PARAM, 9, 0, gfsk_pp_buf);
return MENUMODE_REDRAW;
}
const dropdown_item_t Radio::gfsk_pblDetLen_item = { _ITEM_DROPDOWN, fsk_detlens, fsk_detlens, gfsk_pblDetLen_read, gfsk_pblDetLen_write};
void Radio::gfsk_syncWord_print(void)
{
uint32_t dword[2];
radio.memRegRead(REG_ADDR_GFSK_SYNC_LO, 2, dword);
printf("%08lx", dword[1]);
printf("%08lx", dword[0]);
}
bool Radio::gfsk_syncWord_write(const char* txt)
{
uint8_t buf[8];
const char* ptr;
const char* endPtr;
unsigned o, n = 0;
endPtr = txt + strlen(txt);
for (ptr = txt; sscanf(ptr, "%02x", &o) == 1; ) {
buf[n++] = o;
ptr += 2;
if (ptr >= endPtr)
break;
}
radio.xfer(OPCODE_SET_GFSK_SYNC_WORD, 8, 0, buf);
return false;
}
const value_item_t Radio::gfsk_syncWord_item = { _ITEM_VALUE, 17, gfsk_syncWord_print, gfsk_syncWord_write};
static const char* const addrcomps[] = {
" off ",
"NodeAddress ",
"NodeAddress+broadcast",
NULL
};
unsigned Radio::gfsk_addrcomp_read(bool forWriting)
{
gfskConfig4_t cfg4;
radio.memRegRead(REG_ADDR_GFSK_PAYLOAD_LENGTH_B, 1, &cfg4.dword);
gfsk_pp_buf[4] = cfg4.bits.addr_comp;
return cfg4.bits.addr_comp;
}
menuMode_e Radio::gfsk_addrcomp_write(unsigned sidx)
{
gfsk_pp_buf[4] = sidx;
radio.xfer(OPCODE_SET_PACKET_PARAM, 9, 0, gfsk_pp_buf);
return MENUMODE_REDRAW;
}
const dropdown_item_t Radio::gfsk_addrcomp_item = { _ITEM_DROPDOWN, addrcomps, addrcomps, gfsk_addrcomp_read, gfsk_addrcomp_write};
bool Radio::gfsk_varlen_read()
{
gfskConfig3_t cfg3;
radio.memRegRead(REG_ADDR_GFSK_CFG3, 1, &cfg3.dword);
gfsk_pp_buf[5] = cfg3.bits.variable_length;
return cfg3.bits.variable_length;
}
bool Radio::gfsk_varlen_push()
{
gfsk_pp_buf[5] ^= 1;
radio.xfer(OPCODE_SET_PACKET_PARAM, 9, 0, gfsk_pp_buf);
return gfsk_pp_buf[5];
}
const toggle_item_t Radio::gfsk_varlen_item = { _ITEM_TOGGLE, "fixLen", "varLen", gfsk_varlen_read, gfsk_varlen_push};
void Radio::gfsk_syncLen_print()
{
gfskConfig2_t cfg2;
radio.memRegRead(REG_ADDR_GFSK_CFG2, 1, &cfg2.dword);
gfsk_pp_buf[3] = cfg2.bits.sync_word_length;
printf("%u", cfg2.bits.sync_word_length);
}
bool Radio::gfsk_syncLen_write(const char *txt)
{
unsigned n;
if (sscanf(txt, "%u", &n) == 1) {
gfsk_pp_buf[3] = n;
radio.xfer(OPCODE_SET_PACKET_PARAM, 9, 0, gfsk_pp_buf);
}
return false;
}
const value_item_t Radio::gfsk_syncLen_item = { _ITEM_VALUE, 4, gfsk_syncLen_print, gfsk_syncLen_write};
const char* const Radio::gfsk_crcType_strs[] =
{
/* 0 */ " OFF ",
/* 1 */ "1_BYTE ",
/* 2 */ "2_BYTE ",
/* 3 */ "1_BYTE_INV",
/* 4 */ "2_BYTE_INV",
/* 5 */ NULL
};
unsigned Radio::gfsk_crcType_read(bool for_writing)
{
unsigned ret;
gfskConfig5_t cfg5;
radio.memRegRead(REG_ADDR_GFSK_CFG5, 1, &cfg5.dword);
// gfsk_pp_buf[7]: bit2:inv bit1:twobyte bit0:disabled
if (cfg5.bits.crc_off)
gfsk_pp_buf[7] |= 1;
else
gfsk_pp_buf[7] &= ~1;
if (cfg5.bits.crc_size)
gfsk_pp_buf[7] |= 2;
else
gfsk_pp_buf[7] &= ~2;
if (cfg5.bits.crc_invert)
gfsk_pp_buf[7] |= 4;
else
gfsk_pp_buf[7] &= ~4;
switch (gfsk_pp_buf[7]) {
case GFSK_CRC_OFF: ret = 0; break;
case GFSK_CRC_1_BYTE: ret = 1; break;
case GFSK_CRC_2_BYTE: ret = 2; break;
case GFSK_CRC_1_BYTE_INV: ret = 3; break;
case GFSK_CRC_2_BYTE_INV: ret = 4; break;
default: ret = 5; break;
}
return ret;
}
menuMode_e Radio::gfsk_crcType_write(unsigned sidx)
{
switch (sidx) {
case 0: gfsk_pp_buf[7] = GFSK_CRC_OFF; break;
case 1: gfsk_pp_buf[7] = GFSK_CRC_1_BYTE; break;
case 2: gfsk_pp_buf[7] = GFSK_CRC_2_BYTE; break;
case 3: gfsk_pp_buf[7] = GFSK_CRC_1_BYTE_INV; break;
case 4: gfsk_pp_buf[7] = GFSK_CRC_2_BYTE_INV; break;
}
radio.xfer(OPCODE_SET_PACKET_PARAM, 9, 0, gfsk_pp_buf);
return MENUMODE_REDRAW;
}
const dropdown_item_t Radio::gfsk_crcType_item = { _ITEM_DROPDOWN, gfsk_crcType_strs, gfsk_crcType_strs, gfsk_crcType_read, gfsk_crcType_write };
bool Radio::gfsk_dcfree_read(void)
{
gfskConfig5_t cfg5;
radio.memRegRead(REG_ADDR_GFSK_CFG5, 1, &cfg5.dword);
gfsk_pp_buf[8] = cfg5.bits.whitening_enable;
return cfg5.bits.whitening_enable;
}
bool Radio::gfsk_dcfree_push(void)
{
gfsk_pp_buf[8] ^= 1;
radio.xfer(OPCODE_SET_PACKET_PARAM, 9, 0, gfsk_pp_buf);
return gfsk_pp_buf[8] == 1;
}
const toggle_item_t Radio::gfsk_dcfree_item = { _ITEM_TOGGLE, "off", "on ", gfsk_dcfree_read, gfsk_dcfree_push};
void Radio::gfsk_crcinit_print()
{
radio.memRegRead(REG_ADDR_GFSK_CRC_INIT, 1, &gfsk_crc_Poly);
printf("%04x", (unsigned)gfsk_crc_Poly);
}
bool Radio::gfsk_crcinit_write(const char *txt)
{
uint8_t buf[8];
unsigned crcInit;
sscanf(txt, "%x", &crcInit);
gfsk_crc_initValue = crcInit;
radio.to_big_endian32(gfsk_crc_initValue, buf);
radio.to_big_endian32(gfsk_crc_Poly, buf+4);
radio.xfer(OPCODE_SET_GFSK_CRC_PARAMS, 8, 0, buf);
return false;
}
const value_item_t Radio::gfsk_crcinit_item = { _ITEM_VALUE, 4, gfsk_crcinit_print, gfsk_crcinit_write};
void Radio::gfsk_crcpoly_print()
{
radio.memRegRead(REG_ADDR_GFSK_CRC_POLY, 1, &gfsk_crc_Poly);
printf("%04x", (unsigned)gfsk_crc_Poly);
}
bool Radio::gfsk_crcpoly_write(const char *txt)
{
uint8_t buf[8];
unsigned crcPoly;
sscanf(txt, "%x", &crcPoly);
gfsk_crc_Poly = crcPoly;
radio.to_big_endian32(gfsk_crc_initValue, buf);
radio.to_big_endian32(gfsk_crc_Poly, buf+4);
radio.xfer(OPCODE_SET_GFSK_CRC_PARAMS, 8, 0, buf);
return false;
}
const value_item_t Radio::gfsk_crcpoly_item = { _ITEM_VALUE, 4, gfsk_crcpoly_print, gfsk_crcpoly_write};
const menu_t Radio::gfsk_menu[] = {
{ {FIRST_CHIP_MENU_ROW+2, 1}, "bps:", &gfsk_bitrate_item, FLAG_MSGTYPE_ALL },
{ {FIRST_CHIP_MENU_ROW+2, 15}, "bt:", &gfsk_bt_item, FLAG_MSGTYPE_ALL },
{ {FIRST_CHIP_MENU_ROW+2, 23}, "rxbw:", &gfsk_rxbw_item, FLAG_MSGTYPE_ALL },
{ {FIRST_CHIP_MENU_ROW+2, 39}, "fdev:", &gfsk_fdev_item, FLAG_MSGTYPE_ALL },
{ {FIRST_CHIP_MENU_ROW+3, 1}, "PreambleLength:", &gfsk_pblLen_item, FLAG_MSGTYPE_ALL },
{ {FIRST_CHIP_MENU_ROW+3, 21}, "PreambleDetectorLength:", &gfsk_pblDetLen_item, FLAG_MSGTYPE_ALL },
{ {FIRST_CHIP_MENU_ROW+4, 1}, "syncWord:", &gfsk_syncWord_item, FLAG_MSGTYPE_ALL },
{ {FIRST_CHIP_MENU_ROW+4, 29}, "bits:", &gfsk_syncLen_item, FLAG_MSGTYPE_ALL },
{ {FIRST_CHIP_MENU_ROW+4, 38}, "CRC:", &gfsk_crcType_item, FLAG_MSGTYPE_ALL },
{ {FIRST_CHIP_MENU_ROW+4, 55}, "AddrComp:", &gfsk_addrcomp_item, FLAG_MSGTYPE_ALL },
{ {FIRST_CHIP_MENU_ROW+5, 1}, NULL, &gfsk_varlen_item, FLAG_MSGTYPE_ALL },
{ {FIRST_CHIP_MENU_ROW+5, 10}, "whiten:", &gfsk_dcfree_item, FLAG_MSGTYPE_ALL },
{ {FIRST_CHIP_MENU_ROW+5, 23}, "crcInit:", &gfsk_crcinit_item, FLAG_MSGTYPE_ALL },
{ {FIRST_CHIP_MENU_ROW+5, 36}, "crcPoly:", &gfsk_crcpoly_item, FLAG_MSGTYPE_ALL },
{ {FIRST_CHIP_MENU_ROW+6, 1}, NULL, &dbg_item, FLAG_MSGTYPE_ALL},
{ {0, 0}, NULL, NULL }
};
static const char* const lora_bwstrs[] = {
/* 0 */ " 7.8KHz",
/* 1 */ " 15.6KHz",
/* 2 */ "31,25KHz",
/* 3 */ " 62.5KHz",
/* 4 */ " 125KHz",
/* 5 */ " 250KHz",
/* 6 */ " 500KHz",
/* 7 */ " 1000KHz",
/* 0 */ NULL
};
unsigned Radio::lora_bw_read(bool forWriting)
{
loraConfig0_t cfg0;
radio.memRegRead(REG_ADDR_LORA_CONFIG0, 1, &cfg0.dword);
return cfg0.bits.modem_bw;
}
menuMode_e Radio::lora_bw_write(unsigned sidx)
{
lora_mp_buf[1] = sidx;
radio.xfer(OPCODE_SET_MODULATION, 4, 0, lora_mp_buf);
return MENUMODE_REDRAW;
}
const dropdown_item_t Radio::lora_bw_item = { _ITEM_DROPDOWN, lora_bwstrs, lora_bwstrs, lora_bw_read, lora_bw_write};
void Radio::lora_sf_print()
{
loraConfig0_t cfg0;
radio.memRegRead(REG_ADDR_LORA_CONFIG0, 1, &cfg0.dword);
lora_mp_buf[0] = cfg0.bits.modem_sf;
printf("%u", cfg0.bits.modem_sf);
}
bool Radio::lora_sf_write(const char* str)
{
unsigned sf;
if (sscanf(str, "%u", &sf) == 1) {
lora_mp_buf[0] = sf;
radio.xfer(OPCODE_SET_MODULATION, 4, 0, lora_mp_buf);
}
return false;
}
const value_item_t Radio::lora_sf_item = { _ITEM_VALUE, 3, lora_sf_print, lora_sf_write };
void Radio::lora_pblLen_print()
{
unsigned pl;
loraConfigC_t cfgc;
radio.memRegRead(REG_ADDR_LORA_CONFIGC, 1, &cfgc.dword);
printf("%u", cfgc.bits.preamble_length);
pl = cfgc.bits.preamble_length;
lora_pp_buf[1] = pl & 0xff;
pl >>= 8;
lora_pp_buf[0] = pl;
}
bool Radio::lora_pblLen_write(const char* txt)
{
unsigned n;
if (sscanf(txt, "%u", &n) == 1) {
radio.to_big_endian16(n, lora_pp_buf);
radio.xfer(OPCODE_SET_PACKET_PARAM, 6, 0, lora_pp_buf);
}
return false;
}
const value_item_t Radio::lora_pblLen_item = { _ITEM_VALUE, 5, lora_pblLen_print, lora_pblLen_write};
bool Radio::lora_headerType_read()
{
loraConfig0_t cfg0;
radio.memRegRead(REG_ADDR_LORA_CONFIG0, 1, &cfg0.dword);
lora_pp_buf[2] = cfg0.bits.implicit_header;
return cfg0.bits.implicit_header;
}
bool Radio::lora_headerType_push()
{
bool ret;
if (lora_pp_buf[2]) {
lora_pp_buf[2] = 0;
ret = false;
} else {
lora_pp_buf[2] = 1;
ret = true;
}
radio.xfer(OPCODE_SET_PACKET_PARAM, 6, 0, lora_pp_buf);
return ret;
}
const toggle_item_t Radio::lora_headerType_item = { _ITEM_TOGGLE, "EXPLICIT", "IMPLICIT", lora_headerType_read, lora_headerType_push};
static const char* const lora_crs[] = {
"short 4/5 ",
"short 4/6 ",
"short 4/7 ",
"short 4/8 ",
" long 4/5 ",
" long 4/6 ",
" long 4/8 ",
NULL
};
unsigned Radio::lora_cr_read(bool forWriting)
{
loraConfig0_t cfg0;
radio.memRegRead(REG_ADDR_LORA_CONFIG0, 1, &cfg0.dword);
lora_mp_buf[2] = cfg0.bits.coding_rate;
if (lora_mp_buf[2] > 7)
return 7;
else
return lora_mp_buf[2];
}
menuMode_e Radio::lora_cr_write(unsigned sidx)
{
lora_mp_buf[2] = sidx + 1;
radio.xfer(OPCODE_SET_MODULATION, 4, 0, lora_mp_buf);
return MENUMODE_REDRAW;
}
const dropdown_item_t Radio::lora_cr_item = { _ITEM_DROPDOWN, lora_crs, lora_crs, lora_cr_read, lora_cr_write};
bool Radio::ppmOffset_read()
{
loraConfig0_t cfg0;
radio.memRegRead(REG_ADDR_LORA_CONFIG0, 1, &cfg0.dword);
lora_mp_buf[3] = cfg0.bits.ppm_offset;
return lora_mp_buf[3];
}
bool Radio::ppmOffset_push()
{
bool ret;
if (lora_mp_buf[3]) {
lora_mp_buf[3] = 0;
ret = false;
} else {
lora_mp_buf[3] = 1;
ret = true;
}
radio.xfer(OPCODE_SET_MODULATION, 4, 0, lora_mp_buf);
return ret;
}
const toggle_item_t Radio::lora_ppmOffset_item = { _ITEM_TOGGLE, "LowDatarateOptimize", NULL, ppmOffset_read, ppmOffset_push};
bool Radio::lora_crcon_read()
{
loraConfig0_t cfg0;
radio.memRegRead(REG_ADDR_LORA_CONFIG0, 1, &cfg0.dword);
lora_pp_buf[4] = cfg0.bits.crc_on;
return cfg0.bits.crc_on;
}
bool Radio::lora_crcon_push()
{
bool ret;
if (lora_pp_buf[4]) {
lora_pp_buf[4] = 0;
ret = false;
} else {
lora_pp_buf[4] = 1;
ret = true;
}
radio.xfer(OPCODE_SET_PACKET_PARAM, 6, 0, lora_pp_buf);
return ret;
}
const toggle_item_t Radio::lora_crcon_item = { _ITEM_TOGGLE,
"crc-off",
" CrcOn ",
lora_crcon_read,
lora_crcon_push
};
bool Radio::lora_inviq_read()
{
loraConfigA_t cfgA;
//loraConfigB_t cfgB;
radio.memRegRead(REG_ADDR_LORA_CONFIGA, 1, &cfgA.dword);
/*radio.memRegRead(REG_ADDR_LORA_CONFIGB, 1, buf);
cfgB.dword = radio.from_big_endian32(buf);*/
//TODO which one is RX vs TX: cfgA.bits.invertIQ, cfgB.bits.invertIQ
lora_pp_buf[5] = cfgA.bits.invertIQ;
/*if (cfgA.bits.invertIQ != cfgB.bits.invertIQ)
log_printf("invIQ %u %u\r\n", cfgA.bits.invertIQ, cfgB.bits.invertIQ);*/
return lora_pp_buf[5];
}
bool Radio::lora_inviq_push()
{
lora_pp_buf[5] ^= 1;
radio.xfer(OPCODE_SET_PACKET_PARAM, 6, 0, lora_pp_buf);
return lora_pp_buf[5] == 1;
}
const toggle_item_t Radio::lora_inviq_item = { _ITEM_TOGGLE,
" IQ ",
"invertedIQ",
lora_inviq_read, lora_inviq_push
};
bool Radio::lora_sync_read()
{
loraSync_t sync;
radio.memRegRead(REG_ADDR_LORA_SYNC, 1, &sync.dword);
if (sync.bits.ppg_a == 2 && sync.bits.ppg_b == 4)
return false; // private
else if (sync.bits.ppg_a == 6 && sync.bits.ppg_b == 8)
return true; // public
else
return false; // unknown
}
bool Radio::lora_sync_push()
{
uint8_t buf;
if (lora_sync_read())
buf = 0;
else
buf = 1;
radio.xfer(OPCODE_SET_LORA_PUBLIC_NETWORK, 1, 0, &buf);
return buf;
}
const toggle_item_t Radio::lora_sync_item = { _ITEM_TOGGLE,
"private",
"public ",
lora_sync_read,
lora_sync_push
};
const menu_t Radio::lora_menu[] = {
{ {FIRST_CHIP_MENU_ROW+2, 1}, NULL, &lora_bw_item, FLAG_MSGTYPE_ALL },
{ {FIRST_CHIP_MENU_ROW+2, 12}, "sf:", &lora_sf_item, FLAG_MSGTYPE_ALL },
{ {FIRST_CHIP_MENU_ROW+2, 19}, "cr:", &lora_cr_item, FLAG_MSGTYPE_ALL },
{ {FIRST_CHIP_MENU_ROW+2, 37}, NULL, &lora_ppmOffset_item, FLAG_MSGTYPE_ALL },
{ {FIRST_CHIP_MENU_ROW+3, 1}, "PreambleLength:", &lora_pblLen_item, FLAG_MSGTYPE_ALL },
{ {FIRST_CHIP_MENU_ROW+3, 23}, NULL, &lora_headerType_item, FLAG_MSGTYPE_ALL },
{ {FIRST_CHIP_MENU_ROW+3, 33}, NULL, &lora_crcon_item, FLAG_MSGTYPE_ALL },
{ {FIRST_CHIP_MENU_ROW+3, 43}, NULL, &lora_inviq_item, FLAG_MSGTYPE_ALL },
{ {FIRST_CHIP_MENU_ROW+3, 55}, "sync:", &lora_sync_item, FLAG_MSGTYPE_ALL },
{ {0, 0}, NULL, NULL }
};
void Radio::dbg_push()
{
log_printf("dbg\r\n");
}
const button_item_t Radio::dbg_item = { _ITEM_BUTTON, "DBG", dbg_push };
const button_item_t rfswEn_item = { _ITEM_BUTTON, " RfSwEnable:", NULL};
const button_item_t rfswStbyCfg_item = { _ITEM_BUTTON, "rfswStbyCfg:", NULL};
const button_item_t rfswRxCfg_item = { _ITEM_BUTTON, " rfswRxCfg:", NULL};
const button_item_t rfswTxCfg_item = { _ITEM_BUTTON, " rfswTxCfg:", NULL};
const button_item_t rfswTxHPCfg_item = { _ITEM_BUTTON, "rfswTxHPCfg:", NULL};
const button_item_t rfswGnssCfg_item = { _ITEM_BUTTON, "rfswGnssCfg:", NULL};
const button_item_t rfswWifiCfg_item = { _ITEM_BUTTON, "rfswWifiCfg:", NULL};
bool Radio::DIO10en_read()
{
dioEnable_t dio;
radio.memRegRead(REG_ADDR_DIO10, 1, &dio.dword);
if (dio.bits.enable)
dioBuf[DIO_en_IDX] |= DIO10_BIT;
else
dioBuf[DIO_en_IDX] &= ~DIO10_BIT;
return dio.bits.enable;
}
bool Radio::DIO8en_read()
{
dioEnable_t dio;
radio.memRegRead(REG_ADDR_DIO8, 1, &dio.dword);
if (dio.bits.enable)
dioBuf[DIO_en_IDX] |= DIO8_BIT;
else
dioBuf[DIO_en_IDX] &= ~DIO8_BIT;
return dio.bits.enable;
}
bool Radio::DIO7en_read()
{
dioEnable_t dio;
radio.memRegRead(REG_ADDR_DIO7, 1, &dio.dword);
if (dio.bits.enable)
dioBuf[DIO_en_IDX] |= DIO7_BIT;
else
dioBuf[DIO_en_IDX] &= ~DIO7_BIT;
return dio.bits.enable;
}
bool Radio::DIO6en_read()
{
dioEnable_t dio;
radio.memRegRead(REG_ADDR_DIO6, 1, &dio.dword);
if (dio.bits.enable)
dioBuf[DIO_en_IDX] |= DIO6_BIT;
else
dioBuf[DIO_en_IDX] &= ~DIO6_BIT;
return dio.bits.enable;
}
bool Radio::DIO5en_read()
{
dioEnable_t dio;
radio.memRegRead(REG_ADDR_DIO5, 1, &dio.dword);
if (dio.bits.enable)
dioBuf[DIO_en_IDX] |= DIO5_BIT;
else
dioBuf[DIO_en_IDX] &= ~DIO5_BIT;
return dio.bits.enable;
}
bool Radio::DIO10en_push()
{
dioBuf[DIO_en_IDX] ^= DIO10_BIT;
radio.xfer(OPCODE_SET_DIO_AS_RFSWITCH, 8, 0, dioBuf);
return dioBuf[DIO_en_IDX] == DIO10_BIT;
}
bool Radio::DIO8en_push()
{
dioBuf[DIO_en_IDX] ^= DIO8_BIT;
radio.xfer(OPCODE_SET_DIO_AS_RFSWITCH, 8, 0, dioBuf);
return dioBuf[DIO_en_IDX] == DIO8_BIT;
}
bool Radio::DIO7en_push()
{
dioBuf[DIO_en_IDX] ^= DIO7_BIT;
radio.xfer(OPCODE_SET_DIO_AS_RFSWITCH, 8, 0, dioBuf);
return dioBuf[DIO_en_IDX] == DIO7_BIT;
}
bool Radio::DIO6en_push()
{
dioBuf[DIO_en_IDX] ^= DIO6_BIT;
radio.xfer(OPCODE_SET_DIO_AS_RFSWITCH, 8, 0, dioBuf);
return dioBuf[DIO_en_IDX] == DIO6_BIT;
}
bool Radio::DIO5en_push()
{
dioBuf[DIO_en_IDX] ^= DIO5_BIT;
radio.xfer(OPCODE_SET_DIO_AS_RFSWITCH, 8, 0, dioBuf);
return dioBuf[DIO_en_IDX] == DIO5_BIT;
}
const toggle_item_t Radio::DIO5en_item = { _ITEM_TOGGLE, "DIO5", NULL, DIO5en_read, DIO5en_push};
const toggle_item_t Radio::DIO6en_item = { _ITEM_TOGGLE, "DIO6", NULL, DIO6en_read, DIO6en_push};
const toggle_item_t Radio::DIO7en_item = { _ITEM_TOGGLE, "DIO7", NULL, DIO7en_read, DIO7en_push};
const toggle_item_t Radio::DIO8en_item = { _ITEM_TOGGLE, "DIO8", NULL, DIO8en_read, DIO8en_push};
const toggle_item_t Radio::DIO10en_item = { _ITEM_TOGGLE, "DIO10", NULL, DIO10en_read, DIO10en_push};
bool Radio::DIO10stby_read()
{
return dioBuf[DIO_stby_IDX] == DIO10_BIT;
}
bool Radio::DIO10stby_push()
{
dioBuf[DIO_stby_IDX] ^= DIO10_BIT;
radio.xfer(OPCODE_SET_DIO_AS_RFSWITCH, 8, 0, dioBuf);
return DIO10stby_read();
}
bool Radio::DIO8stby_read()
{
return dioBuf[DIO_stby_IDX] == DIO8_BIT;
}
bool Radio::DIO8stby_push()
{
dioBuf[DIO_stby_IDX] ^= DIO8_BIT;
radio.xfer(OPCODE_SET_DIO_AS_RFSWITCH, 8, 0, dioBuf);
return DIO8stby_read();
}
bool Radio::DIO7stby_read()
{
return dioBuf[DIO_stby_IDX] == DIO7_BIT;
}
bool Radio::DIO7stby_push()
{
dioBuf[DIO_stby_IDX] ^= DIO7_BIT;
radio.xfer(OPCODE_SET_DIO_AS_RFSWITCH, 8, 0, dioBuf);
return DIO7stby_read();
}
bool Radio::DIO6stby_read()
{
return dioBuf[DIO_stby_IDX] == DIO6_BIT;
}
bool Radio::DIO6stby_push()
{
dioBuf[DIO_stby_IDX] ^= DIO6_BIT;
radio.xfer(OPCODE_SET_DIO_AS_RFSWITCH, 8, 0, dioBuf);
return DIO6stby_read();
}
bool Radio::DIO5stby_read()
{
return dioBuf[DIO_stby_IDX] == DIO5_BIT;
}
bool Radio::DIO5stby_push()
{
dioBuf[DIO_stby_IDX] ^= DIO5_BIT;
radio.xfer(OPCODE_SET_DIO_AS_RFSWITCH, 8, 0, dioBuf);
return DIO5stby_read();
}
const toggle_item_t Radio::DIO5stby_item = { _ITEM_TOGGLE, "DIO5", NULL, DIO5stby_read, DIO5stby_push};
const toggle_item_t Radio::DIO6stby_item = { _ITEM_TOGGLE, "DIO6", NULL, DIO6stby_read, DIO6stby_push};
const toggle_item_t Radio::DIO7stby_item = { _ITEM_TOGGLE, "DIO7", NULL, DIO7stby_read, DIO7stby_push};
const toggle_item_t Radio::DIO8stby_item = { _ITEM_TOGGLE, "DIO8", NULL, DIO8stby_read, DIO8stby_push};
const toggle_item_t Radio::DIO10stby_item = { _ITEM_TOGGLE, "DIO10", NULL, DIO10stby_read, DIO10stby_push};
bool Radio::DIO10rx_read()
{
return dioBuf[DIO_rx_IDX] == DIO10_BIT;
}
bool Radio::DIO10rx_push()
{
dioBuf[DIO_rx_IDX] ^= DIO10_BIT;
radio.xfer(OPCODE_SET_DIO_AS_RFSWITCH, 8, 0, dioBuf);
return DIO10rx_read();
}
bool Radio::DIO8rx_read()
{
return dioBuf[DIO_rx_IDX] == DIO8_BIT;
}
bool Radio::DIO8rx_push()
{
dioBuf[DIO_rx_IDX] ^= DIO8_BIT;
radio.xfer(OPCODE_SET_DIO_AS_RFSWITCH, 8, 0, dioBuf);
return DIO8rx_read();
}
bool Radio::DIO7rx_read()
{
return dioBuf[DIO_rx_IDX] == DIO7_BIT;
}
bool Radio::DIO7rx_push()
{
dioBuf[DIO_rx_IDX] ^= DIO7_BIT;
radio.xfer(OPCODE_SET_DIO_AS_RFSWITCH, 8, 0, dioBuf);
return DIO7rx_read();
}
bool Radio::DIO6rx_read()
{
return dioBuf[DIO_rx_IDX] == DIO6_BIT;
}
bool Radio::DIO6rx_push()
{
dioBuf[DIO_rx_IDX] ^= DIO6_BIT;
radio.xfer(OPCODE_SET_DIO_AS_RFSWITCH, 8, 0, dioBuf);
return DIO6rx_read();
}
bool Radio::DIO5rx_read()
{
return dioBuf[DIO_rx_IDX] == DIO5_BIT;
}
bool Radio::DIO5rx_push()
{
dioBuf[DIO_rx_IDX] ^= DIO5_BIT;
radio.xfer(OPCODE_SET_DIO_AS_RFSWITCH, 8, 0, dioBuf);
return DIO5rx_read();
}
const toggle_item_t Radio::DIO5rx_item = { _ITEM_TOGGLE, "DIO5", NULL, DIO5rx_read, DIO5rx_push};
const toggle_item_t Radio::DIO6rx_item = { _ITEM_TOGGLE, "DIO6", NULL, DIO6rx_read, DIO6rx_push};
const toggle_item_t Radio::DIO7rx_item = { _ITEM_TOGGLE, "DIO7", NULL, DIO7rx_read, DIO7rx_push};
const toggle_item_t Radio::DIO8rx_item = { _ITEM_TOGGLE, "DIO8", NULL, DIO8rx_read, DIO8rx_push};
const toggle_item_t Radio::DIO10rx_item = { _ITEM_TOGGLE, "DIO10", NULL, DIO10rx_read, DIO10rx_push};
bool Radio::DIO10tx_read()
{
return dioBuf[DIO_tx_IDX] == DIO10_BIT;
}
bool Radio::DIO10tx_push()
{
dioBuf[DIO_tx_IDX] ^= DIO10_BIT;
radio.xfer(OPCODE_SET_DIO_AS_RFSWITCH, 8, 0, dioBuf);
return DIO10tx_read();
}
bool Radio::DIO8tx_read()
{
return dioBuf[DIO_tx_IDX] == DIO8_BIT;
}
bool Radio::DIO8tx_push()
{
dioBuf[DIO_tx_IDX] ^= DIO8_BIT;
radio.xfer(OPCODE_SET_DIO_AS_RFSWITCH, 8, 0, dioBuf);
return DIO8tx_read();
}
bool Radio::DIO7tx_read()
{
return dioBuf[DIO_tx_IDX] == DIO7_BIT;
}
bool Radio::DIO7tx_push()
{
dioBuf[DIO_tx_IDX] ^= DIO7_BIT;
radio.xfer(OPCODE_SET_DIO_AS_RFSWITCH, 8, 0, dioBuf);
return DIO7tx_read();
}
bool Radio::DIO6tx_read()
{
return dioBuf[DIO_tx_IDX] == DIO6_BIT;
}
bool Radio::DIO6tx_push()
{
dioBuf[DIO_tx_IDX] ^= DIO6_BIT;
radio.xfer(OPCODE_SET_DIO_AS_RFSWITCH, 8, 0, dioBuf);
return DIO6tx_read();
}
bool Radio::DIO5tx_read()
{
return dioBuf[DIO_tx_IDX] == DIO5_BIT;
}
bool Radio::DIO5tx_push()
{
dioBuf[DIO_tx_IDX] ^= DIO5_BIT;
radio.xfer(OPCODE_SET_DIO_AS_RFSWITCH, 8, 0, dioBuf);
return DIO5tx_read();
}
const toggle_item_t Radio::DIO5tx_item = { _ITEM_TOGGLE, "DIO5", NULL, DIO5tx_read, DIO5tx_push};
const toggle_item_t Radio::DIO6tx_item = { _ITEM_TOGGLE, "DIO6", NULL, DIO6tx_read, DIO6tx_push};
const toggle_item_t Radio::DIO7tx_item = { _ITEM_TOGGLE, "DIO7", NULL, DIO7tx_read, DIO7tx_push};
const toggle_item_t Radio::DIO8tx_item = { _ITEM_TOGGLE, "DIO8", NULL, DIO8tx_read, DIO8tx_push};
const toggle_item_t Radio::DIO10tx_item = { _ITEM_TOGGLE, "DIO10", NULL, DIO10tx_read, DIO10tx_push};
bool Radio::DIO10txhp_read()
{
return dioBuf[DIO_txhp_IDX] == DIO10_BIT;
}
bool Radio::DIO10txhp_push()
{
dioBuf[DIO_txhp_IDX] ^= DIO10_BIT;
radio.xfer(OPCODE_SET_DIO_AS_RFSWITCH, 8, 0, dioBuf);
return DIO10txhp_read();
}
bool Radio::DIO8txhp_read()
{
return dioBuf[DIO_txhp_IDX] == DIO8_BIT;
}
bool Radio::DIO8txhp_push()
{
dioBuf[DIO_txhp_IDX] ^= DIO8_BIT;
radio.xfer(OPCODE_SET_DIO_AS_RFSWITCH, 8, 0, dioBuf);
return DIO8txhp_read();
}
bool Radio::DIO7txhp_read()
{
return dioBuf[DIO_txhp_IDX] == DIO7_BIT;
}
bool Radio::DIO7txhp_push()
{
dioBuf[DIO_txhp_IDX] ^= DIO7_BIT;
radio.xfer(OPCODE_SET_DIO_AS_RFSWITCH, 8, 0, dioBuf);
return DIO7txhp_read();
}
bool Radio::DIO6txhp_read()
{
return dioBuf[DIO_txhp_IDX] == DIO6_BIT;
}
bool Radio::DIO6txhp_push()
{
dioBuf[DIO_txhp_IDX] ^= DIO6_BIT;
radio.xfer(OPCODE_SET_DIO_AS_RFSWITCH, 8, 0, dioBuf);
return DIO6txhp_read();
}
bool Radio::DIO5txhp_read()
{
return dioBuf[DIO_txhp_IDX] == DIO5_BIT;
}
bool Radio::DIO5txhp_push()
{
dioBuf[DIO_txhp_IDX] ^= DIO5_BIT;
radio.xfer(OPCODE_SET_DIO_AS_RFSWITCH, 8, 0, dioBuf);
return DIO5txhp_read();
}
const toggle_item_t Radio::DIO5txhp_item = { _ITEM_TOGGLE, "DIO5", NULL, DIO5txhp_read, DIO5txhp_push};
const toggle_item_t Radio::DIO6txhp_item = { _ITEM_TOGGLE, "DIO6", NULL, DIO6txhp_read, DIO6txhp_push};
const toggle_item_t Radio::DIO7txhp_item = { _ITEM_TOGGLE, "DIO7", NULL, DIO7txhp_read, DIO7txhp_push};
const toggle_item_t Radio::DIO8txhp_item = { _ITEM_TOGGLE, "DIO8", NULL, DIO8txhp_read, DIO8txhp_push};
const toggle_item_t Radio::DIO10txhp_item = { _ITEM_TOGGLE, "DIO10", NULL, DIO10txhp_read, DIO10txhp_push};
bool Radio::DIO10gnss_read()
{
return dioBuf[DIO_gnss_IDX] == DIO10_BIT;
}
bool Radio::DIO10gnss_push()
{
dioBuf[DIO_gnss_IDX] ^= DIO10_BIT;
radio.xfer(OPCODE_SET_DIO_AS_RFSWITCH, 8, 0, dioBuf);
return DIO10gnss_read();
}
bool Radio::DIO8gnss_read()
{
return dioBuf[DIO_gnss_IDX] == DIO8_BIT;
}
bool Radio::DIO8gnss_push()
{
dioBuf[DIO_gnss_IDX] ^= DIO8_BIT;
radio.xfer(OPCODE_SET_DIO_AS_RFSWITCH, 8, 0, dioBuf);
return DIO8gnss_read();
}
bool Radio::DIO7gnss_read()
{
return dioBuf[DIO_gnss_IDX] == DIO7_BIT;
}
bool Radio::DIO7gnss_push()
{
dioBuf[DIO_gnss_IDX] ^= DIO7_BIT;
radio.xfer(OPCODE_SET_DIO_AS_RFSWITCH, 8, 0, dioBuf);
return DIO7gnss_read();
}
bool Radio::DIO6gnss_read()
{
return dioBuf[DIO_gnss_IDX] == DIO6_BIT;
}
bool Radio::DIO6gnss_push()
{
dioBuf[DIO_gnss_IDX] ^= DIO6_BIT;
radio.xfer(OPCODE_SET_DIO_AS_RFSWITCH, 8, 0, dioBuf);
return DIO6gnss_read();
}
bool Radio::DIO5gnss_read()
{
return dioBuf[DIO_gnss_IDX] == DIO5_BIT;
}
bool Radio::DIO5gnss_push()
{
dioBuf[DIO_gnss_IDX] ^= DIO5_BIT;
radio.xfer(OPCODE_SET_DIO_AS_RFSWITCH, 8, 0, dioBuf);
return DIO5gnss_read();
}
const toggle_item_t Radio::DIO5gnss_item = { _ITEM_TOGGLE, "DIO5", NULL, DIO5gnss_read, DIO5gnss_push};
const toggle_item_t Radio::DIO6gnss_item = { _ITEM_TOGGLE, "DIO6", NULL, DIO6gnss_read, DIO6gnss_push};
const toggle_item_t Radio::DIO7gnss_item = { _ITEM_TOGGLE, "DIO7", NULL, DIO7gnss_read, DIO7gnss_push};
const toggle_item_t Radio::DIO8gnss_item = { _ITEM_TOGGLE, "DIO8", NULL, DIO8gnss_read, DIO8gnss_push};
const toggle_item_t Radio::DIO10gnss_item = { _ITEM_TOGGLE, "DIO10", NULL, DIO10gnss_read, DIO10gnss_push};
bool Radio::DIO10wifi_read()
{
return dioBuf[DIO_wifi_IDX] == DIO10_BIT;
}
bool Radio::DIO10wifi_push()
{
dioBuf[DIO_wifi_IDX] ^= DIO10_BIT;
radio.xfer(OPCODE_SET_DIO_AS_RFSWITCH, 8, 0, dioBuf);
return DIO10wifi_read();
}
bool Radio::DIO8wifi_read()
{
return dioBuf[DIO_wifi_IDX] == DIO8_BIT;
}
bool Radio::DIO8wifi_push()
{
dioBuf[DIO_wifi_IDX] ^= DIO8_BIT;
radio.xfer(OPCODE_SET_DIO_AS_RFSWITCH, 8, 0, dioBuf);
return DIO8wifi_read();
}
bool Radio::DIO7wifi_read()
{
return dioBuf[DIO_wifi_IDX] == DIO7_BIT;
}
bool Radio::DIO7wifi_push()
{
dioBuf[DIO_wifi_IDX] ^= DIO7_BIT;
radio.xfer(OPCODE_SET_DIO_AS_RFSWITCH, 8, 0, dioBuf);
return DIO7wifi_read();
}
bool Radio::DIO6wifi_read()
{
return dioBuf[DIO_wifi_IDX] == DIO6_BIT;
}
bool Radio::DIO6wifi_push()
{
dioBuf[DIO_wifi_IDX] ^= DIO6_BIT;
radio.xfer(OPCODE_SET_DIO_AS_RFSWITCH, 8, 0, dioBuf);
return DIO6wifi_read();
}
bool Radio::DIO5wifi_read()
{
return dioBuf[DIO_wifi_IDX] == DIO5_BIT;
}
bool Radio::DIO5wifi_push()
{
dioBuf[DIO_wifi_IDX] ^= DIO5_BIT;
radio.xfer(OPCODE_SET_DIO_AS_RFSWITCH, 8, 0, dioBuf);
return DIO5wifi_read();
}
const toggle_item_t Radio::DIO5wifi_item = { _ITEM_TOGGLE, "DIO5", NULL, DIO5wifi_read, DIO5wifi_push};
const toggle_item_t Radio::DIO6wifi_item = { _ITEM_TOGGLE, "DIO6", NULL, DIO6wifi_read, DIO6wifi_push};
const toggle_item_t Radio::DIO7wifi_item = { _ITEM_TOGGLE, "DIO7", NULL, DIO7wifi_read, DIO7wifi_push};
const toggle_item_t Radio::DIO8wifi_item = { _ITEM_TOGGLE, "DIO8", NULL, DIO8wifi_read, DIO8wifi_push};
const toggle_item_t Radio::DIO10wifi_item = { _ITEM_TOGGLE, "DIO10", NULL, DIO10wifi_read, DIO10wifi_push};
const menu_t Radio::none_menu[] = {
{ {FIRST_CHIP_MENU_ROW+3, 1}, NULL, &rfswEn_item, FLAG_MSGTYPE_ALL},
{ {FIRST_CHIP_MENU_ROW+3, 14}, NULL, &DIO10en_item, FLAG_MSGTYPE_ALL},
{ {FIRST_CHIP_MENU_ROW+3, 21}, NULL, &DIO8en_item, FLAG_MSGTYPE_ALL},
{ {FIRST_CHIP_MENU_ROW+3, 26}, NULL, &DIO7en_item, FLAG_MSGTYPE_ALL},
{ {FIRST_CHIP_MENU_ROW+3, 32}, NULL, &DIO6en_item, FLAG_MSGTYPE_ALL},
{ {FIRST_CHIP_MENU_ROW+3, 38}, NULL, &DIO5en_item, FLAG_MSGTYPE_ALL},
{ {FIRST_CHIP_MENU_ROW+4, 1}, NULL, &rfswStbyCfg_item, FLAG_MSGTYPE_ALL},
{ {FIRST_CHIP_MENU_ROW+4, 14}, NULL, &DIO10stby_item, FLAG_MSGTYPE_ALL},
{ {FIRST_CHIP_MENU_ROW+4, 21}, NULL, &DIO8stby_item, FLAG_MSGTYPE_ALL},
{ {FIRST_CHIP_MENU_ROW+4, 26}, NULL, &DIO7stby_item, FLAG_MSGTYPE_ALL},
{ {FIRST_CHIP_MENU_ROW+4, 32}, NULL, &DIO6stby_item, FLAG_MSGTYPE_ALL},
{ {FIRST_CHIP_MENU_ROW+4, 38}, NULL, &DIO5stby_item, FLAG_MSGTYPE_ALL},
{ {FIRST_CHIP_MENU_ROW+5, 1}, NULL, &rfswRxCfg_item, FLAG_MSGTYPE_ALL},
{ {FIRST_CHIP_MENU_ROW+5, 14}, NULL, &DIO10rx_item, FLAG_MSGTYPE_ALL},
{ {FIRST_CHIP_MENU_ROW+5, 21}, NULL, &DIO8rx_item, FLAG_MSGTYPE_ALL},
{ {FIRST_CHIP_MENU_ROW+5, 26}, NULL, &DIO7rx_item, FLAG_MSGTYPE_ALL},
{ {FIRST_CHIP_MENU_ROW+5, 32}, NULL, &DIO6rx_item, FLAG_MSGTYPE_ALL},
{ {FIRST_CHIP_MENU_ROW+5, 38}, NULL, &DIO5rx_item, FLAG_MSGTYPE_ALL},
{ {FIRST_CHIP_MENU_ROW+6, 1}, NULL, &rfswTxCfg_item, FLAG_MSGTYPE_ALL},
{ {FIRST_CHIP_MENU_ROW+6, 14}, NULL, &DIO10tx_item, FLAG_MSGTYPE_ALL},
{ {FIRST_CHIP_MENU_ROW+6, 21}, NULL, &DIO8tx_item, FLAG_MSGTYPE_ALL},
{ {FIRST_CHIP_MENU_ROW+6, 26}, NULL, &DIO7tx_item, FLAG_MSGTYPE_ALL},
{ {FIRST_CHIP_MENU_ROW+6, 32}, NULL, &DIO6tx_item, FLAG_MSGTYPE_ALL},
{ {FIRST_CHIP_MENU_ROW+6, 38}, NULL, &DIO5tx_item, FLAG_MSGTYPE_ALL},
{ {FIRST_CHIP_MENU_ROW+7, 1}, NULL, &rfswTxHPCfg_item, FLAG_MSGTYPE_ALL},
{ {FIRST_CHIP_MENU_ROW+7, 14}, NULL, &DIO10txhp_item, FLAG_MSGTYPE_ALL},
{ {FIRST_CHIP_MENU_ROW+7, 21}, NULL, &DIO8txhp_item, FLAG_MSGTYPE_ALL},
{ {FIRST_CHIP_MENU_ROW+7, 26}, NULL, &DIO7txhp_item, FLAG_MSGTYPE_ALL},
{ {FIRST_CHIP_MENU_ROW+7, 32}, NULL, &DIO6txhp_item, FLAG_MSGTYPE_ALL},
{ {FIRST_CHIP_MENU_ROW+7, 38}, NULL, &DIO5txhp_item, FLAG_MSGTYPE_ALL},
{ {FIRST_CHIP_MENU_ROW+8, 1}, NULL, &rfswGnssCfg_item, FLAG_MSGTYPE_ALL},
{ {FIRST_CHIP_MENU_ROW+8, 14}, NULL, &DIO10gnss_item, FLAG_MSGTYPE_ALL},
{ {FIRST_CHIP_MENU_ROW+8, 21}, NULL, &DIO8gnss_item, FLAG_MSGTYPE_ALL},
{ {FIRST_CHIP_MENU_ROW+8, 26}, NULL, &DIO7gnss_item, FLAG_MSGTYPE_ALL},
{ {FIRST_CHIP_MENU_ROW+8, 32}, NULL, &DIO6gnss_item, FLAG_MSGTYPE_ALL},
{ {FIRST_CHIP_MENU_ROW+8, 38}, NULL, &DIO5gnss_item, FLAG_MSGTYPE_ALL},
{ {FIRST_CHIP_MENU_ROW+9, 1}, NULL, &rfswWifiCfg_item, FLAG_MSGTYPE_ALL},
{ {FIRST_CHIP_MENU_ROW+9, 14}, NULL, &DIO10wifi_item, FLAG_MSGTYPE_ALL},
{ {FIRST_CHIP_MENU_ROW+9, 21}, NULL, &DIO8wifi_item, FLAG_MSGTYPE_ALL},
{ {FIRST_CHIP_MENU_ROW+9, 26}, NULL, &DIO7wifi_item, FLAG_MSGTYPE_ALL},
{ {FIRST_CHIP_MENU_ROW+9, 32}, NULL, &DIO6wifi_item, FLAG_MSGTYPE_ALL},
{ {FIRST_CHIP_MENU_ROW+9, 38}, NULL, &DIO5wifi_item, FLAG_MSGTYPE_ALL},
{ {LAST_CHIP_MENU_ROW, 1}, NULL, &dbg_item, FLAG_MSGTYPE_ALL},
{ {0, 0}, NULL, NULL }
};
const menu_t* Radio::get_modem_sub_menu() { return NULL; }
const menu_t* Radio::get_modem_menu()
{
pktType = radio.getPacketType();
if (pktType == PACKET_TYPE_LORA)
return lora_menu;
else if (pktType == PACKET_TYPE_GFSK)
return gfsk_menu;
else
return none_menu;
return NULL;
}
void Radio::setFS()
{
radio.xfer(OPCODE_SET_FS, 0, 0, NULL);
}
void Radio::test()
{
}
void Radio::rxDone(uint8_t size, float rssi, float snr)
{
RadioEvents->RxDone(size, rssi, snr);
}
void Radio::txDoneBottom()
{
if (RadioEvents->TxDone_botHalf)
RadioEvents->TxDone_botHalf();
}
void Radio::boardInit(const RadioEvents_t* e)
{
uint8_t buf[4];
{
float default_ms = 62.5;
unsigned ticks = default_ms * 32.768;
radio.to_big_endian24(ticks, tcxo_buf+1);
}
radio.txDone = txDoneBottom;
radio.rxDone = rxDone;
radio.cadDone = cadDone;
//radio.chipModeChange = chipModeChange;
RadioEvents = e;
stat_t stat;
stat.word = radio.xfer(OPCODE_GET_VERSION, 0, 0, NULL);
stat.word = radio.xfer(0x0000, 0, 4, buf);
if (stat.bits.cmdStatus == CMD_DAT) {
sprintf(chip_ver, "LR1110 %02x %02x %u.%u",
buf[0], /* silicon rev */
buf[1], /* use case */
buf[2], /* firmware major */
buf[3] /* firmware minor */
);
}
initRfSwDIO();
readChip();
}
const char* const navToHostStr[] = {
/* 0 */ "ok",
/* 1 */ "cmd unexpected",
/* 2 */ "cmd not implemented",
/* 3 */ "cmd paramters invalid",
/* 4 */ "message sanity check",
/* 5 */ "scanning failed",
/* 6 */ "no time",
/* 7 */ "no satellite detected",
/* 8 */ "almanac too old",
/* 9 */ "alamanac update fail: crc",
/* 10 */ "alamanac update fail: flash integrity",
/* 11 */ "alamanac update fail: date too old",
/* 12 */ "alamanac update fail: not allowed",
/* 13 */ "global almanac crc error",
/* 14 */ "almanac version not supported",
/* 15 */ ""
};
struct wifidr {
const char *txt;
float Mbps;
};
const struct wifidr wifiDatarates[] = {
/* 0 */ { NULL, 0},
/* 1 */ { "DBPSK", 1},
/* 2 */ { "DQPSK", 2},
/* 3 */ { "BPSK", 6},
/* 4 */ { "BPSK", 9},
/* 5 */ { "QPSK", 12},
/* 6 */ { "QPSK", 18},
/* 7 */ { "16-QAM", 24},
/* 8 */ { "16-QAM", 36},
/* 9 */ { "(9)", 0},
/* 10 */ { "(10)", 0},
/* 11 */ { "BPSK", 6.5},
/* 12 */ { "QPSK", 13},
/* 13 */ { "QPSK", 19.5},
/* 14 */ { "16-QAM", 26},
/* 15 */ { "16-QAM", 39},
/* 16 */ { "(16)", 0},
/* 17 */ { "(17)", 0},
/* 18 */ { "(18)", 0},
/* 19 */ { "BPSK", 7.2},
/* 20 */ { "QPSK", 14.4},
/* 21 */ { "QPSK", 21.7},
/* 22 */ { "16-QAM", 28.9},
/* 23 */ { "16-QAM", 43.3},
};
void print_wifi_result(const uint8_t *result)
{
char out[96];
char str[24];
unsigned n, macStart;
wifiType_t wt;
wifiChanInfo_t ci;
wt.octet = result[0];
ci.octet = result[1];
out[0] = 0;
strcat(out, "802.11");
switch (wt.bits.signal) {
case 1: strcat(out, "b"); break;
case 2: strcat(out, "g"); break;
case 3: strcat(out, "n"); break;
}
sprintf(str, " %s %.1fMbps", wifiDatarates[wt.bits.datarate].txt, wifiDatarates[wt.bits.datarate].Mbps);
strcat(out, str);
strcat(out, " ");
sprintf(str, "ch%u ", ci.bits.channelID);
strcat(out, str);
switch (ci.bits.channelID) {
// table 10-5
}
strcat(out, " ");
sprintf(str, "mv:%u ", ci.bits.macValidationID);
strcat(out, str);
switch (ci.bits.macValidationID) {
case 1: strcat(out, "gateway"); break;
case 2: strcat(out, "phone"); break;
case 3: strcat(out, "?"); break;
// table 10.8
}
sprintf(str, " rssi:%d ", (int8_t)result[2]);
strcat(out, str);
if (wifiResultFormatBasic) {
macStart = 3;
} else {
macStart = 4;
}
for (n = 0; n < 6; n++) {
sprintf(str, "%02x", result[n+macStart]);
strcat(out, str);
if (n < 5)
strcat(out, ":");
}
strcat(out, " ");
if (!wifiResultFormatBasic) {
sprintf(str, "frameCtrl:%02x ", result[3]);
strcat(out, str);
}
log_printf("%s\r\n", out);
}
bool Radio::service(int8_t statusRow)
{
irq_t irq;
irq.dword = radio.service();
if (irq.dword != 0) {
char str[94];
sprintf(str, "irq.dword:%06lx ", irq.dword);
if (irq.bits.TxDone)
strcat(str, "TxDone ");
if (irq.bits.RxDone)
strcat(str, "RxDone ");
if (irq.bits.PreambleDetected)
strcat(str, "PreambleDetected ");
if (irq.bits.SyncHeaderValid)
strcat(str, "SyncHeaderValid ");
if (irq.bits.HeaderErr)
strcat(str, "HeaderErr ");
if (irq.bits.CadDone)
strcat(str, "CadDone ");
if (irq.bits.CadDetected)
strcat(str, "CadDetected ");
if (irq.bits.Timeout)
strcat(str, "Timeout ");
if (irq.bits.lowBat)
strcat(str, "lowBat ");
if (irq.bits.FskLenError)
strcat(str, "FskLenError ");
if (irq.bits.FskAddrError)
strcat(str, "FskAddrError ");
if (irq.bits.CmdErr) {
char txt[23];
sprintf(txt, "\e[31mCmdErr_%04x\e[0m ", radio.err_opcode);
strcat(str, txt);
}
if (irq.bits.Error) {
strcat(str, "\e[31mError: ");
if (radio.errorStat.bits.lf_rc_calib)
strcat(str, "lf_rc_calib ");
if (radio.errorStat.bits.hf_rc_calib)
strcat(str, "hf_rc_calib ");
if (radio.errorStat.bits.adc_calib)
strcat(str, "adc_calib ");
if (radio.errorStat.bits.pll_calib)
strcat(str, "pll_calib ");
if (radio.errorStat.bits.img_calib)
strcat(str, "img_calib ");
if (radio.errorStat.bits.hf_xosc_start_)
strcat(str, "hf_xosc_start ");
if (radio.errorStat.bits.lf_xosc_start)
strcat(str, "lf_xosc_start ");
if (radio.errorStat.bits.pll_lock)
strcat(str, "pll_lock ");
if (radio.errorStat.bits.rx_adc_offset)
strcat(str, "rx_adc_offset ");
strcat(str, "\e[0m");
}
if (irq.bits.WifiDone) {
strcat(str, "WifiDone ");
}
if (irq.bits.GNSSDone) {
strcat(str, "GNSSDone ");
}
log_printf("%s\r\n", str);
/****************************/
if (irq.bits.WifiDone) {
stat_t stat;
uint8_t nbResults;
stat.word = radio.xfer(OPCODE_GET_WIFI_NB_RESULTS, 0, 0, NULL);
stat.word = radio.xfer(0x0000, 0, 1, &nbResults);
if (stat.bits.cmdStatus == CMD_DAT) {
unsigned n;
log_printf("nbResults:%u\r\n", nbResults);
for (n = 0; n < nbResults; n++) {
uint8_t buf[3];
uint8_t resultBuf[22];
buf[0] = n;
buf[1] = 1; // number of results in this read
buf[2] = wifiResultFormatBasic ? 4 : 1;
stat.word = radio.xfer(OPCODE_WIFI_READ_RESULTS, 3, 0, buf);
// basic = 9byte length
// full = 22byte length
stat.word = radio.xfer(0x0000, 0, wifiResultFormatBasic ? 9 : 22, resultBuf);
if (stat.bits.cmdStatus == CMD_DAT)
print_wifi_result(resultBuf);
else
log_printf("readResult:%s\r\n", radio.cmdStatus_toString(stat.bits.cmdStatus));
}
} else
log_printf("nbResults:%s\r\n", radio.cmdStatus_toString(stat.bits.cmdStatus));
} // ..if (irq.bits.WifiDone)
if (irq.bits.GNSSDone) {
uint8_t gnssResultBuf[512];
uint8_t buf[2];
stat_t stat;
unsigned resultSize;
stat.word = radio.xfer(OPCODE_GNSS_GET_RESULT_SIZE, 0, 0, NULL);
stat.word = radio.xfer(0x0000, 0, 2, buf);
if (stat.bits.cmdStatus == CMD_DAT) {
resultSize = buf[1];
resultSize <<= 8;
resultSize |= buf[0];
log_printf("resultSize:%u\r\n", resultSize);
stat.word = radio.xfer(OPCODE_GNSS_READ_RESULTS, 0, 0, NULL);
stat.word = radio.xfer(0x0000, 0, resultSize, gnssResultBuf);
if (stat.bits.cmdStatus == CMD_DAT) {
unsigned i = 0, n;
switch (gnssResultBuf[0]) {
case 0: log_printf("navToHost:%s\r\n", navToHostStr[gnssResultBuf[0]]); break;
case 1: log_printf("navToSolver\r\n"); break;
case 2: log_printf("navToDMC\r\n"); break;
default: log_printf("nav:%u\r\n", gnssResultBuf[0]); break;
}
for (i = 0; i < resultSize; ) {
printf("%03x:", i);
for (n = 0; n < 16; n++) {
printf("%02x ", gnssResultBuf[i+n]);
if (n == 7)
printf(" ");
}
for (n = 0; n < 16; n++) {
if (n > ' ' && n < 0x7f)
printf("%c", gnssResultBuf[i+n]);
else
printf(".");
if (n == 7)
printf(" ");
}
printf("\r\n");
i += 16;
}
} else
log_printf("resultBuf:%s\r\n", radio.cmdStatus_toString(stat.bits.cmdStatus));
} else
log_printf("resultSize:%s\r\n", radio.cmdStatus_toString(stat.bits.cmdStatus));
} // ..if (irq.bits.GNSSDone)
} // ..if (irq.dword != 0)
return false;
}
char Radio::chip_ver[24];
const char* const Radio::chipNum_str = chip_ver;
const char* const Radio::opmode_select_strs[] = {
"SLEEP ", // 0
"STDBY-RC ", // 1
"STDBY-XOSC", // 2
"FS ", // 3
"RX ", // 4
"TX ", // 5
NULL
};
menuMode_e Radio::opmode_write(unsigned sel)
{
//stat_t stat;
uint8_t buf[5];
switch (sel) {
case 0: //sleep
{
unsigned ticks = 0;
buf[0] = 1; // sleep config: dont wakeup, retain chip state
radio.to_big_endian24(ticks, buf+1);
/*stat.word =*/ radio.xfer(OPCODE_SET_SLEEP, 5, 0, buf);
}
break;
case 1: // stby-rc
buf[0] = 0;
/*stat.word =*/ radio.xfer(OPCODE_SET_STANDBY, 1, 0, buf);
break;
case 2: // stby-xosc
buf[0] = 1;
/*stat.word =*/ radio.xfer(OPCODE_SET_STANDBY, 1, 0, buf);
break;
case 3: // fs
setFS();
break;
case 4: // rx
{
unsigned ticks = 0xffffff; // all 1's: receive until commanded to stop
radio.to_big_endian24(ticks, buf);
log_printf("setRx %02x %02x %02x\r\n", buf[0], buf[1], buf[2]);
/*stat.word =*/ radio.xfer(OPCODE_SET_RX, 3, 0, buf);
}
break;
case 5: // tx
{
unsigned ticks = 0; // 0 = disable-tx-timeout
radio.to_big_endian24(ticks, buf);
log_printf("setTx %02x %02x %02x\r\n", buf[0], buf[1], buf[2]);
/*stat.word =*/ radio.xfer(OPCODE_SET_TX, 3, 0, buf);
}
break;
}
return MENUMODE_REDRAW;
}
const char* const Radio::opmode_status_strs[] = {
"SLEEP ", // 0
"STDBY-RC ", // 1
"STDBY-XOSC", // 2
"FS ", // 3
"RX ", // 4
"TX ", // 5
"wifi/gnss ", // 6
NULL
};
unsigned Radio::opmode_read(bool forWriting)
{
uint8_t buf[4];
stat_t stat;
stat.word = radio.xfer(OPCODE_GET_STATUS, 4, 0, buf);
return stat.bits.chipMode;
}
const char* const Radio::pktType_strs[] = {
"NONE ",
"GFSK ",
"LORA ",
NULL
};
unsigned Radio::pktType_read(bool fw)
{
return radio.getPacketType();
}
menuMode_e Radio::pktType_write(unsigned idx)
{
//stat_t stat;
uint8_t buf = idx;
/*stat.word =*/ radio.xfer(OPCODE_SET_PACKET_TYPE, 1, 0, &buf);
return MENUMODE_REINIT_MENU;
}
bool Radio::tx_dbm_write(const char* str)
{
int dbm;
sscanf(str, "%d", &dbm);
tx_param_buf[0] = dbm;
radio.xfer(OPCODE_SET_TXPARAMS, 2, 0, tx_param_buf);
return false;
}
void Radio::tx_dbm_print()
{
txParamsB_t txpb; // txpb.bits.PaSel
txParamsC_t txpc;
radio.memRegRead(REG_ADDR_TX_PARAMS_C, 1, &txpc.dword);
radio.memRegRead(REG_ADDR_TX_PARAMS_B, 1, &txpb.dword);
if (txpb.bits.PaSel)
printf("%d", txpc.bits.tx_dbm - 9);
else
printf("%d", txpc.bits.tx_dbm - 17);
}
const char* Radio::tx_ramp_strs[] = {
"10 ", // 0
"20 ", // 1
"40 ", // 2
"80 ", // 3
"200 ", // 4
"800 ", // 5
"1700", // 6
"3400", // 7
NULL
};
unsigned Radio::tx_ramp_read(bool fw)
{
txParamsC_t txpc;
radio.memRegRead(REG_ADDR_TX_PARAMS_C, 1, &txpc.dword);
return txpc.bits.pa_ramp_time;
}
menuMode_e Radio::tx_ramp_write(unsigned sidx)
{
tx_param_buf[1] = sidx;
radio.xfer(OPCODE_SET_TXPARAMS, 2, 0, tx_param_buf);
return MENUMODE_REDRAW;
}
void Radio::tx_payload_length_print()
{
printf("%u", get_payload_length());
}
#endif /* ..SX1265_H */