test sending sensor results over lora radio. Accelerometer and temp/pressure.
Serial terminal operates at 115200.
This project provides a text-based menu over serial port.
Operating the program only requires using the arrow keys, enter key to activate a control, or entering numbers.
Two sensors provided:
LIS12DH12
accelerometer operates in a continuous sampling mode. Enable control for accelerometer enables this continuous sampling, approx every 3 seconds.
LPS22HH temperature / pressure sensor operates as single shot, where pressing the control button on terminal causes single sample to be performed.
poll rate control will enable repeated reading of pressure/temperature-sensor or photo-sensor when poll rate is greater than zero.
target must be: DISCO_L072CZ_LRWAN1
radio_sx127x.cpp
- Committer:
- Wayne Roberts
- Date:
- 2019-04-29
- Revision:
- 2:972a5704f152
- Parent:
- 0:e1e70da93044
File content as of revision 2:972a5704f152:
#include "radio.h"
#ifdef SX127x_H
const char* const Radio::chipNum_str = "SX127x";
const RadioEvents_t* Radio::RadioEvents;
LowPowerTimer Radio::lpt;
uint8_t Radio::bw_idx;
RegPaRamp_t Radio::RegPaRamp;
const char* opModes[] = {
"SLEEP ", // 0
"STANDBY ", // 1
"FS_TX ", // 2
"TX ", // 3
"FS_RX ", // 4
"RX ", // 5
"RX_SINGLE", // 6
"CAD " // 7
};
const char* Radio::tx_ramp_strs[] = {
"3400", // 0
"2000", // 1
"1000", // 2
"500 ", // 3
"250 ", // 4
"125 ", // 5
"100 ", // 6
"62 ", // 7
"50 ", // 8
"40 ", // 9
"31 ", // 10
"25 ", // 11
"20 ", // 12
"15 ", // 13
"12 ", // 14
"10 ", // 15
NULL
};
unsigned Radio::tx_ramp_read(bool fw)
{
RegPaRamp.octet = radio.read_reg(REG_PARAMP);
return RegPaRamp.bits.PaRamp;
}
menuMode_e Radio::tx_ramp_write(unsigned val)
{
RegPaRamp.octet = radio.read_reg(REG_PARAMP);
RegPaRamp.bits.PaRamp = val;
radio.write_reg(REG_PARAMP, RegPaRamp.octet);
return MENUMODE_REDRAW;
}
const char* const Radio::pktType_strs[] = {
"FSK ", // 0
"OOK ", // 1
"LORA", // 2
NULL
};
unsigned Radio::pktType_read(bool fw)
{
radio.RegOpMode.octet = radio.read_reg(REG_OPMODE);
if (radio.RegOpMode.bits.LongRangeMode)
return 2;
else
return radio.RegOpMode.bits.ModulationType;
}
menuMode_e Radio::pktType_write(unsigned idx)
{
if (idx == 2) {
if (!radio.RegOpMode.bits.LongRangeMode) {
/* to lora */
radio.set_opmode(RF_OPMODE_SLEEP);
radio.RegOpMode.bits.LongRangeMode = 1;
wait_us(1000);
radio.write_reg(REG_OPMODE, radio.RegOpMode.octet);
}
} else {
if (radio.RegOpMode.bits.LongRangeMode) {
/* from lora */
radio.set_opmode(RF_OPMODE_SLEEP);
radio.RegOpMode.bits.LongRangeMode = 0;
wait_us(1000);
radio.write_reg(REG_OPMODE, radio.RegOpMode.octet);
}
if (radio.RegOpMode.bits.ModulationType != idx) {
radio.RegOpMode.bits.ModulationType = idx;
radio.write_reg(REG_OPMODE, radio.RegOpMode.octet);
}
}
return MENUMODE_REINIT_MENU;
}
void Radio::hw_reset()
{
radio.hw_reset();
}
void Radio::clearIrqFlags()
{
if (radio.RegOpMode.bits.LongRangeMode) {
radio.write_reg(REG_LR_IRQFLAGS, 0xff); // clear flags in radio
} else {
radio.write_reg(REG_FSK_IRQFLAGS1, 0x0b);
radio.write_reg(REG_FSK_IRQFLAGS2, 0x11);
}
}
void Radio::readChip()
{
}
uint8_t Radio::get_payload_length()
{
if (radio.RegOpMode.bits.LongRangeMode) {
lora.RegPayloadLength = radio.read_reg(REG_LR_PAYLOADLENGTH);
return lora.RegPayloadLength;
} else {
fsk.RegPktConfig2.word = radio.read_u16(REG_FSK_PACKETCONFIG2);
return fsk.RegPktConfig2.bits.PayloadLength;
}
}
void Radio::set_payload_length(uint8_t len)
{
if (radio.RegOpMode.bits.LongRangeMode) {
lora.RegPayloadLength = len;
radio.write_reg(REG_LR_PAYLOADLENGTH, lora.RegPayloadLength);
} else {
fsk.RegPktConfig2.bits.PayloadLength = len;
radio.write_u16(REG_FSK_PACKETCONFIG2, fsk.RegPktConfig2.word);
}
}
void Radio::Rx()
{
if (radio.RegOpMode.bits.LongRangeMode)
lora.start_rx(RF_OPMODE_RECEIVER);
else
fsk.start_rx();
}
void Radio::txPkt()
{
if (radio.RegOpMode.bits.LongRangeMode) {
lora.RegPayloadLength = radio.read_reg(REG_LR_PAYLOADLENGTH);
lora.start_tx(lora.RegPayloadLength);
} else {
fsk.RegPktConfig2.word = radio.read_u16(REG_FSK_PACKETCONFIG2);
//log_printf("fsk payLen %u\r\n", fsk.RegPktConfig2.bits.PayloadLength);
fsk.start_tx(fsk.RegPktConfig2.bits.PayloadLength);
}
}
void Radio::tx_carrier()
{
radio.set_opmode(RF_OPMODE_SLEEP);
fsk.enable(false);
radio.write_u16(REG_FSK_FDEVMSB, 0);
radio.write_u16(REG_FSK_PREAMBLEMSB, 0xffff);
fsk.start_tx(8);
}
void Radio::tx_preamble()
{
if (radio.RegOpMode.bits.LongRangeMode) {
radio.write_u16(REG_LR_PREAMBLEMSB, 0xffff);
lora.start_tx(8);
} else {
radio.write_u16(REG_FSK_PREAMBLEMSB, 0xffff);
fsk.start_tx(8);
}
}
bool Radio::service(int8_t statusRow)
{
bool ret = false;
static RegIrqFlags1_t prevRegIrqFlags1;
static RegIrqFlags2_t prevRegIrqFlags2;
static us_timestamp_t prev_now;
us_timestamp_t now = lpt.read_us();
if (radio.RegOpMode.bits.LongRangeMode) {
const float bws[] = {7.8, 10.4, 15.6, 20.8, 31.25, 41.7, 62.5, 125, 250, 500};
int32_t est_freq_error;
int idx, hz;
service_action_e act = lora.service();
switch (act) {
case SERVICE_READ_FIFO:
est_freq_error = radio.read_reg(REG_LR_TEST28);
est_freq_error <<= 8;
est_freq_error += radio.read_reg(REG_LR_TEST29);
est_freq_error <<= 8;
est_freq_error += radio.read_reg(REG_LR_TEST2A);
if (est_freq_error & 0x80000)
est_freq_error |= 0xfff00000; // extend sign from 20bit to 32bit
//log_printf("est_freq_error:%08x\r\n", est_freq_error);
if (radio.type == SX1272)
idx = bw_idx + 7;
else
idx = bw_idx;
hz = est_freq_error * -0.524288 * bws[idx] / 500;
log_printf("hz:%d\r\n", hz);
RadioEvents->RxDone(lora.RegRxNbBytes, lora.get_pkt_rssi(), lora.RegPktSnrValue / 4.0);
break;
case SERVICE_TX_DONE:
if (RadioEvents->TxDone_botHalf)
RadioEvents->TxDone_botHalf();
break;
case SERVICE_ERROR:
case SERVICE_NONE:
break;
}
if (radio.RegOpMode.bits.Mode == RF_OPMODE_CAD) {
if (radio.dio1 || radio.dio0) {
RegIrqFlags_t irqFlags;
irqFlags.octet = 0;
log_printf("Cad: ");
if (radio.dio0) {
pc.printf("Done ");
radio.RegOpMode.bits.Mode = RF_OPMODE_STANDBY;
irqFlags.bits.CadDone = 1;
}
if (radio.dio1) {
pc.printf("Detected");
irqFlags.bits.CadDetected = 1;
}
pc.printf("\r\n");
radio.write_reg(REG_LR_IRQFLAGS, irqFlags.octet);
}
}
} else {
service_action_e act = fsk.service();
switch (act) {
case SERVICE_READ_FIFO:
/*if (fsk.RegRxConfig.bits.AfcAutoOn) {
printf("%dHz ", (int)(FREQ_STEP_HZ * fsk.RegAfcValue));
if (rssi != 0) {
printf("pkt:-%.1fdBm ", rssi / 2.0);
rssi = 0;
}
}*/
if (fsk.RegRxConfig.bits.AfcAutoOn)
log_printf("%dHz\r\n", (int)(FREQ_STEP_HZ * fsk.RegAfcValue));
RadioEvents->RxDone(fsk.rx_buf_length, /*TODO rssi*/0, 0);
break;
case SERVICE_TX_DONE:
if (RadioEvents->TxDone_botHalf)
RadioEvents->TxDone_botHalf();
break;
case SERVICE_ERROR:
case SERVICE_NONE:
break;
}
if (statusRow > 0 && now-prev_now > 50000) {
RegIrqFlags1_t RegIrqFlags1;
RegIrqFlags2_t RegIrqFlags2;
RegIrqFlags1.octet = radio.read_reg(REG_FSK_IRQFLAGS1);
RegIrqFlags2.octet = radio.read_reg(REG_FSK_IRQFLAGS2);
prev_now = now;
if (RegIrqFlags1.octet != prevRegIrqFlags1.octet || RegIrqFlags2.octet != prevRegIrqFlags2.octet) {
pc.printf("\e[%u;1f", statusRow); // set (force) cursor to row;column
if (RegIrqFlags1.bits.ModeReady)
pc.printf("ModeReady ");
if (RegIrqFlags1.bits.RxReady)
pc.printf("RxReady ");
if (RegIrqFlags1.bits.TxReady)
pc.printf("TxReady ");
if (RegIrqFlags1.bits.PllLock)
pc.printf("PllLock ");
if (RegIrqFlags1.bits.Rssi)
pc.printf("Rssi ");
if (RegIrqFlags1.bits.Timeout)
pc.printf("Timeout ");
if (RegIrqFlags1.bits.PreambleDetect)
pc.printf("PreambleDetect ");
if (RegIrqFlags1.bits.SyncAddressMatch)
pc.printf("SyncAddressMatch ");
pc.printf(" | ");
if (RegIrqFlags2.bits.FifoFull)
pc.printf("FifoFull ");
if (RegIrqFlags2.bits.FifoEmpty)
pc.printf("FifoEmpty ");
if (RegIrqFlags2.bits.FifoLevel)
pc.printf("FifoLevel ");
if (RegIrqFlags2.bits.FifoOverrun)
pc.printf("FifoOverrun ");
if (RegIrqFlags2.bits.PacketSent)
pc.printf("PacketSent ");
if (RegIrqFlags2.bits.PayloadReady)
pc.printf("PayloadReady ");
if (RegIrqFlags2.bits.CrcOk)
pc.printf("CrcOk ");
if (RegIrqFlags2.bits.LowBat)
pc.printf("LowBat ");
prevRegIrqFlags1.octet = RegIrqFlags1.octet;
prevRegIrqFlags2.octet = RegIrqFlags2.octet;
pc.printf("\e[K");
ret = true;
} // ..if irq flag changed
} // ..if (++cnt > X)
} // ..!radio.RegOpMode.bits.LongRangeMode
return ret;
}
void Radio::setFS()
{
radio.set_opmode(RF_OPMODE_SYNTHESIZER_RX);
}
const menu_t* Radio::get_modem_sub_menu()
{
radio.RegOpMode.octet = radio.read_reg(REG_OPMODE);
if (radio.RegOpMode.bits.LongRangeMode) {
return NULL;
} else {
if (radio.RegOpMode.bits.ModulationType == 1) {
fsk.RegOokPeak.octet = radio.read_reg(REG_FSK_OOKPEAK);
if (fsk.RegOokPeak.bits.OokThreshType == 0) {
return ook_fixed_menu;
} else if (fsk.RegOokPeak.bits.OokThreshType == 1) {
return ook_peak_menu;
} else if (fsk.RegOokPeak.bits.OokThreshType == 2) {
return ook_average_menu;
}
} else
return NULL;
}
return NULL;
}
const menu_t* Radio::get_modem_menu()
{
radio.RegOpMode.octet = radio.read_reg(REG_OPMODE);
if (radio.RegOpMode.bits.LongRangeMode) {
return lora_menu;
} else {
if (radio.RegOpMode.bits.ModulationType == 0)
return fsk_menu;
else {
return ook_menu;
}
}
}
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);
//log_printf("scanned %u from \"%s\"\r\n", len, txt);
set_payload_length(len);
return false;
}
const char* const Radio::opmode_status_strs[] = {
"SLEEP ", // 0
"STANDBY ", // 1
"FS_TX ", // 2
"TX ", // 3
"FS_RX ", // 4
"RX ", // 5
"RX_SINGLE", // 6
"CAD ", // 7
NULL
};
const char* const Radio::opmode_select_strs[] = {
"SLEEP ", // 0
"STANDBY ", // 1
"FS_TX ", // 2
"TX ", // 3
"FS_RX ", // 4
"RX ", // 5
"RX_SINGLE", // 6
"CAD ", // 7
NULL
};
unsigned Radio::opmode_read(bool forWriting)
{
radio.RegOpMode.octet = radio.read_reg(REG_OPMODE);
return radio.RegOpMode.bits.Mode;
}
menuMode_e Radio::opmode_write(unsigned sel)
{
radio.RegOpMode.bits.Mode = sel;
radio.write_reg(REG_OPMODE, radio.RegOpMode.octet);
return MENUMODE_REDRAW;
}
void Radio::ocp_print(void)
{
unsigned i;
radio.RegOcp.octet = radio.read_reg(REG_OCP);
if (radio.RegOcp.bits.OcpTrim < 16)
i = 45 + (5 * radio.RegOcp.bits.OcpTrim);
else if (radio.RegOcp.bits.OcpTrim < 28)
i = (10 * radio.RegOcp.bits.OcpTrim) - 30;
else
i = 240;
pc.printf("%u", i);
}
bool Radio::ocp_write(const char* txt)
{
unsigned i;
sscanf(txt, "%u", &i);
if (i < 130)
radio.RegOcp.bits.OcpTrim = (i - 45) / 5;
else
radio.RegOcp.bits.OcpTrim = (i + 30) / 10;
radio.write_reg(REG_OCP, radio.RegOcp.octet);
return MENUMODE_REDRAW;
}
const value_item_t Radio::ocp_item = { _ITEM_VALUE, 4, ocp_print, ocp_write};
static const char* const lora_bws_1276[] = {
" 7.8KHz", // 0
" 10.4KHz", // 1
" 15.6KHz", // 2
" 20.8KHz", // 3
"31.25KHz", // 4
" 41.7KHz", // 5
" 62.5KHz", // 6
" 125KHz", // 7
" 250KHz", // 8
" 500KHz", // 9
NULL
};
static const char* const lora_bws_1272[] = {
"125KHz", // 0
"250KHz", // 1
"500KHz", // 2
NULL
};
unsigned Radio::lora_bw_read(bool fw)
{
bw_idx = lora.getBw();
return bw_idx;
}
menuMode_e Radio::lora_bw_write(unsigned sidx)
{
lora.setBw(sidx);
bw_idx = sidx;
return MENUMODE_REDRAW;
}
dropdown_item_t Radio::lora_bw_item = { _ITEM_DROPDOWN, NULL, NULL, lora_bw_read, lora_bw_write};
void Radio::lora_sf_print()
{
pc.printf("%u", lora.getSf());
}
bool Radio::lora_sf_write(const char* txt)
{
unsigned sf;
sscanf(txt, "%u", &sf);
lora.setSf(sf);
return false;
}
const value_item_t Radio::lora_sf_item = { _ITEM_VALUE, 3, lora_sf_print, lora_sf_write };
const char* const lora_crs[] = {
"4/5", // 0
"4/6", // 1
"4/7", // 2
"4/8", // 3
NULL
};
unsigned Radio::lora_cr_read(bool)
{
return lora.getCodingRate(false);
}
menuMode_e Radio::lora_cr_write(unsigned sidx)
{
lora.setCodingRate(sidx);
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()
{
lora.RegPreamble = radio.read_u16(REG_LR_PREAMBLEMSB);
pc.printf("%u", lora.RegPreamble);
}
bool Radio::lora_pblLen_write(const char* str)
{
unsigned n;
sscanf(str, "%u", &n);
lora.RegPreamble = n;
radio.write_u16(REG_LR_PREAMBLEMSB, lora.RegPreamble);
return false;
}
const value_item_t Radio::lora_pblLen_item = { _ITEM_VALUE, 5, lora_pblLen_print, lora_pblLen_write};
static const char* const lora_fixlen[] = {
"EXPLICIT", // 0
"IMPLICIT", // 1
NULL
};
unsigned Radio::lora_fixlen_read(bool f)
{
if (lora.getHeaderMode())
return 1;
else
return 0;
}
menuMode_e Radio::lora_fixlen_write(unsigned sidx)
{
lora.setHeaderMode(sidx == 1); // true = implicit
return MENUMODE_REDRAW;
}
const dropdown_item_t Radio::lora_fixlen_item = { _ITEM_DROPDOWN, lora_fixlen, lora_fixlen, lora_fixlen_read, lora_fixlen_write};
bool Radio::lora_crcon_read()
{
return lora.getRxPayloadCrcOn();
}
bool Radio::lora_crcon_push()
{
lora.setRxPayloadCrcOn(!lora.getRxPayloadCrcOn());
return lora.getRxPayloadCrcOn();
}
const toggle_item_t Radio::lora_crcon_item = { _ITEM_TOGGLE, "CrcOn", NULL, lora_crcon_read, lora_crcon_push};
bool Radio::lora_iqinvTX_read()
{
lora.RegTest33.octet = radio.read_reg(REG_LR_TEST33);
return !lora.RegTest33.bits.chirp_invert_tx;
}
bool Radio::lora_iqinvTX_push()
{
lora.invert_tx(lora.RegTest33.bits.chirp_invert_tx);
return !lora.RegTest33.bits.chirp_invert_tx;
}
const toggle_item_t Radio::lora_iqinvTX_item = { _ITEM_TOGGLE, "iqInvTX", NULL, lora_iqinvTX_read, lora_iqinvTX_push};
bool Radio::lora_iqinvRX_read()
{
lora.RegTest33.octet = radio.read_reg(REG_LR_TEST33);
return lora.RegTest33.bits.invert_i_q;
}
bool Radio::lora_iqinvRX_push()
{
lora.invert_rx(!lora.RegTest33.bits.invert_i_q);
lora.RegTest33.octet = radio.read_reg(REG_LR_TEST33);
return lora.RegTest33.bits.invert_i_q;
}
const toggle_item_t Radio::lora_iqinvRX_item = { _ITEM_TOGGLE, "iqInvRX", NULL, lora_iqinvRX_read, lora_iqinvRX_push};
void Radio::lora_ppg_print()
{
pc.printf("%02x", radio.read_reg(REG_LR_SYNC_BYTE));
}
bool Radio::lora_ppg_write(const char* str)
{
unsigned ppg;
sscanf(str, "%x", &ppg);
radio.write_reg(REG_LR_SYNC_BYTE, ppg);
return false;
}
const value_item_t Radio::lora_ppg_item = { _ITEM_VALUE, 4, lora_ppg_print, lora_ppg_write};
void Radio::cadrx_push()
{
if (radio.RegDioMapping1.bits.Dio0Mapping != 2 || radio.RegDioMapping1.bits.Dio1Mapping != 2) {
radio.RegDioMapping1.bits.Dio0Mapping = 2; // DIO0 to CadDone
radio.RegDioMapping1.bits.Dio1Mapping = 2; // DIO1 to CadDetected
radio.write_reg(REG_DIOMAPPING1, radio.RegDioMapping1.octet);
}
radio.set_opmode(RF_OPMODE_CAD);
}
const button_item_t Radio::lora_cadrx_item = { _ITEM_BUTTON, "CADRX", cadrx_push };
const menu_t Radio::lora_menu[] = {
{ {FIRST_CHIP_MENU_ROW, 22}, "bw:", &lora_bw_item, FLAG_MSGTYPE_ALL },
{ {FIRST_CHIP_MENU_ROW, 35}, "sf:", &lora_sf_item, FLAG_MSGTYPE_ALL },
{ {FIRST_CHIP_MENU_ROW, 42}, "cr:", &lora_cr_item, FLAG_MSGTYPE_ALL },
{ {FIRST_CHIP_MENU_ROW, 50}, "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, 10}, NULL, &lora_crcon_item, FLAG_MSGTYPE_ALL },
{ {FIRST_CHIP_MENU_ROW+1, 20}, NULL, &lora_iqinvTX_item, FLAG_MSGTYPE_ALL },
{ {FIRST_CHIP_MENU_ROW+1, 30}, NULL, &lora_iqinvRX_item, FLAG_MSGTYPE_ALL },
{ {FIRST_CHIP_MENU_ROW+1, 40}, "ppg:", &lora_ppg_item, FLAG_MSGTYPE_ALL },
{ {FIRST_CHIP_MENU_ROW+2, 1}, NULL, &lora_cadrx_item, FLAG_MSGTYPE_ALL },
{ {0, 0}, NULL, NULL }
};
void Radio::fsk_ook_bps_print(void)
{
pc.printf("%lu", fsk.get_bitrate());
}
bool Radio::fsk_ook_bps_write(const char* txt)
{
unsigned bps;
sscanf(txt, "%u", &bps);
fsk.set_bitrate(bps);
return false;
}
const value_item_t Radio::fsk_ook_bitrate_item = { _ITEM_VALUE, 8, fsk_ook_bps_print, fsk_ook_bps_write };
void Radio::gfsk_fdev_print(void)
{
pc.printf("%lu", fsk.get_tx_fdev_hz());
}
bool Radio::gfsk_fdev_write(const char* txt)
{
unsigned hz;
sscanf(txt, "%u", &hz);
fsk.set_tx_fdev_hz(hz);
return false;
}
const value_item_t Radio::gfsk_fdev_item = { _ITEM_VALUE, 8, gfsk_fdev_print, gfsk_fdev_write};
const char* const gfsk_bts[] = {
"off", // 0
"1.0", // 1
"0.5", // 2
"0.3", // 3
NULL
};
const char* const ook_bts[] = {
"off ", // 0
"bitRate ", // 1
"2*bitRate", // 2
NULL
};
unsigned Radio::bt_read(bool forWriting)
{
if (radio.type == SX1276) {
RegPaRamp.octet = radio.read_reg(REG_PARAMP);
return RegPaRamp.bits.ModulationShaping;
} else if (radio.type == SX1272) {
radio.RegOpMode.octet = radio.read_reg(REG_OPMODE);
return radio.RegOpMode.bits.ModulationShaping;
}
return 3;
}
menuMode_e Radio::bt_write(unsigned sel)
{
if (radio.type == SX1276) {
RegPaRamp.bits.ModulationShaping = sel;
radio.write_reg(REG_PARAMP, RegPaRamp.octet);
} else if (radio.type == SX1272) {
radio.RegOpMode.bits.ModulationShaping = sel;
radio.write_reg(REG_OPMODE, radio.RegOpMode.octet);
}
return MENUMODE_REDRAW;
}
const dropdown_item_t Radio::gfsk_bt_item = { _ITEM_DROPDOWN, gfsk_bts, gfsk_bts, bt_read, bt_write};
const dropdown_item_t Radio::ook_bt_item = { _ITEM_DROPDOWN, ook_bts, ook_bts, bt_read, bt_write};
bool Radio::paSelect_read()
{
radio.RegPaConfig.octet = radio.read_reg(REG_PACONFIG);
return radio.RegPaConfig.bits.PaSelect;
}
bool Radio::paSelect_push()
{
radio.RegPaConfig.bits.PaSelect ^= 1;
radio.write_reg(REG_PACONFIG, radio.RegPaConfig.octet);
return radio.RegPaConfig.bits.PaSelect;
}
const toggle_item_t Radio::paSelect_item = { _ITEM_TOGGLE,
"RFO ", // 0
"PA_BOOST", // 1
paSelect_read, paSelect_push
};
const char* const rxbws[] = {
" 2.6", // 0
" 3.1", // 1
" 3.9", // 2
" 5.2", // 3
" 6.3", // 4
" 7.8", // 5
" 10.4", // 6
" 12.5", // 7
" 15.6", // 8
" 20.8", // 9
" 25.0", // 10
" 31.3", // 11
" 41.7", // 12
" 50.0", // 13
" 62.5", // 14
" 83.3", // 15
"100.0", // 16
"125.0", // 17
"166.7", // 18
"200.0", // 19
"250.0", // 20
NULL
};
unsigned Radio::bw_read(uint8_t regAddr)
{
RegRxBw_t reg_bw;
reg_bw.octet = radio.read_reg(regAddr);
switch (reg_bw.bits.Exponent) {
case 7:
if (reg_bw.bits.Mantissa == 2)
return 0;
if (reg_bw.bits.Mantissa == 1)
return 1;
if (reg_bw.bits.Mantissa == 0)
return 2;
break;
case 6:
if (reg_bw.bits.Mantissa == 2)
return 3;
if (reg_bw.bits.Mantissa == 1)
return 4;
if (reg_bw.bits.Mantissa == 0)
return 5;
break;
case 5:
if (reg_bw.bits.Mantissa == 2)
return 6;
if (reg_bw.bits.Mantissa == 1)
return 7;
if (reg_bw.bits.Mantissa == 0)
return 8;
break;
case 4:
if (reg_bw.bits.Mantissa == 2)
return 9;
if (reg_bw.bits.Mantissa == 1)
return 10;
if (reg_bw.bits.Mantissa == 0)
return 11;
break;
case 3:
if (reg_bw.bits.Mantissa == 2)
return 12;
if (reg_bw.bits.Mantissa == 1)
return 13;
if (reg_bw.bits.Mantissa == 0)
return 14;
break;
case 2:
if (reg_bw.bits.Mantissa == 2)
return 15;
if (reg_bw.bits.Mantissa == 1)
return 16;
if (reg_bw.bits.Mantissa == 0)
return 17;
break;
case 1:
if (reg_bw.bits.Mantissa == 2)
return 18;
if (reg_bw.bits.Mantissa == 1)
return 19;
if (reg_bw.bits.Mantissa == 0)
return 20;
break;
}
return 21;
}
unsigned Radio::rxbw_read(bool)
{
return bw_read(REG_FSK_RXBW);
}
unsigned Radio::afcbw_read(bool)
{
return bw_read(REG_FSK_AFCBW);
}
void Radio::bw_write(unsigned sidx, uint8_t regAddr)
{
RegRxBw_t reg_bw;
reg_bw.octet = radio.read_reg(regAddr);
switch (sidx) {
case 0:
reg_bw.bits.Mantissa = 2;
reg_bw.bits.Exponent = 7;
break;
case 1:
reg_bw.bits.Mantissa = 1;
reg_bw.bits.Exponent = 7;
break;
case 2:
reg_bw.bits.Mantissa = 0;
reg_bw.bits.Exponent = 7;
break;
case 3:
reg_bw.bits.Mantissa = 2;
reg_bw.bits.Exponent = 6;
break;
case 4:
reg_bw.bits.Mantissa = 1;
reg_bw.bits.Exponent = 6;
break;
case 5:
reg_bw.bits.Mantissa = 0;
reg_bw.bits.Exponent = 6;
break;
case 6:
reg_bw.bits.Mantissa = 2;
reg_bw.bits.Exponent = 5;
break;
case 7:
reg_bw.bits.Mantissa = 1;
reg_bw.bits.Exponent = 5;
break;
case 8:
reg_bw.bits.Mantissa = 0;
reg_bw.bits.Exponent = 5;
break;
case 9:
reg_bw.bits.Mantissa = 2;
reg_bw.bits.Exponent = 4;
break;
case 10:
reg_bw.bits.Mantissa = 1;
reg_bw.bits.Exponent = 4;
break;
case 11:
reg_bw.bits.Mantissa = 0;
reg_bw.bits.Exponent = 4;
break;
case 12:
reg_bw.bits.Mantissa = 2;
reg_bw.bits.Exponent = 3;
break;
case 13:
reg_bw.bits.Mantissa = 1;
reg_bw.bits.Exponent = 3;
break;
case 14:
reg_bw.bits.Mantissa = 0;
reg_bw.bits.Exponent = 3;
break;
case 15:
reg_bw.bits.Mantissa = 2;
reg_bw.bits.Exponent = 2;
break;
case 16:
reg_bw.bits.Mantissa = 1;
reg_bw.bits.Exponent = 2;
break;
case 17:
reg_bw.bits.Mantissa = 0;
reg_bw.bits.Exponent = 2;
break;
case 18:
reg_bw.bits.Mantissa = 2;
reg_bw.bits.Exponent = 1;
break;
case 19:
reg_bw.bits.Mantissa = 1;
reg_bw.bits.Exponent = 1;
break;
case 20:
reg_bw.bits.Mantissa = 0;
reg_bw.bits.Exponent = 1;
break;
}
radio.write_reg(regAddr, reg_bw.octet);
}
menuMode_e Radio::rxbw_write(unsigned sidx)
{
bw_write(sidx, REG_FSK_RXBW);
return MENUMODE_REDRAW;
}
menuMode_e Radio::afcbw_write(unsigned sidx)
{
bw_write(sidx, REG_FSK_AFCBW);
return MENUMODE_REDRAW;
}
const dropdown_item_t Radio::rxbw_item = { _ITEM_DROPDOWN, rxbws, rxbws, rxbw_read, rxbw_write};
const dropdown_item_t Radio::afcbw_item = { _ITEM_DROPDOWN, rxbws, rxbws, afcbw_read, afcbw_write};
void Radio::pblLen_print()
{
pc.printf("%u", radio.read_u16(REG_FSK_PREAMBLEMSB));
}
bool Radio::pblLen_write(const char* txt)
{
unsigned n;
sscanf(txt, "%u", &n);
radio.write_u16(REG_FSK_PREAMBLEMSB, n);
return false;
}
const value_item_t Radio::pblLen_item = { _ITEM_VALUE, 6, pblLen_print, pblLen_write};
const char* const rxTriggers[] = {
"off ", // 0
"RSSI ", // 1
"Preamble ", // 2
"RSSI+Preamble", // 3
NULL
};
unsigned Radio::rxTrigger_read(bool fw)
{
fsk.RegRxConfig.octet = radio.read_reg(REG_FSK_RXCONFIG);
return fsk.RegRxConfig.bits.RxTrigger;
}
menuMode_e Radio::rxTrigger_write(unsigned sidx)
{
fsk.RegRxConfig.bits.RxTrigger = sidx;
radio.write_reg(REG_FSK_RXCONFIG, fsk.RegRxConfig.octet);
return MENUMODE_REDRAW;
}
const dropdown_item_t Radio::rxTrigger_item = { _ITEM_DROPDOWN, rxTriggers, rxTriggers, rxTrigger_read, rxTrigger_write};
bool Radio::AgcAutoOn_read()
{
fsk.RegRxConfig.octet = radio.read_reg(REG_FSK_RXCONFIG);
return fsk.RegRxConfig.bits.AgcAutoOn;
}
bool Radio::AgcAutoOn_push()
{
fsk.RegRxConfig.bits.AgcAutoOn ^= 1;
radio.write_reg(REG_FSK_RXCONFIG, fsk.RegRxConfig.octet);
return fsk.RegRxConfig.bits.AgcAutoOn;
}
bool Radio::AfcAutoOn_read()
{
fsk.RegRxConfig.octet = radio.read_reg(REG_FSK_RXCONFIG);
return fsk.RegRxConfig.bits.AfcAutoOn;
}
bool Radio::AfcAutoOn_push()
{
fsk.RegRxConfig.bits.AfcAutoOn ^= 1;
radio.write_reg(REG_FSK_RXCONFIG, fsk.RegRxConfig.octet);
return fsk.RegRxConfig.bits.AfcAutoOn;
}
const toggle_item_t Radio::agcautoon_item = { _ITEM_TOGGLE, "AgcAutoOn", NULL, AgcAutoOn_read, AgcAutoOn_push};
const toggle_item_t Radio::afcautoon_item = { _ITEM_TOGGLE, "AfcAutoOn", NULL, AfcAutoOn_read, AfcAutoOn_push};
bool Radio::RestartRxOnCollision_read()
{
fsk.RegRxConfig.octet = radio.read_reg(REG_FSK_RXCONFIG);
return fsk.RegRxConfig.bits.RestartRxOnCollision;
}
bool Radio::RestartRxOnCollision_push()
{
fsk.RegRxConfig.bits.RestartRxOnCollision ^= 1;
radio.write_reg(REG_FSK_RXCONFIG, fsk.RegRxConfig.octet);
return fsk.RegRxConfig.bits.RestartRxOnCollision;
}
const toggle_item_t Radio::RestartRxOnCollision_item = { _ITEM_TOGGLE,
"RestartRxOnCollision", NULL,
RestartRxOnCollision_read, RestartRxOnCollision_push
};
void Radio::RestartRxWithPllLock_push()
{
fsk.RegRxConfig.bits.RestartRxWithPllLock = 1;
radio.write_reg(REG_FSK_RXCONFIG, fsk.RegRxConfig.octet);
fsk.RegRxConfig.bits.RestartRxWithPllLock = 0;
}
const button_item_t Radio::RestartRxWithPllLock_item = { _ITEM_BUTTON,
"RestartRxWithPllLock",
RestartRxWithPllLock_push
};
void Radio::RestartRxWithoutPllLock_push()
{
fsk.RegRxConfig.bits.RestartRxWithoutPllLock = 1;
radio.write_reg(REG_FSK_RXCONFIG, fsk.RegRxConfig.octet);
fsk.RegRxConfig.bits.RestartRxWithoutPllLock = 0;
}
const button_item_t Radio::RestartRxWithoutPllLock_item = { _ITEM_BUTTON,
"RestartRxWithoutPllLock",
RestartRxWithoutPllLock_push
};
bool Radio::AfcAutoClearOn_read(void)
{
fsk.RegAfcFei.octet = radio.read_reg(REG_FSK_AFCFEI);
return fsk.RegAfcFei.bits.AfcAutoClearOn;
}
bool Radio::AfcAutoClearOn_push(void)
{
fsk.RegAfcFei.bits.AfcAutoClearOn ^= 1;
radio.write_reg(REG_FSK_AFCFEI, fsk.RegAfcFei.octet);
return fsk.RegAfcFei.bits.AfcAutoClearOn;
}
const toggle_item_t Radio::AfcAutoClearOn_item = { _ITEM_TOGGLE, "AfcAutoClearOn", NULL, AfcAutoClearOn_read, AfcAutoClearOn_push};
void Radio::AgcStart_push()
{
fsk.RegAfcFei.bits.AgcStart = 1;
radio.write_reg(REG_FSK_AFCFEI, fsk.RegAfcFei.octet);
fsk.RegAfcFei.bits.AgcStart = 1;
}
const button_item_t Radio::AgcStart_item = { _ITEM_BUTTON, "AgcStart", AgcStart_push};
void Radio::AfcClear_push()
{
fsk.RegAfcFei.bits.AfcClear = 1;
radio.write_reg(REG_FSK_AFCFEI, fsk.RegAfcFei.octet);
fsk.RegAfcFei.bits.AfcClear = 0;
}
const button_item_t Radio::AfcClear_item = { _ITEM_BUTTON, "AfcClear", AfcClear_push};
void Radio::syncWord_print(void)
{
unsigned n, stop;
fsk.RegSyncConfig.octet = radio.read_reg(REG_FSK_SYNCCONFIG);
stop = fsk.RegSyncConfig.bits.SyncSize + 1;
for (n = 0; n < stop; n++) {
pc.printf("%02x", radio.read_reg(REG_FSK_SYNCVALUE1+n));
}
}
bool Radio::syncWord_write(const char* txt)
{
const char* ptr;
const char* endPtr;
unsigned o, n = 0;
endPtr = txt + strlen(txt);
for (ptr = txt; sscanf(ptr, "%02x", &o) == 1; ) {
radio.write_reg(REG_FSK_SYNCVALUE1+n, o);
n++;
ptr += 2;
if (ptr >= endPtr)
break;
}
fsk.RegSyncConfig.bits.SyncSize = n - 1;
radio.write_reg(REG_FSK_SYNCCONFIG, fsk.RegSyncConfig.octet);
return false;
}
const value_item_t Radio::syncWord_item = { _ITEM_VALUE, 17, syncWord_print, syncWord_write};
void Radio::syncSize_print(void)
{
fsk.RegSyncConfig.octet = radio.read_reg(REG_FSK_SYNCCONFIG);
pc.printf("%u", fsk.RegSyncConfig.bits.SyncSize + 1);
}
bool Radio::syncSize_write(const char* txt)
{
unsigned n;
sscanf(txt, "%u", &n);
if (n > 0) {
fsk.RegSyncConfig.bits.SyncSize = n - 1;
radio.write_reg(REG_FSK_SYNCCONFIG, fsk.RegSyncConfig.octet);
}
return false;
}
const value_item_t Radio::syncSize_item = { _ITEM_VALUE, 2, syncSize_print, syncSize_write};
bool Radio::SyncOn_read()
{
fsk.RegSyncConfig.octet = radio.read_reg(REG_FSK_SYNCCONFIG);
return fsk.RegSyncConfig.bits.SyncOn;
}
bool Radio::SyncOn_push()
{
fsk.RegSyncConfig.bits.SyncOn ^= 1;
radio.write_reg(REG_FSK_SYNCCONFIG, fsk.RegSyncConfig.octet);
return fsk.RegSyncConfig.bits.SyncOn;
}
const toggle_item_t Radio::syncOn_item = { _ITEM_TOGGLE, "SyncOn", NULL, SyncOn_read, SyncOn_push};
bool Radio::fsk_pktfmt_read()
{
fsk.RegPktConfig1.octet = radio.read_reg(REG_FSK_PACKETCONFIG1);
return fsk.RegPktConfig1.bits.PacketFormatVariable;
}
bool Radio::fsk_pktfmt_push()
{
fsk.RegPktConfig1.bits.PacketFormatVariable ^= 1;
radio.write_reg(REG_FSK_PACKETCONFIG1, fsk.RegPktConfig1.octet);
return fsk.RegPktConfig1.bits.PacketFormatVariable;
}
const toggle_item_t Radio::fskook_pktfmt_item = { _ITEM_TOGGLE,
"fixed ",
"variable",
fsk_pktfmt_read, fsk_pktfmt_push
};
void Radio::rssiOffset_print(void)
{
int ro;
fsk.RegRssiConfig.octet = radio.read_reg(REG_FSK_RSSICONFIG);
ro = fsk.RegRssiConfig.bits.RssiOffset;
pc.printf("%d", ro);
}
bool Radio::rssiOffset_write(const char* txt)
{
int ro;
sscanf(txt, "%d", &ro);
fsk.RegRssiConfig.bits.RssiOffset = ro;
radio.write_reg(REG_FSK_RSSICONFIG, fsk.RegRssiConfig.octet);
return false;
}
const value_item_t Radio::rssiOffset_item = { _ITEM_VALUE, 2, rssiOffset_print, rssiOffset_write};
const char* const rssiSmoothings[] = {
"2 ", // 0
"4 ", // 1
"8 ", // 2
"16 ", // 3
"32 ", // 4
"64 ", // 5
"128", // 6
"256", // 7
NULL
};
unsigned Radio::rssiSmoothing_read(bool fw)
{
fsk.RegRssiConfig.octet = radio.read_reg(REG_FSK_RSSICONFIG);
return fsk.RegRssiConfig.bits.RssiSmoothing;
}
menuMode_e Radio::rssiSmoothing_write(unsigned sidx)
{
radio.write_reg(REG_FSK_RSSICONFIG, fsk.RegRssiConfig.octet);
fsk.RegRssiConfig.bits.RssiSmoothing = sidx;
return MENUMODE_REDRAW;
}
const dropdown_item_t Radio::rssiSmoothing_item = { _ITEM_DROPDOWN, rssiSmoothings, rssiSmoothings, rssiSmoothing_read, rssiSmoothing_write};
bool Radio::dataMode_read()
{
fsk.RegPktConfig2.word = radio.read_u16(REG_FSK_PACKETCONFIG2);
return fsk.RegPktConfig2.bits.DataModePacket;
}
bool Radio::dataMode_push()
{
fsk.RegPktConfig2.bits.DataModePacket ^= 1;
radio.write_u16(REG_FSK_PACKETCONFIG2, fsk.RegPktConfig2.word);
return fsk.RegPktConfig2.bits.DataModePacket;
}
const toggle_item_t Radio::dataMode_item = { _ITEM_TOGGLE,
"continuous",
"packet ",
dataMode_read, dataMode_push
};
bool Radio::bitSyncOn_read(void)
{
fsk.RegOokPeak.octet = radio.read_reg(REG_FSK_OOKPEAK);
return fsk.RegOokPeak.bits.BitSyncOn;
}
bool Radio::bitSyncOn_push(void)
{
fsk.RegOokPeak.bits.BitSyncOn ^= 1;
radio.write_reg(REG_FSK_OOKPEAK, fsk.RegOokPeak.octet);
return fsk.RegOokPeak.bits.BitSyncOn;
}
const toggle_item_t Radio::bitSyncOn_item = { _ITEM_TOGGLE,
"BitSyncOn", NULL,
bitSyncOn_read, bitSyncOn_push
};
const button_item_t Radio::pdLabel_item = { _ITEM_BUTTON, "PreambleDetector", NULL};
bool Radio::pdOn_read(void)
{
fsk.RegPreambleDetect.octet = radio.read_reg(REG_FSK_PREAMBLEDETECT);
return fsk.RegPreambleDetect.bits.PreambleDetectorOn;
}
bool Radio::pdOn_push(void)
{
fsk.RegPreambleDetect.bits.PreambleDetectorOn ^= 1;
radio.write_reg(REG_FSK_PREAMBLEDETECT, fsk.RegPreambleDetect.octet);
return fsk.RegPreambleDetect.bits.PreambleDetectorOn;
}
const toggle_item_t Radio::pdOn_item = { _ITEM_TOGGLE,
"On", NULL,
pdOn_read, pdOn_push
};
const char* const pdsizes[] = {
"1 byte ", // 0
"2 bytes", // 1
"3 bytes", // 2
NULL
};
unsigned Radio::pdSize_read(bool)
{
fsk.RegPreambleDetect.octet = radio.read_reg(REG_FSK_PREAMBLEDETECT);
return fsk.RegPreambleDetect.bits.PreambleDetectorSize;
}
menuMode_e Radio::pdSize_write(unsigned sidx)
{
fsk.RegPreambleDetect.bits.PreambleDetectorSize = sidx;
radio.write_reg(REG_FSK_PREAMBLEDETECT, fsk.RegPreambleDetect.octet);
return MENUMODE_REDRAW;
}
const dropdown_item_t Radio::pdSize_item = { _ITEM_DROPDOWN, pdsizes, pdsizes, pdSize_read, pdSize_write};
void Radio::pdTol_print(void)
{
fsk.RegPreambleDetect.octet = radio.read_reg(REG_FSK_PREAMBLEDETECT);
pc.printf("%u", fsk.RegPreambleDetect.bits.PreambleDetectorTol);
}
bool Radio::pdTol_write(const char* txt)
{
unsigned n;
sscanf(txt, "%u", &n);
fsk.RegPreambleDetect.bits.PreambleDetectorTol = n;
radio.write_reg(REG_FSK_PREAMBLEDETECT, fsk.RegPreambleDetect.octet);
return false;
}
const value_item_t Radio::pdTol_item = { _ITEM_VALUE, 3, pdTol_print, pdTol_write};
bool Radio::TxStartCondition_read()
{
fsk.RegFifoThreshold.octet = radio.read_reg(REG_FSK_FIFOTHRESH);
return fsk.RegFifoThreshold.bits.TxStartCondition;
}
bool Radio::TxStartCondition_push()
{
fsk.RegFifoThreshold.bits.TxStartCondition ^= 1;
radio.write_reg(REG_FSK_FIFOTHRESH, fsk.RegFifoThreshold.octet);
return fsk.RegFifoThreshold.bits.TxStartCondition;
}
const toggle_item_t Radio::TxStartCondition_item = { _ITEM_TOGGLE,
"FifoLevel ", // 0
"FifoNotEmpty", // 1
TxStartCondition_read, TxStartCondition_push
};
void Radio::FifoThreshold_print(void)
{
fsk.RegFifoThreshold.octet = radio.read_reg(REG_FSK_FIFOTHRESH);
pc.printf("%u", fsk.RegFifoThreshold.bits.FifoThreshold);
}
bool Radio::FifoThreshold_write(const char* txt)
{
unsigned n;
sscanf(txt, "%u", &n);
fsk.RegFifoThreshold.bits.FifoThreshold = n;
radio.write_reg(REG_FSK_FIFOTHRESH, fsk.RegFifoThreshold.octet);
return false;
}
const value_item_t Radio::FifoThreshold_item = { _ITEM_VALUE, 3, FifoThreshold_print, FifoThreshold_write};
const char* const dcFrees[] = {
"none ", // 0
"manchester", // 1
"whitening ", // 2
NULL
};
unsigned Radio::dcFree_read(bool fw)
{
fsk.RegPktConfig1.octet = radio.read_reg(REG_FSK_PACKETCONFIG1);
return fsk.RegPktConfig1.bits.DcFree;
}
menuMode_e Radio::dcFree_write(unsigned sidx)
{
fsk.RegPktConfig1.bits.DcFree = sidx;
radio.write_reg(REG_FSK_PACKETCONFIG1, fsk.RegPktConfig1.octet);
return MENUMODE_REDRAW;
}
const dropdown_item_t Radio::dcFree_item = { _ITEM_DROPDOWN, dcFrees, dcFrees, dcFree_read, dcFree_write};
bool Radio::fskook_crcon_read()
{
fsk.RegPktConfig1.octet = radio.read_reg(REG_FSK_PACKETCONFIG1);
return fsk.RegPktConfig1.bits.CrcOn;
}
bool Radio::fskook_crcon_push()
{
fsk.RegPktConfig1.bits.CrcOn ^= 1;
radio.write_reg(REG_FSK_PACKETCONFIG1, fsk.RegPktConfig1.octet);
if (radio.RegOpMode.bits.Mode == RF_OPMODE_RECEIVER)
fsk.config_dio0_for_pktmode_rx();
return fsk.RegPktConfig1.bits.CrcOn;
}
const toggle_item_t Radio::fskook_crcon_item = { _ITEM_TOGGLE,
"CrcOn", NULL,
fskook_crcon_read, fskook_crcon_push
};
void Radio::rssiThresh_print()
{
fsk.RegRssiThresh = radio.read_reg(REG_FSK_RSSITHRESH);
pc.printf("%.1f", fsk.RegRssiThresh / -2.0);
}
bool Radio::rssiThresh_write(const char* txt)
{
float dbm;
sscanf(txt, "%f", &dbm);
fsk.RegRssiThresh = dbm * -2.0;
radio.write_reg(REG_FSK_RSSITHRESH, fsk.RegRssiThresh);
return false;
}
const value_item_t Radio::rssiThresh_item = { _ITEM_VALUE, 3, rssiThresh_print, rssiThresh_write};
bool Radio::pblPol_read()
{
fsk.RegSyncConfig.octet = radio.read_reg(REG_FSK_SYNCCONFIG);
return fsk.RegSyncConfig.bits.PreamblePolarity;
}
bool Radio::pblPol_push()
{
fsk.RegSyncConfig.bits.PreamblePolarity ^= 1;
radio.write_reg(REG_FSK_SYNCCONFIG, fsk.RegSyncConfig.octet);
return fsk.RegSyncConfig.bits.PreamblePolarity;
}
const toggle_item_t Radio::pblPol_item = { _ITEM_TOGGLE,
"0xaa",
"0x55",
pblPol_read, pblPol_push
};
const menu_t Radio::fsk_menu[] = {
{ {FIRST_CHIP_MENU_ROW, 22}, "bps:", &fsk_ook_bitrate_item, FLAG_MSGTYPE_ALL },
{ {FIRST_CHIP_MENU_ROW, 34}, "fdev:", &gfsk_fdev_item, FLAG_MSGTYPE_ALL },
{ {FIRST_CHIP_MENU_ROW, 47}, "BT:", &gfsk_bt_item, FLAG_MSGTYPE_ALL },
{ {FIRST_CHIP_MENU_ROW, 57}, "length:", &fskook_pktfmt_item, FLAG_MSGTYPE_ALL },
{ {FIRST_CHIP_MENU_ROW+1, 1}, "rxbw:", &rxbw_item, FLAG_MSGTYPE_ALL },
{ {FIRST_CHIP_MENU_ROW+1, 14}, "afcbw:", &afcbw_item, FLAG_MSGTYPE_ALL },
{ {FIRST_CHIP_MENU_ROW+1, 27}, "preambleLen:", &pblLen_item, FLAG_MSGTYPE_ALL },
{ {FIRST_CHIP_MENU_ROW+1, 47}, "RxTrigger:", &rxTrigger_item, FLAG_MSGTYPE_ALL },
{ {FIRST_CHIP_MENU_ROW+1, 72}, NULL, &pblPol_item, FLAG_MSGTYPE_ALL },
{ {FIRST_CHIP_MENU_ROW+2, 1}, "syncWord:", &syncWord_item, FLAG_MSGTYPE_ALL, &syncSize_item},
{ {FIRST_CHIP_MENU_ROW+2, 27}, "syncSize:", &syncSize_item, FLAG_MSGTYPE_ALL },
{ {FIRST_CHIP_MENU_ROW+2, 39}, NULL, &syncOn_item, FLAG_MSGTYPE_ALL },
{ {FIRST_CHIP_MENU_ROW+2, 47}, "DataMode:", &dataMode_item, FLAG_MSGTYPE_ALL },
{ {FIRST_CHIP_MENU_ROW+2, 69}, NULL, &bitSyncOn_item, FLAG_MSGTYPE_ALL },
{ {FIRST_CHIP_MENU_ROW+3, 1}, NULL, &pdLabel_item, FLAG_MSGTYPE_ALL },
{ {FIRST_CHIP_MENU_ROW+3, 18}, NULL, &pdOn_item, FLAG_MSGTYPE_ALL },
{ {FIRST_CHIP_MENU_ROW+3, 23}, "size:", &pdSize_item , FLAG_MSGTYPE_ALL },
{ {FIRST_CHIP_MENU_ROW+3, 36}, "tol:", &pdTol_item , FLAG_MSGTYPE_ALL },
{ {FIRST_CHIP_MENU_ROW+3, 48}, "rssiThresh:", &rssiThresh_item , FLAG_MSGTYPE_ALL },
{ {FIRST_CHIP_MENU_ROW+4, 1}, NULL, &agcautoon_item, FLAG_MSGTYPE_ALL },
{ {FIRST_CHIP_MENU_ROW+4, 11}, NULL, &afcautoon_item, FLAG_MSGTYPE_ALL },
{ {FIRST_CHIP_MENU_ROW+4, 22}, NULL, &RestartRxOnCollision_item, FLAG_MSGTYPE_ALL },
{ {FIRST_CHIP_MENU_ROW+4, 43}, NULL, &RestartRxWithPllLock_item, FLAG_MSGTYPE_ALL },
{ {FIRST_CHIP_MENU_ROW+4, 64}, NULL, &RestartRxWithoutPllLock_item, FLAG_MSGTYPE_ALL },
{ {FIRST_CHIP_MENU_ROW+5, 1}, NULL, &AfcAutoClearOn_item, FLAG_MSGTYPE_ALL },
{ {FIRST_CHIP_MENU_ROW+5, 17}, NULL, &AgcStart_item, FLAG_MSGTYPE_ALL },
{ {FIRST_CHIP_MENU_ROW+5, 27}, NULL, &AfcClear_item, FLAG_MSGTYPE_ALL },
{ {FIRST_CHIP_MENU_ROW+5, 37}, "rssiOffset:", &rssiOffset_item, FLAG_MSGTYPE_ALL },
{ {FIRST_CHIP_MENU_ROW+5, 52}, "rssiSmoothing:", &rssiSmoothing_item, FLAG_MSGTYPE_ALL },
{ {FIRST_CHIP_MENU_ROW+6, 1}, "TxStartCondition:", &TxStartCondition_item, FLAG_MSGTYPE_ALL },
{ {FIRST_CHIP_MENU_ROW+6, 32}, "FifoThreshold:", &FifoThreshold_item, FLAG_MSGTYPE_ALL },
{ {FIRST_CHIP_MENU_ROW+6, 50}, "dcFree:", &dcFree_item, FLAG_MSGTYPE_ALL },
{ {FIRST_CHIP_MENU_ROW+6, 68}, NULL, &fskook_crcon_item, FLAG_MSGTYPE_ALL },
{ {0, 0}, NULL, NULL }
};
const button_item_t Radio::ookLabel_item = { _ITEM_BUTTON, "Ook", NULL};
const menu_t Radio::common_menu[] = {
{ {FIRST_CHIP_MENU_ROW, 1}, NULL, &paSelect_item, FLAG_MSGTYPE_ALL },
{ {FIRST_CHIP_MENU_ROW, 10}, "ocp mA:", &ocp_item, FLAG_MSGTYPE_ALL },
{ {0, 0}, NULL, NULL }
};
const char* const ook_peak_steps[] = {
"0.5", // 0
"1.0", // 1
"1.5", // 2
"2.0", // 3
"3.0", // 4
"4.0", // 5
"5.0", // 6
"6.0", // 7
NULL
};
unsigned Radio::ook_peak_step_read(bool fw)
{
fsk.RegOokPeak.octet = radio.read_reg(REG_FSK_OOKPEAK);
return fsk.RegOokPeak.bits.OokPeakThreshStep;
}
menuMode_e Radio::ook_peak_step_write(unsigned sidx)
{
fsk.RegOokPeak.bits.OokPeakThreshStep = sidx;
radio.write_reg(REG_FSK_OOKPEAK, fsk.RegOokPeak.octet);
return MENUMODE_REDRAW;
}
const dropdown_item_t Radio::ook_peak_step_item = { _ITEM_DROPDOWN, ook_peak_steps, ook_peak_steps, ook_peak_step_read, ook_peak_step_write};
const char* const ook_peak_decs[] = {
"once per chip ", // 0
"once every 2 chips ", // 1
"once every 4 chips ", // 2
"once every 8 chips ", // 3
"twice in each chip ", // 4
"4 times in each chip ", // 5
"8 times in each chip ", // 6
"16 times in each chip", // 7
NULL
};
unsigned Radio::ook_peak_dec_read(bool fw)
{
RegOokAvg_t RegOokAvg;
RegOokAvg.octet = radio.read_reg(REG_FSK_OOKAVG);
return RegOokAvg.bits.OokPeakThreshDec;
}
menuMode_e Radio::ook_peak_dec_write(unsigned sidx)
{
RegOokAvg_t RegOokAvg;
RegOokAvg.octet = radio.read_reg(REG_FSK_OOKAVG);
RegOokAvg.bits.OokPeakThreshDec = sidx;
radio.write_reg(REG_FSK_OOKAVG, RegOokAvg.octet);
return MENUMODE_REDRAW;
}
const dropdown_item_t Radio::ook_peak_dec_item = { _ITEM_DROPDOWN, ook_peak_decs, ook_peak_decs, ook_peak_dec_read, ook_peak_dec_write};
void Radio::ookFixedThresh_print()
{
pc.printf("%u", radio.read_reg(REG_FSK_OOKFIX));
}
bool Radio::ookFixedThresh_write(const char* txt)
{
unsigned n;
sscanf(txt, "%u", &n);
radio.write_reg(REG_FSK_OOKFIX, n);
return false;
}
const value_item_t Radio::ookFixedThresh_item = { _ITEM_VALUE, 3, ookFixedThresh_print, ookFixedThresh_write};
const char* const ook_avgOffsets[] = {
"0.0dB", // 0
"2.0dB", // 1
"4.0dB", // 2
"6.0dB", // 3
NULL
};
unsigned Radio::ook_avgOffset_read(bool fw)
{
RegOokAvg_t RegOokAvg;
RegOokAvg.octet = radio.read_reg(REG_FSK_OOKAVG);
return RegOokAvg.bits.OokAverageOffset;
}
menuMode_e Radio::ook_avgOffset_write(unsigned sidx)
{
RegOokAvg_t RegOokAvg;
RegOokAvg.octet = radio.read_reg(REG_FSK_OOKAVG);
RegOokAvg.bits.OokAverageOffset = sidx;
radio.write_reg(REG_FSK_OOKAVG, RegOokAvg.octet);
return MENUMODE_REDRAW;
}
const dropdown_item_t Radio::ook_avgOffset_item = { _ITEM_DROPDOWN, ook_avgOffsets, ook_avgOffsets, ook_avgOffset_read, ook_avgOffset_write};
const char* const ook_avgFilters[] = {
"chip rate / 32.π", // 0
"chip rate / 8.π ", // 1
"chip rate / 4.π ", // 2
"chip rate / 2.π ", // 3
NULL
};
unsigned Radio::ook_avgFilter_read(bool fw)
{
RegOokAvg_t RegOokAvg;
RegOokAvg.octet = radio.read_reg(REG_FSK_OOKAVG);
return RegOokAvg.bits.OokAverageThreshFilt;
}
menuMode_e Radio::ook_avgFilter_write(unsigned sidx)
{
RegOokAvg_t RegOokAvg;
RegOokAvg.octet = radio.read_reg(REG_FSK_OOKAVG);
RegOokAvg.bits.OokAverageThreshFilt = sidx;
radio.write_reg(REG_FSK_OOKAVG, RegOokAvg.octet);
return MENUMODE_REDRAW;
}
const dropdown_item_t Radio::ook_avgFilter_item = { _ITEM_DROPDOWN, ook_avgFilters, ook_avgFilters, ook_avgFilter_read, ook_avgFilter_write};
const char* const ookthreshs[] = {
"fixed ", // 0
"peak ", // 1
"average", // 2
NULL
};
unsigned Radio::ookthreshtype_read(bool)
{
fsk.RegOokPeak.octet = radio.read_reg(REG_FSK_OOKPEAK);
return fsk.RegOokPeak.bits.OokThreshType;
}
menuMode_e Radio::ookthreshtype_write(unsigned sidx)
{
fsk.RegOokPeak.bits.OokThreshType = sidx;
radio.write_reg(REG_FSK_OOKPEAK, fsk.RegOokPeak.octet);
return MENUMODE_REINIT_MENU;
}
const dropdown_item_t Radio::ookthreshtype_item = { _ITEM_DROPDOWN, ookthreshs, ookthreshs, ookthreshtype_read, ookthreshtype_write};
const menu_t Radio::ook_menu[] = {
{ {FIRST_CHIP_MENU_ROW, 22}, "bps:", &fsk_ook_bitrate_item, FLAG_MSGTYPE_ALL },
{ {FIRST_CHIP_MENU_ROW, 34}, "Fcutoff=", &ook_bt_item, FLAG_MSGTYPE_ALL },
{ {FIRST_CHIP_MENU_ROW, 56}, "length:", &fskook_pktfmt_item, FLAG_MSGTYPE_ALL },
{ {FIRST_CHIP_MENU_ROW+1, 1}, "rxbw:", &rxbw_item, FLAG_MSGTYPE_ALL },
{ {FIRST_CHIP_MENU_ROW+1, 12}, "afcbw:", &afcbw_item, FLAG_MSGTYPE_ALL },
{ {FIRST_CHIP_MENU_ROW+1, 25}, "preambleLen:", &pblLen_item, FLAG_MSGTYPE_ALL },
{ {FIRST_CHIP_MENU_ROW+1, 47}, "RxTrigger:", &rxTrigger_item, FLAG_MSGTYPE_ALL },
{ {FIRST_CHIP_MENU_ROW+2, 1}, "syncWord:", &syncWord_item, FLAG_MSGTYPE_ALL, &syncSize_item},
{ {FIRST_CHIP_MENU_ROW+2, 27}, "syncSize:", &syncSize_item, FLAG_MSGTYPE_ALL },
{ {FIRST_CHIP_MENU_ROW+2, 39}, NULL, &syncOn_item, FLAG_MSGTYPE_ALL },
{ {FIRST_CHIP_MENU_ROW+2, 47}, "DataMode:", &dataMode_item, FLAG_MSGTYPE_ALL },
{ {FIRST_CHIP_MENU_ROW+2, 69}, NULL, &bitSyncOn_item, FLAG_MSGTYPE_ALL },
{ {FIRST_CHIP_MENU_ROW+3, 1}, NULL, &pdLabel_item, FLAG_MSGTYPE_ALL },
{ {FIRST_CHIP_MENU_ROW+3, 18}, NULL, &pdOn_item, FLAG_MSGTYPE_ALL },
{ {FIRST_CHIP_MENU_ROW+3, 23}, "size:", &pdSize_item , FLAG_MSGTYPE_ALL },
{ {FIRST_CHIP_MENU_ROW+3, 36}, "tol:", &pdTol_item , FLAG_MSGTYPE_ALL },
{ {FIRST_CHIP_MENU_ROW+3, 48}, "rssiThresh:", &rssiThresh_item , FLAG_MSGTYPE_ALL },
{ {FIRST_CHIP_MENU_ROW+4, 1}, "TxStartCondition:", &TxStartCondition_item, FLAG_MSGTYPE_ALL },
{ {FIRST_CHIP_MENU_ROW+4, 32}, "FifoThreshold:", &FifoThreshold_item, FLAG_MSGTYPE_ALL },
{ {FIRST_CHIP_MENU_ROW+4, 50}, "dcFree:", &dcFree_item, FLAG_MSGTYPE_ALL },
{ {FIRST_CHIP_MENU_ROW+4, 68}, NULL, &fskook_crcon_item, FLAG_MSGTYPE_ALL },
{ {FIRST_CHIP_MENU_ROW+5, 1}, NULL, &ookLabel_item, FLAG_MSGTYPE_ALL },
{ {FIRST_CHIP_MENU_ROW+5, 5}, "threshType:", &ookthreshtype_item, FLAG_MSGTYPE_ALL },
{ {0, 0}, NULL, NULL }
};
const menu_t Radio::ook_fixed_menu[] = {
{ {FIRST_CHIP_MENU_ROW+5, 25}, "threshold:", &ookFixedThresh_item, FLAG_MSGTYPE_ALL },
{ {0, 0}, NULL, NULL }
};
const menu_t Radio::ook_peak_menu[] = {
{ {FIRST_CHIP_MENU_ROW+5, 25}, "step:", &ook_peak_step_item, FLAG_MSGTYPE_ALL },
{ {FIRST_CHIP_MENU_ROW+5, 40}, "dec:", &ook_peak_dec_item, FLAG_MSGTYPE_ALL },
{ {0, 0}, NULL, NULL }
};
const menu_t Radio::ook_average_menu[] = {
{ {FIRST_CHIP_MENU_ROW+5, 25}, "offset:", &ook_avgOffset_item, FLAG_MSGTYPE_ALL },
{ {FIRST_CHIP_MENU_ROW+5, 45}, "filter:", &ook_avgFilter_item, FLAG_MSGTYPE_ALL },
{ {0, 0}, NULL, NULL }
};
void Radio::boardInit(const RadioEvents_t* e)
{
targetInit();
RadioEvents = e;
RegPaRamp.octet = radio.read_reg(REG_PARAMP);
if (radio.type == SX1276) {
lora_bw_item.printed_strs = lora_bws_1276;
lora_bw_item.selectable_strs = lora_bws_1276;
} else if (radio.type == SX1272) {
lora_bw_item.printed_strs = lora_bws_1272;
lora_bw_item.selectable_strs = lora_bws_1272;
}
lpt.start();
}
unsigned Radio::read_register(unsigned addr)
{
return radio.read_reg(addr);
}
void Radio::write_register(unsigned addr, unsigned val)
{
radio.write_reg(addr, val);
}
void Radio::test() { }
#endif /* ..SX127x_H */