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 */