wayne roberts / Mbed OS utility_sx12xx
Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers radio_sx126x.cpp Source File

radio_sx126x.cpp

00001 #include "radio.h"
00002 #ifdef SX126x_H 
00003 
00004 #define CHIP_TYPE_SX1262        0
00005 #define CHIP_TYPE_SX1261        1
00006 
00007 #if defined(TARGET_FF_ARDUINO) || defined(TARGET_FF_ARDUINO_UNO) 
00008 #ifdef TARGET_DISCO_L072CZ_LRWAN1
00009     /* Type1SJ */
00010     SPI spi(PB_15, PB_14, PB_13); // mosi, miso, sclk
00011                    //spi, nss, busy, dio1
00012     SX126x Radio::radio(spi, PB_12, PC_2, PB_0);
00013 
00014     DigitalOut antswPower(PA_15);
00015     const uint8_t chipType = CHIP_TYPE_SX1262;
00016     #define PINNAME_NRST            PB_1
00017     void Radio::chipModeChange() { }
00018 #else
00019     SPI spi(D11, D12, D13); // mosi, miso, sclk
00020                    //spi, nss, busy, dio1
00021     SX126x Radio::radio(spi, D7, D3, D5);
00022 
00023     DigitalOut antswPower(D8);
00024     AnalogIn xtalSel(A3);
00025 
00026     DigitalIn chipType(A2);
00027 
00028     #define PINNAME_NRST            A0
00029 
00030     #define LED_ON      1
00031     #define LED_OFF     0
00032     DigitalOut tx_led(A4);
00033     DigitalOut rx_led(A5);
00034 
00035     void Radio::chipModeChange()
00036     {
00037         if (radio.chipMode == CHIPMODE_NONE) {
00038             tx_led = LED_OFF;
00039             rx_led = LED_OFF;
00040         } else if (radio.chipMode == CHIPMODE_TX) {
00041             tx_led = LED_ON;
00042             rx_led = LED_OFF;
00043         } else if (radio.chipMode == CHIPMODE_RX) {
00044             tx_led = LED_OFF;
00045             rx_led = LED_ON;
00046         }
00047     }
00048 #endif /* !TARGET_DISCO_L072CZ_LRWAN1 */
00049 #endif /* TARGET_FF_ARDUINO */
00050 
00051 const char* const Radio::chipNum_str = "SX126x";
00052 
00053 ModulationParams_t Radio::mpFSK, Radio::mpLORA;
00054 PacketParams_t Radio::ppFSK, Radio::ppLORA;
00055 
00056 const RadioEvents_t* Radio::RadioEvents;
00057 LowPowerTimer Radio::lpt;
00058 uint8_t Radio::pktType;
00059 uint8_t Radio::bw_idx;
00060 uint8_t Radio::cadParams[7];
00061 uint16_t Radio::ppg;
00062 unsigned Radio::tcxoDelayTicks;
00063 
00064 const char* opModes[] = {
00065     "SLEEP    ", // 0
00066     "STBY_RC  ", // 1
00067     "STBY_XOSC", // 2
00068     "FS       ", // 3
00069     "RX       ", // 4
00070     "TX       "  // 5
00071 };
00072 
00073 void Radio::readChip()
00074 {
00075     bwSel_t bwSel;
00076     shapeCfg_t shapeCfg;
00077     unsigned d = radio.readReg(REG_ADDR_BITRATE, 3);
00078     printf("%06x:%u->", d ,d);
00079     printf("bitrate %ubps\r\n", (32 * XTAL_FREQ_HZ) / d);
00080     mpFSK.gfsk.bitrateHi = d >> 16;
00081     mpFSK.gfsk.bitrateMid = d >> 8;
00082     mpFSK.gfsk.bitrateLo = d;
00083 
00084     d = radio.readReg(REG_ADDR_FREQDEV, 3);
00085     printf("fdev %fKHz\r\n", d / KHZ_TO_FRF);
00086     mpFSK.gfsk.fdevHi = d >> 16;
00087     mpFSK.gfsk.fdevMid = d >> 8;
00088     mpFSK.gfsk.fdevLo = d;
00089 
00090     shapeCfg.octet = radio.readReg(REG_ADDR_SHAPECFG, 1);
00091     mpFSK.gfsk.PulseShape = shapeCfg.octet;
00092 
00093     bwSel.octet = radio.readReg(REG_ADDR_BWSEL, 1);
00094     // GFSK_RX_BW_*
00095     printf("bwsSel:%02x\r\n", bwSel.octet);
00096     mpFSK.gfsk.bandwidth = bwSel.octet;
00097 
00098     {
00099         unsigned n = radio.readReg(REG_ADDR_FSK_PREAMBLE_TXLEN , 2);
00100         ppFSK.gfsk.PreambleLengthHi = n << 8; // param1
00101         ppFSK.gfsk.PreambleLengthLo = n;// param2
00102     }
00103 
00104     {
00105         pktCtrl1_t pktCtrl1;
00106         pktCtrl1.octet = radio.readReg(REG_ADDR_FSK_PKTCTRL1, 1);
00107         ppFSK.gfsk.PreambleDetectorLength = pktCtrl1.octet & 0x07;    // param3
00108     }
00109 
00110 
00111     ppFSK.gfsk.SyncWordLength = radio.readReg(REG_ADDR_FSK_SYNC_LEN, 1);// param4
00112     ppFSK.gfsk.AddrComp = radio.readReg(REG_ADDR_NODEADDRCOMP, 1);// param5
00113 
00114     {
00115         pktCtrl0_t pktCtrl0;
00116         pktCtrl0.octet = radio.readReg(REG_ADDR_FSK_PKTCTRL0, 1);
00117         ppFSK.gfsk.PacketType = pktCtrl0.bits.pkt_len_format;   // param6
00118     }
00119 
00120     ppFSK.gfsk.PayloadLength = radio.readReg(REG_ADDR_FSK_PAYLOAD_LEN, 1);// param7
00121 
00122     {
00123         pktCtrl2_t pktCtrl2;
00124         pktCtrl2.octet = radio.readReg(REG_ADDR_FSK_PKTCTRL2, 1);
00125         ppFSK.gfsk.CRCType = pktCtrl2.octet & 0x7; // param8
00126         ppFSK.gfsk.Whitening = pktCtrl2.bits.whit_enable;   // param9
00127     }
00128 
00129     /*******************************/
00130 
00131     {
00132         loraConfig0_t conf0;
00133         conf0.octet = radio.readReg(REG_ADDR_LORA_CONFIG0, 1);
00134         printf("LoRa bw%u sf%u ", conf0.bits.modem_bw, conf0.bits.modem_sf);
00135         mpLORA.lora.spreadingFactor = conf0.bits.modem_sf;
00136         mpLORA.lora.bandwidth = conf0.bits.modem_bw;
00137     }
00138 
00139     {
00140         loraConfig1_t conf1;
00141         conf1.octet = radio.readReg(REG_ADDR_LORA_CONFIG1, 1);
00142         mpLORA.lora.LowDatarateOptimize = conf1.bits.ppm_offset;
00143         ppLORA.lora.HeaderType = conf1.bits.implicit_header;
00144         ppLORA.lora.InvertIQ = conf1.bits.rx_invert_iq;
00145         mpLORA.lora.codingRate = conf1.bits.tx_coding_rate;
00146     }
00147 
00148     {
00149         loraConfig2_t conf2;
00150         conf2.octet = radio.readReg(REG_ADDR_LORA_CONFIG2, 1);
00151         ppLORA.lora.CRCType = conf2.bits.tx_payload_crc16_en;
00152     }
00153 
00154     {
00155         uint32_t val = radio.readReg(REG_ADDR_LORA_PREAMBLE_SYMBNB, 2);
00156         ppLORA.lora.PreambleLengthHi = val >> 8;
00157         ppLORA.lora.PreambleLengthLo = val;
00158     }
00159 
00160     {
00161         AnaCtrl6_t AnaCtrl6;
00162         AnaCtrl7_t AnaCtrl7;
00163         PaCtrl1b_t PaCtrl1b;
00164 
00165         AnaCtrl6.octet = radio.readReg(REG_ADDR_ANACTRL6, 1);
00166         pa_config_buf[0] = AnaCtrl6.bits.pa_dctrim_select_ana;  // paDutyCycle
00167 
00168         AnaCtrl7.octet = radio.readReg(REG_ADDR_ANACTRL7, 1);
00169         pa_config_buf[1] = AnaCtrl7.bits.pa_hp_sel_ana; // hpMax
00170 
00171         PaCtrl1b.octet = radio.readReg(REG_ADDR_PA_CTRL1B, 1);
00172         pa_config_buf[2] = PaCtrl1b.bits.tx_mode_bat;   // deviceSel
00173 
00174         pa_config_buf[3] = 1;   // paLut
00175     }
00176 
00177     {
00178         cadParams[0] = radio.readReg(REG_ADDR_LORA_CONFIG9, 1);
00179         cadParams[0] >>= 5;
00180 
00181         cadParams[1] = radio.readReg(REG_ADDR_LORA_CAD_PN_RATIO, 1);
00182         cadParams[2] = radio.readReg(REG_ADDR_LORA_CAD_MINPEAK, 1);
00183     }
00184 
00185     pa_config_buf[2] = chipType;    /* auto-detect device from pin pull */
00186     radio.xfer(OPCODE_SET_PA_CONFIG, 4, 0, pa_config_buf);
00187 }
00188 
00189 void Radio::hw_reset()
00190 {
00191     radio.hw_reset(PINNAME_NRST);
00192 }
00193 
00194 void Radio::clearIrqFlags()
00195 {
00196     uint8_t buf[2];
00197     buf[0] = 0x03;
00198     buf[1] = 0xff;
00199     radio.xfer(OPCODE_CLEAR_IRQ_STATUS, 2, 0, buf);
00200 }
00201 
00202 uint8_t Radio::get_payload_length()
00203 {
00204     pktType = radio.getPacketType();
00205 
00206     if (pktType == PACKET_TYPE_GFSK) {
00207         ppFSK.gfsk.PayloadLength = radio.readReg(REG_ADDR_FSK_PAYLOAD_LEN, 1);
00208         return ppFSK.gfsk.PayloadLength;
00209     } else if (pktType == PACKET_TYPE_LORA) {
00210         ppLORA.lora.PayloadLength = radio.readReg(REG_ADDR_LORA_TXPKTLEN, 1);
00211         return ppLORA.lora.PayloadLength;
00212     } else
00213         return 0;
00214 }
00215 
00216 const char* const Radio::opmode_status_strs[] = {
00217     "<0>      ", // 0
00218     "RFU      ", // 1
00219     "STBY_RC  ", // 2
00220     "STBY_XOSC", // 3
00221     "FS       ", // 4
00222     "RX       ", // 5
00223     "TX       ", // 6
00224     "<7>      ", // 7
00225     NULL
00226 };
00227 
00228 const char* const Radio::opmode_select_strs[] = {
00229     "SLEEP     ", // 0
00230     "STDBY_RC  ", // 1
00231     "STDBY_XOSC", // 2
00232     "FS        ", // 3
00233     "RX        ", // 4
00234     "TX        ", // 5
00235     NULL
00236 };
00237 
00238 unsigned Radio::opmode_read(bool forWriting)
00239 {
00240     status_t status;
00241     radio.xfer(OPCODE_GET_STATUS, 0, 1, &status.octet);
00242 
00243     if (forWriting) {
00244         /* translate opmode_status_strs to opmode_select_strs */
00245         switch (status.bits.chipMode) {
00246             case 2: return 1; // STBY_RC
00247             case 3: return 2; // STBY_XOSC
00248             case 4: return 3; // FS
00249             case 5: return 4; // RX
00250             case 6: return 5; // TX
00251             default: return 0;
00252         }
00253     } else
00254         return status.bits.chipMode;
00255 }
00256 
00257 menuMode_e Radio::opmode_write(unsigned sel)
00258 {
00259     switch (sel) {
00260         case 0:
00261             antswPower = 0;
00262             radio.setSleep(true, false);
00263             break;
00264         case 1:
00265             antswPower = 0;
00266             radio.setStandby(STBY_RC);
00267             break;
00268         case 2:
00269             antswPower = 0;
00270             radio.setStandby(STBY_XOSC);
00271             break;
00272         case 3:
00273             antswPower = 0;
00274             radio.setFS();
00275             break;
00276         case 4:
00277             antswPower = 1;
00278             radio.start_rx(0);
00279             break;
00280         case 5:
00281             antswPower = 1;
00282             {
00283                 uint8_t buf[3];
00284                 buf[0] = 0;
00285                 buf[0] = 0;
00286                 buf[1] = 0;
00287                 radio.xfer(OPCODE_SET_TX, 3, 0, buf);
00288             }
00289             break;
00290     }
00291 
00292     return MENUMODE_REDRAW;
00293 }
00294 
00295 void Radio::setFS()
00296 {
00297     radio.setFS();
00298 }
00299 
00300 const char* const Radio::pktType_strs[] = {
00301     "GFSK   ",
00302     "LORA   ",
00303     NULL
00304 };
00305 
00306 unsigned Radio::pktType_read(bool fw)
00307 {
00308     return radio.getPacketType();
00309 }
00310 
00311 menuMode_e Radio::pktType_write(unsigned idx)
00312 {
00313     radio.setPacketType(idx);
00314     return MENUMODE_REINIT_MENU;
00315 }
00316 
00317 void Radio::tx_carrier()
00318 {
00319     radio.SetDIO2AsRfSwitchCtrl(1);
00320     antswPower = 1;
00321     radio.xfer(OPCODE_SET_TX_CARRIER, 0, 0, NULL);
00322 }
00323 
00324 void Radio::tx_preamble()
00325 {
00326     radio.SetDIO2AsRfSwitchCtrl(1);
00327     antswPower = 1;
00328     radio.xfer(OPCODE_SET_TX_PREAMBLE, 0, 0, NULL);
00329 }
00330 
00331 void Radio::get_rssi()
00332 {
00333     uint8_t buf[3];
00334     radio.xfer(OPCODE_GET_RSSIINST, 0, 3, buf);
00335     log_printf("-%0.1f dBm\r\n", buf[1]/2.0);
00336 }
00337 
00338 void Radio::txPkt()
00339 {
00340     uint8_t txlen = get_payload_length();
00341 
00342     radio.SetDIO2AsRfSwitchCtrl(1);
00343     antswPower = 1;
00344     radio.setBufferBase(0, 0);
00345 
00346     {
00347         uint8_t buf[8];
00348         IrqFlags_t irqEnable;
00349         irqEnable.word = 0;
00350         irqEnable.bits.TxDone = 1;
00351         irqEnable.bits.Timeout = 1;
00352 
00353         buf[0] = irqEnable.word >> 8;    // enable bits
00354         buf[1] = irqEnable.word; // enable bits
00355         buf[2] = irqEnable.word >> 8;     // dio1
00356         buf[3] = irqEnable.word;  // dio1
00357         buf[4] = 0; // dio2
00358         buf[5] = 0; // dio2
00359         buf[6] = 0; // dio3
00360         buf[7] = 0; // dio3
00361         radio.xfer(OPCODE_SET_DIO_IRQ_PARAMS, 8, 0, buf);
00362     }
00363 
00364     radio.start_tx(txlen);
00365 }
00366 
00367 uint8_t Radio::tx_param_buf[2];
00368 uint8_t Radio::pa_config_buf[4];
00369 
00370 void Radio::tx_dbm_print()
00371 {
00372     PwrCtrl_t PwrCtrl;
00373     PaCtrl1b_t PaCtrl1b;
00374     unsigned v = radio.readReg(REG_ADDR_ANACTRL16, 1);
00375 
00376     if (v & 0x10) {
00377         printf("%d", PA_OFF_DBM);
00378         return;
00379     }
00380 
00381     PwrCtrl.octet = radio.readReg(REG_ADDR_PWR_CTRL, 1);
00382 
00383     PaCtrl1b.octet = radio.readReg(REG_ADDR_PA_CTRL1B, 1);
00384     pa_config_buf[2] = PaCtrl1b.bits.tx_mode_bat;   // deviceSel
00385 
00386     if (PaCtrl1b.bits.tx_mode_bat)
00387         printf("%d", PwrCtrl.bits.tx_pwr - 17);
00388     else
00389         printf("%d", PwrCtrl.bits.tx_pwr - 9);
00390 }
00391 
00392 bool Radio::tx_dbm_write(const char* str)
00393 {
00394     int dbm;
00395     unsigned v = radio.readReg(REG_ADDR_ANACTRL16, 1);
00396 
00397     sscanf(str, "%d", &dbm);
00398 
00399     if (dbm == PA_OFF_DBM) {
00400         /* bench test: prevent overloading receiving station (very low tx power) */
00401         v |= 0x10;  // pa dac atb tst
00402         radio.writeReg(REG_ADDR_ANACTRL16, v, 1);
00403     } else {
00404         tx_param_buf[0] = dbm;
00405         radio.xfer(OPCODE_SET_TX_PARAMS, 2, 0, tx_param_buf);
00406 
00407         if (v & 0x10) {
00408             v &= ~0x10;
00409             radio.writeReg(REG_ADDR_ANACTRL16, v, 1);
00410         }
00411     }
00412 
00413     return false;
00414 }
00415 
00416 const char* Radio::tx_ramp_strs[] = {
00417     "10  ", // 0
00418     "20  ", // 1
00419     "40  ", // 2
00420     "80  ", // 3
00421     "200 ", // 4
00422     "800 ", // 5
00423     "1700", // 6
00424     "3400", // 7
00425     NULL
00426 };
00427 
00428 unsigned Radio::tx_ramp_read(bool fw)
00429 {
00430     PwrCtrl_t PwrCtrl;
00431     PwrCtrl.octet = radio.readReg(REG_ADDR_PWR_CTRL, 1);
00432     tx_param_buf[1] = PwrCtrl.octet >> 5;
00433     return PwrCtrl.bits.ramp_time;
00434 }
00435 
00436 menuMode_e Radio::tx_ramp_write(unsigned sidx)
00437 {
00438     tx_param_buf[1] = sidx;
00439     radio.xfer(OPCODE_SET_TX_PARAMS, 2, 0, tx_param_buf);
00440     return MENUMODE_REDRAW;
00441 }
00442 
00443 void Radio::set_payload_length(uint8_t len)
00444 {
00445     pktType = radio.getPacketType();
00446 
00447     if (pktType == PACKET_TYPE_GFSK) {
00448         ppFSK.gfsk.PayloadLength = len;
00449         radio.xfer(OPCODE_SET_PACKET_PARAMS, 9, 0, ppFSK.buf);
00450     } else if (pktType == PACKET_TYPE_LORA) {
00451         ppLORA.lora.PayloadLength = len;
00452         radio.xfer(OPCODE_SET_PACKET_PARAMS, 6, 0, ppLORA.buf);
00453     }
00454 }
00455 
00456 void Radio::tx_payload_length_print()
00457 {
00458     printf("%u", get_payload_length());
00459 }
00460 
00461 bool Radio::tx_payload_length_write(const char* txt)
00462 {
00463     unsigned len;
00464 
00465     sscanf(txt, "%u", &len);
00466 
00467     set_payload_length(len);
00468 
00469     return false;
00470 }
00471 
00472 bool Radio::service(int8_t statusRow)
00473 {
00474     static uint8_t prevRxStatus;
00475     static uint8_t prevPktCtrl0;
00476     uint8_t buf[4];
00477     static IrqFlags_t prevIrqFlags;
00478     IrqFlags_t irqFlags;
00479     bool ret = false;
00480     //static us_timestamp_t prev_now;
00481     //static uint64_t prev_now;
00482     static Kernel::Clock::time_point prev_now;
00483     //us_timestamp_t now = lpt.read_us();
00484     //uint64_t now = Kernel::get_ms_count();
00485     Kernel::Clock::time_point now = Kernel::Clock::now();
00486     
00487 
00488     radio.service();
00489 
00490     if (statusRow > 0 && now-prev_now > 50ms) {
00491         uint8_t rxStatus, pktCtrl0;
00492         bool chg = false;
00493         radio.xfer(OPCODE_GET_IRQ_STATUS, 0, 3, buf);
00494         irqFlags.word = buf[1] << 8;
00495         irqFlags.word |= buf[2];
00496 
00497         rxStatus = radio.readReg(0x6c9, 1);
00498         if (rxStatus != prevRxStatus) {
00499             chg = true;
00500             prevRxStatus = rxStatus;
00501         }
00502 
00503         pktCtrl0 = radio.readReg(0x6b3, 1);
00504         if (pktCtrl0 != prevPktCtrl0) {
00505             chg = true;
00506             prevPktCtrl0 = pktCtrl0;
00507         }
00508 
00509         if (irqFlags.word != prevIrqFlags.word && chg) {
00510             printf("\e[%u;1f", statusRow);  // set (force) cursor to row;column
00511 
00512             printf("%02x ", rxStatus);
00513             printf("%02x ", pktCtrl0);
00514 
00515             if (irqFlags.bits.TxDone)
00516                 printf("TxDone ");
00517             if (irqFlags.bits.RxDone)
00518                 printf("RxDone ");
00519             if (irqFlags.bits.PreambleDetected)
00520                 printf("PreambleDetected ");
00521             if (irqFlags.bits.SyncWordValid)
00522                 printf("SyncWordValid ");
00523             if (irqFlags.bits.HeaderValid)
00524                 printf("HeaderValid ");
00525             if (irqFlags.bits.HeaderErr)
00526                 printf("HeaderErr ");
00527             if (irqFlags.bits.CrCerr)
00528                 printf("CrCerr ");
00529             if (irqFlags.bits.CadDone)
00530                 printf("CadDone ");
00531             if (irqFlags.bits.CadDetected)
00532                 printf("CadDetected ");
00533             if (irqFlags.bits.Timeout)
00534                 printf("Timeout ");
00535 
00536             printf("\e[K");
00537             ret = true;
00538 
00539             prevIrqFlags.word = irqFlags.word;
00540         }
00541 
00542         prev_now = now;
00543     }
00544 
00545     return ret;
00546 }
00547 
00548 void Radio::Rx()
00549 {
00550     antswPower = 1;
00551 
00552     {
00553         uint8_t buf[8];
00554         IrqFlags_t irqEnable;
00555         irqEnable.word = 0;
00556         irqEnable.bits.RxDone = 1;
00557         irqEnable.bits.Timeout = 1;
00558 
00559         buf[0] = 3;//irqEnable.word >> 8;    // enable bits
00560         buf[1] = 0xff;//irqEnable.word; // enable bits
00561         buf[2] = irqEnable.word >> 8;     // dio1
00562         buf[3] = irqEnable.word;  // dio1
00563         buf[4] = 0; // dio2
00564         buf[5] = 0; // dio2
00565         buf[6] = 0; // dio3
00566         buf[7] = 0; // dio3
00567         radio.xfer(OPCODE_SET_DIO_IRQ_PARAMS, 8, 0, buf);
00568     }
00569 
00570     radio.start_rx(RX_TIMEOUT_CONTINUOUS);
00571 }
00572 
00573 void Radio::rxDone(uint8_t size, float rssi, float snr)
00574 {
00575     if (pktType == PACKET_TYPE_GFSK) {
00576         int16_t cfo = radio.readReg(REG_ADDR_FSK_DEMOD_CFO, 2);
00577         // justify 12bit to 16bit signed
00578         if (cfo & 0x0800)
00579             cfo |= 0xf000;
00580         log_printf("cfo:%d\r\n", cfo);
00581     } else if (pktType == PACKET_TYPE_LORA) {
00582         const float bwkhzs[] = {
00583             7.81, 10.42, 15.63, 20.83, 31.25, 41.67, 62.5, 125, 250, 500
00584         };
00585         int hz;
00586         int32_t fei;
00587         loraStatus1_t loraStatus1;
00588         loraStatus1.dword = radio.readReg(REG_ADDR_LORA_STATUS, 3);
00589         if (loraStatus1.bits.est_freq_error & 0x80000)
00590             fei = 0xfff00000 | loraStatus1.bits.est_freq_error;
00591         else
00592             fei = loraStatus1.bits.est_freq_error;
00593 
00594         //hz = fei * HZ_TO_FRF * bwkhzs[bw_idx]/500;
00595         hz = fei * -HZ_TO_FRF * bwkhzs[bw_idx]/1000;
00596         log_printf("hz:%d\r\n", hz);
00597     }
00598 
00599     RadioEvents->RxDone(size, rssi, snr);
00600 }
00601 
00602 void Radio::txDoneBottom()
00603 {
00604     if (RadioEvents->TxDone_botHalf)
00605         RadioEvents->TxDone_botHalf();
00606         
00607     antswPower = 0;
00608 }
00609 
00610 /*void Radio::cadDone(bool det)
00611 {
00612     log_printf("cadDone ");
00613     if (det)
00614         printf("CadDetected");
00615 
00616     printf("\r\n");
00617 }*/
00618 
00619 uint8_t ana_regs[128];
00620 
00621 void Radio::boardInit(const RadioEvents_t* e)
00622 {
00623     hw_reset();
00624 
00625     radio.txDone = txDoneBottom;
00626     radio.rxDone = rxDone;
00627     radio.cadDone = cadDone;
00628 
00629     radio.chipModeChange = chipModeChange;
00630 
00631     readChip();
00632 
00633     RadioEvents = e;
00634 
00635     lpt.start();
00636     radio.SetDIO2AsRfSwitchCtrl(1);
00637 
00638     tcxoDelayTicks = 3200;   // some default timeout for tcxo
00639 }
00640 
00641 bool Radio::deviceSel_read()
00642 {
00643     PaCtrl1b_t PaCtrl1b;
00644     PaCtrl1b.octet = radio.readReg(REG_ADDR_PA_CTRL1B, 1);
00645     pa_config_buf[2] = PaCtrl1b.bits.tx_mode_bat;   // deviceSel
00646     return PaCtrl1b.bits.tx_mode_bat;
00647 }
00648 
00649 bool Radio::deviceSel_push()
00650 {
00651 /*    if (pa_config_buf[2])
00652         pa_config_buf[2] = 0;
00653     else
00654         pa_config_buf[2] = 1;*/
00655     pa_config_buf[2] ^= 1;
00656 
00657     radio.xfer(OPCODE_SET_PA_CONFIG, 4, 0, pa_config_buf);
00658 
00659     return pa_config_buf[2];
00660 }
00661 
00662 const toggle_item_t Radio::deviceSel_item = { _ITEM_TOGGLE, "SX1262", "SX1261", deviceSel_read, deviceSel_push};
00663 
00664 static const char* const paDutyCycles[] = {
00665     "0",
00666     "1",
00667     "2",
00668     "3",
00669     "4",
00670     "5",
00671     "6",
00672     "7",
00673     NULL
00674 };
00675 
00676 unsigned Radio::paDutyCycle_read(bool forWriting)
00677 {
00678     AnaCtrl6_t AnaCtrl6;
00679     AnaCtrl6.octet = radio.readReg(REG_ADDR_ANACTRL6, 1);
00680     pa_config_buf[0] = AnaCtrl6.bits.pa_dctrim_select_ana;
00681     return AnaCtrl6.bits.pa_dctrim_select_ana;
00682 }
00683 
00684 menuMode_e Radio::paDutyCycle_write(unsigned sidx)
00685 {
00686     pa_config_buf[0] = sidx;
00687     radio.xfer(OPCODE_SET_PA_CONFIG, 4, 0, pa_config_buf);
00688     return MENUMODE_REDRAW;
00689 }
00690 
00691 const dropdown_item_t Radio::paDutyCycle_item = { _ITEM_DROPDOWN, paDutyCycles, paDutyCycles, paDutyCycle_read, paDutyCycle_write};
00692 
00693 static const char* const hpMaxs[] = {
00694     "0",
00695     "1",
00696     "2",
00697     "3",
00698     "4",
00699     "5",
00700     "6",
00701     "7",
00702     NULL
00703 };
00704 
00705 unsigned Radio::hpMax_read(bool forWriting)
00706 {
00707     AnaCtrl7_t AnaCtrl7;
00708     AnaCtrl7.octet = radio.readReg(REG_ADDR_ANACTRL7, 1);
00709     pa_config_buf[1] = AnaCtrl7.bits.pa_hp_sel_ana;
00710     return AnaCtrl7.bits.pa_hp_sel_ana;
00711 }
00712 
00713 menuMode_e Radio::hpMax_write(unsigned sidx)
00714 {
00715     pa_config_buf[1] = sidx;
00716     radio.xfer(OPCODE_SET_PA_CONFIG, 4, 0, pa_config_buf);
00717     return MENUMODE_REDRAW;
00718 }
00719 
00720 const dropdown_item_t Radio::hpMax_item = { _ITEM_DROPDOWN, hpMaxs, hpMaxs, hpMax_read, hpMax_write};
00721 
00722 void Radio::ocp_print()
00723 {
00724     uint8_t ocp = radio.readReg(REG_ADDR_OCP, 1);
00725     printf("%.1f", ocp * 2.5);
00726 
00727 }
00728 
00729 bool Radio::ocp_write(const char* txt)
00730 {
00731     float mA;
00732     if (sscanf(txt, "%f", &mA) == 1)
00733         radio.writeReg(REG_ADDR_OCP, mA / 2.5, 1);
00734 
00735     return false;
00736 }
00737 
00738 const value_item_t Radio::ocp_item = { _ITEM_VALUE, 5, ocp_print, ocp_write};
00739 
00740 void Radio::xta_print()
00741 {
00742     uint8_t trim = radio.readReg(REG_ADDR_XTA_TRIM, 1);
00743     printf("%02x", trim);
00744 }
00745 
00746 bool Radio::xta_write(const char* txt)
00747 {
00748     unsigned trim;
00749     if (sscanf(txt, "%x", &trim) == 1)
00750         radio.writeReg(REG_ADDR_XTA_TRIM, trim, 1);
00751 
00752     return false;
00753 }
00754 
00755 const value_item_t Radio::xta_item = { _ITEM_VALUE, 3, xta_print, xta_write};
00756 
00757 void Radio::xtb_print()
00758 {
00759     uint8_t trim = radio.readReg(REG_ADDR_XTB_TRIM, 1);
00760     printf("%02x", trim);
00761 }
00762 
00763 bool Radio::xtb_write(const char* txt)
00764 {
00765     unsigned trim;
00766     if (sscanf(txt, "%x", &trim) == 1)
00767         radio.writeReg(REG_ADDR_XTB_TRIM, trim, 1);
00768 
00769     return false;
00770 }
00771 
00772 const value_item_t Radio::xtb_item = { _ITEM_VALUE, 3, xtb_print, xtb_write};
00773 
00774 void Radio::ldo_push()
00775 {
00776     uint8_t buf = 0;
00777     radio.xfer(OPCODE_SET_REGULATOR_MODE, 1, 0, &buf);
00778     log_printf("-> LDO\r\n");
00779 }
00780 
00781 const button_item_t Radio::ldo_item = { _ITEM_BUTTON, "LDO", ldo_push };
00782 
00783 void Radio::dcdc_push()
00784 {
00785     uint8_t buf = 1;
00786     radio.xfer(OPCODE_SET_REGULATOR_MODE, 1, 0, &buf);
00787     log_printf("-> DC-DC\r\n");
00788 }
00789 
00790 const button_item_t Radio::dcdc_item = { _ITEM_BUTTON, "DCDC", dcdc_push };
00791 
00792 static const char* const rxfe_pms[] = {
00793     "LP  0dB",
00794     "HP1 2dB",
00795     "HP2 4dB",
00796     "HP3 6dB",
00797     NULL
00798 };
00799 
00800 unsigned Radio::rxfe_pm_read(bool)
00801 {
00802     AgcSensiAdj_t agcs;
00803     agcs.octet = radio.readReg(REG_ADDR_AGC_SENSI_ADJ, 1);
00804     return agcs.bits.power_mode;
00805 }
00806 
00807 menuMode_e Radio::rxfe_pm_write(unsigned sidx)
00808 {
00809     AgcSensiAdj_t agcs;
00810     agcs.octet = radio.readReg(REG_ADDR_AGC_SENSI_ADJ, 1);
00811     agcs.bits.power_mode = sidx;
00812     radio.writeReg(REG_ADDR_AGC_SENSI_ADJ, agcs.octet, 1);
00813     return MENUMODE_REDRAW;
00814 }
00815 
00816 const dropdown_item_t Radio::rxfe_pm_item = { _ITEM_DROPDOWN, rxfe_pms, rxfe_pms, rxfe_pm_read, rxfe_pm_write};
00817 
00818 #ifdef MEMSCAN
00819 #define SHADOW_SIZE     0x9ff
00820 uint8_t Radio::shadow_read[SHADOW_SIZE];
00821 
00822 void Radio::memread_push()
00823 {
00824     unsigned addr;
00825     for (addr = 0; addr < SHADOW_SIZE; addr++) {
00826         shadow_read[addr] = radio.readReg(addr, 1);
00827     }
00828     log_printf("memread\r\n");
00829 }
00830 
00831 const button_item_t Radio::memread_item = { _ITEM_BUTTON, "MRead", memread_push };
00832 
00833 void Radio::memcmp_push()
00834 {
00835     unsigned addr;
00836     uint8_t r;
00837     for (addr = 0; addr < SHADOW_SIZE; addr++) {
00838         r = radio.readReg(addr, 1);
00839         if (shadow_read[addr] != r) {
00840             log_printf("%03x: %02x -> %02x\r\n", addr, shadow_read[addr], r);
00841         }
00842     }
00843     log_printf("memcmpDone\r\n");
00844 }
00845 
00846 const button_item_t Radio::memcmp_item = { _ITEM_BUTTON, "MCmp", memcmp_push };
00847 #endif /* MEMSCAN */
00848 
00849 void to_big_endian24(uint32_t in, uint8_t *out)
00850 {
00851     out[2] = in & 0xff;
00852     in >>= 8;
00853     out[1] = in & 0xff;
00854     in >>= 8;
00855     out[0] = in & 0xff;
00856 }
00857 
00858 void Radio::tcxo_volts_print(void)
00859 {
00860     // yyy;
00861 }
00862 
00863 bool Radio::tcxo_volts_write(const char *txt)
00864 {
00865     uint8_t buf[4];
00866     float volts;
00867     sscanf(txt, "%f", &volts);
00868     if (volts > 3.15)
00869         buf[0] = 7;  // 3.3v
00870     else if (volts > 2.85)
00871         buf[0] = 6; // 3.0v
00872     else if (volts > 2.55)
00873         buf[0] = 5; // 2.7v
00874     else if (volts > 2.3)
00875         buf[0] = 4; // 2.4v
00876     else if (volts > 2.3)
00877         buf[0] = 3; // 2.2v
00878     else if (volts > 2.0)
00879         buf[0] = 2; // 1.8v
00880     else if (volts > 1.65)
00881         buf[0] = 1; // 1.7v
00882     else
00883         buf[0] = 0; // 1.6v
00884 
00885     to_big_endian24(tcxoDelayTicks, buf+1);
00886 
00887     radio.xfer(OPCODE_SET_DIO3_AS_TCXO_CTRL, 4, 0, buf);
00888     log_printf("set txco %u, %u\r\n", buf[0], tcxoDelayTicks);
00889     return false;
00890 }
00891 
00892 const value_item_t Radio::tcxo_volts_item = { _ITEM_VALUE, 3, tcxo_volts_print, tcxo_volts_write};
00893 
00894 void Radio::tcxo_delay_print(void)
00895 {
00896     printf("%u", tcxoDelayTicks / 64);
00897 }
00898 
00899 
00900 bool Radio::tcxo_delay_write(const char *txt)
00901 {
00902     unsigned ms;
00903     sscanf(txt, "%u", &ms);
00904     tcxoDelayTicks = ms * 64;
00905     return false;
00906 }
00907 
00908 const value_item_t Radio::tcxo_delay_item = { _ITEM_VALUE, 5, tcxo_delay_print, tcxo_delay_write};
00909 
00910 const menu_t Radio::common_menu[] = {
00911     { {FIRST_CHIP_MENU_ROW,  1},   "deviceSel:",   &deviceSel_item, FLAG_MSGTYPE_ALL, &tx_dbm_item },
00912     { {FIRST_CHIP_MENU_ROW, 18}, "paDutyCycle:", &paDutyCycle_item, FLAG_MSGTYPE_ALL },
00913     { {FIRST_CHIP_MENU_ROW, 33},       "hpMax:",       &hpMax_item, FLAG_MSGTYPE_ALL },
00914     { {FIRST_CHIP_MENU_ROW, 42},      "ocp mA:",         &ocp_item, FLAG_MSGTYPE_ALL },
00915     { {FIRST_CHIP_MENU_ROW, 55},         "XTA:",         &xta_item, FLAG_MSGTYPE_ALL },
00916     { {FIRST_CHIP_MENU_ROW, 62},         "XTB:",         &xtb_item, FLAG_MSGTYPE_ALL },
00917 
00918     { {FIRST_CHIP_MENU_ROW+1,  1},  NULL,   &ldo_item, FLAG_MSGTYPE_ALL },
00919     { {FIRST_CHIP_MENU_ROW+1,  5},  NULL,   &dcdc_item, FLAG_MSGTYPE_ALL },
00920     { {FIRST_CHIP_MENU_ROW+1, 12},  "rxfe power:",   &rxfe_pm_item, FLAG_MSGTYPE_ALL },
00921     { {FIRST_CHIP_MENU_ROW+1, 35},  "tcxoVolts:",   &tcxo_volts_item, FLAG_MSGTYPE_ALL },
00922     { {FIRST_CHIP_MENU_ROW+1, 50},  "tcxoDelay(ms):",   &tcxo_delay_item, FLAG_MSGTYPE_ALL },
00923 #ifdef MEMSCAN
00924     { {LAST_CHIP_MENU_ROW, 1},  NULL,   &memread_item, FLAG_MSGTYPE_ALL },
00925     { {LAST_CHIP_MENU_ROW, 10},  NULL,   &memcmp_item, FLAG_MSGTYPE_ALL },
00926 #endif /* MEMSCAN */
00927 
00928     { {0, 0}, NULL, NULL }
00929 };
00930 
00931 const uint8_t loraBWs[] = {
00932     LORA_BW_7, LORA_BW_10, LORA_BW_15,
00933     LORA_BW_20, LORA_BW_31, LORA_BW_41,
00934     LORA_BW_62, LORA_BW_125, LORA_BW_250,
00935     LORA_BW_500
00936 };
00937 
00938 static const char* const lora_bwstrs[] = {
00939     " 7.81KHz", "10.42KHz", "15.63KHz",
00940     "20.83KHz", "31.25KHz", "41.67KHz",
00941     " 62.5KHz", "  125KHz", "  250KHz",
00942     "  500KHz",
00943     NULL
00944 };
00945 
00946 unsigned Radio::lora_bw_read(bool forWriting)
00947 {
00948     unsigned n;
00949     loraConfig0_t conf0;
00950     conf0.octet = radio.readReg(REG_ADDR_LORA_CONFIG0, 1);
00951     mpLORA.lora.bandwidth = conf0.bits.modem_bw;
00952     for (n = 0; n < sizeof(loraBWs); n++) {
00953         if (conf0.bits.modem_bw == loraBWs[n]) {
00954             bw_idx = n;
00955             return n;
00956         }
00957     }
00958     return sizeof(loraBWs);
00959 }
00960 
00961 menuMode_e Radio::lora_bw_write(unsigned sidx)
00962 {
00963     mpLORA.lora.bandwidth = loraBWs[sidx];
00964     radio.xfer(OPCODE_SET_MODULATION_PARAMS, 4, 0, mpLORA.buf);
00965     bw_idx = sidx;
00966     return MENUMODE_REDRAW;
00967 }
00968 
00969 const dropdown_item_t Radio::lora_bw_item = { _ITEM_DROPDOWN, lora_bwstrs, lora_bwstrs, lora_bw_read, lora_bw_write};
00970 
00971 void Radio::lora_sf_print()
00972 {
00973     loraConfig0_t conf0;
00974     conf0.octet = radio.readReg(REG_ADDR_LORA_CONFIG0, 1);
00975     mpLORA.lora.spreadingFactor = conf0.bits.modem_sf;
00976     printf("%u", conf0.bits.modem_sf);
00977 }
00978 
00979 bool Radio::lora_sf_write(const char* str)
00980 {
00981     unsigned sf;
00982     if (sscanf(str, "%u", &sf) == 1) {
00983         mpLORA.lora.spreadingFactor = sf;
00984         radio.xfer(OPCODE_SET_MODULATION_PARAMS, 4, 0, mpLORA.buf);
00985     }
00986     return false;
00987 }
00988 
00989 const value_item_t Radio::lora_sf_item = { _ITEM_VALUE, 3, lora_sf_print, lora_sf_write };
00990 
00991 static const char* const lora_crs[] = {
00992     "4/5   ",
00993     "4/6   ",
00994     "4/7   ",
00995     "4/8   ",
00996     NULL
00997 };
00998 
00999 unsigned Radio::lora_cr_read(bool forWriting)
01000 {
01001     loraConfig1_t conf1;
01002     conf1.octet = radio.readReg(REG_ADDR_LORA_CONFIG1, 1);
01003     mpLORA.lora.codingRate = conf1.bits.tx_coding_rate;
01004     return conf1.bits.tx_coding_rate;
01005 }
01006 
01007 menuMode_e Radio::lora_cr_write(unsigned sidx)
01008 {
01009     mpLORA.lora.codingRate = sidx;
01010     radio.xfer(OPCODE_SET_MODULATION_PARAMS, 4, 0, mpLORA.buf);
01011     return MENUMODE_REDRAW;
01012 }
01013 
01014 const dropdown_item_t Radio::lora_cr_item = { _ITEM_DROPDOWN, lora_crs, lora_crs, lora_cr_read, lora_cr_write};
01015 
01016 bool Radio::ppmOffset_read()
01017 {
01018     loraConfig1_t conf1;
01019     conf1.octet = radio.readReg(REG_ADDR_LORA_CONFIG1, 1);
01020     mpLORA.lora.LowDatarateOptimize = conf1.bits.ppm_offset;
01021     return conf1.bits.ppm_offset;
01022 }
01023 
01024 bool Radio::ppmOffset_push()
01025 {
01026     if (mpLORA.lora.LowDatarateOptimize)
01027         mpLORA.lora.LowDatarateOptimize = 0;
01028     else
01029         mpLORA.lora.LowDatarateOptimize = 1;
01030 
01031     radio.xfer(OPCODE_SET_MODULATION_PARAMS, 4, 0, mpLORA.buf);
01032     return mpLORA.lora.LowDatarateOptimize;
01033 }
01034 
01035 const toggle_item_t Radio::lora_ppmOffset_item = { _ITEM_TOGGLE, "LowDatarateOptimize", NULL, ppmOffset_read, ppmOffset_push};
01036 
01037 void Radio::lora_pblLen_print()
01038 {
01039     unsigned val = radio.readReg(REG_ADDR_LORA_PREAMBLE_SYMBNB, 2);
01040     ppLORA.lora.PreambleLengthHi = val >> 8;
01041     ppLORA.lora.PreambleLengthLo = val;
01042     printf("%u", val);
01043 }
01044 
01045 bool Radio::lora_pblLen_write(const char* txt)
01046 {
01047     unsigned n;
01048     if (sscanf(txt, "%u", &n) == 1) {
01049         ppLORA.lora.PreambleLengthHi = n >> 8;
01050         ppLORA.lora.PreambleLengthLo = n;
01051         radio.xfer(OPCODE_SET_PACKET_PARAMS, 6, 0, ppLORA.buf);
01052     }
01053     return false;
01054 }
01055 
01056 const value_item_t Radio::lora_pblLen_item = { _ITEM_VALUE, 5, lora_pblLen_print, lora_pblLen_write};
01057 
01058 bool Radio::lora_headerType_read()
01059 {
01060     loraConfig1_t conf1;
01061     conf1.octet = radio.readReg(REG_ADDR_LORA_CONFIG1, 1);
01062     ppLORA.lora.HeaderType = conf1.bits.implicit_header;
01063     return conf1.bits.implicit_header;
01064 }
01065 
01066 bool Radio::lora_headerType_push()
01067 {
01068     if (ppLORA.lora.HeaderType)
01069         ppLORA.lora.HeaderType = 0;
01070     else
01071         ppLORA.lora.HeaderType = 1;
01072 
01073     radio.xfer(OPCODE_SET_PACKET_PARAMS, 6, 0, ppLORA.buf);
01074     return ppLORA.lora.HeaderType;
01075 }
01076 
01077 const toggle_item_t Radio::lora_headerType_item = { _ITEM_TOGGLE, "EXPLICIT", "IMPLICIT", lora_headerType_read, lora_headerType_push};
01078 
01079 bool Radio::lora_crcon_read()
01080 {
01081     loraConfig2_t conf2;
01082     conf2.octet = radio.readReg(REG_ADDR_LORA_CONFIG2, 1);
01083     ppLORA.lora.CRCType = conf2.bits.tx_payload_crc16_en;
01084     return conf2.bits.tx_payload_crc16_en;
01085 }
01086 
01087 bool Radio::lora_crcon_push()
01088 {
01089     if (ppLORA.lora.CRCType)
01090         ppLORA.lora.CRCType = 0;
01091     else
01092         ppLORA.lora.CRCType = 1;
01093 
01094     radio.xfer(OPCODE_SET_PACKET_PARAMS, 6, 0, ppLORA.buf);
01095     return ppLORA.lora.CRCType;
01096 }
01097 
01098 const toggle_item_t Radio::lora_crcon_item = { _ITEM_TOGGLE, "CrcOn", NULL, lora_crcon_read, lora_crcon_push};
01099 
01100 bool Radio::lora_inviq_read()
01101 {
01102     loraConfig1_t conf1;
01103     conf1.octet = radio.readReg(REG_ADDR_LORA_CONFIG1, 1);
01104     ppLORA.lora.InvertIQ = conf1.bits.rx_invert_iq;
01105     return conf1.bits.rx_invert_iq;
01106 }
01107 
01108 bool Radio::lora_inviq_push()
01109 {
01110     if (ppLORA.lora.InvertIQ)
01111         ppLORA.lora.InvertIQ = 0;
01112     else
01113         ppLORA.lora.InvertIQ = 1;
01114 
01115     radio.xfer(OPCODE_SET_PACKET_PARAMS, 6, 0, ppLORA.buf);
01116     return ppLORA.lora.InvertIQ;
01117 }
01118 
01119 const toggle_item_t Radio::lora_inviq_item = { _ITEM_TOGGLE, "InvertIQ", NULL, lora_inviq_read, lora_inviq_push};
01120 
01121 void Radio::lora_ppg_print()
01122 {
01123     uint8_t val;
01124     ppg = radio.readReg(REG_ADDR_LORA_SYNC, 2);
01125 
01126     val = (ppg >> 8) & 0xf0;
01127     val |= (ppg & 0xf0) >> 4;
01128     printf("%02x", val);
01129 }
01130 
01131 bool Radio::lora_ppg_write(const char* txt)
01132 {
01133     unsigned val;
01134     if (sscanf(txt, "%x", &val) == 1) {
01135         ppg &= 0x0707;
01136         ppg |= (val & 0xf0) << 8;
01137         ppg |= (val & 0x0f) << 4;
01138         radio.writeReg(REG_ADDR_LORA_SYNC, ppg, 2);
01139     }
01140     return false;
01141 }
01142 
01143 const value_item_t Radio::lora_ppg_item = { _ITEM_VALUE, 4, lora_ppg_print, lora_ppg_write};
01144 
01145 bool Radio::lora_sdmode_read()
01146 {
01147     sdCfg0_t sdcfg;
01148     sdcfg.octet = radio.readReg(REG_ADDR_SDCFG0, 1);
01149     return sdcfg.bits.sd_mode;
01150 }
01151 
01152 bool Radio::lora_sdmode_push()
01153 {
01154     sdCfg0_t sdcfg;
01155     sdcfg.octet = radio.readReg(REG_ADDR_SDCFG0, 1);
01156     sdcfg.bits.sd_mode ^= 1;
01157     radio.writeReg(REG_ADDR_SDCFG0, sdcfg.octet, 1);
01158     return sdcfg.bits.sd_mode;
01159 }
01160 
01161 const toggle_item_t Radio::lora_sdmode_item = { _ITEM_TOGGLE, "sd_mode", NULL, lora_sdmode_read, lora_sdmode_push};
01162 
01163 void Radio::cad_push()
01164 {
01165     {
01166         uint8_t buf[8];
01167         IrqFlags_t irqEnable;
01168         irqEnable.word = 0;
01169         irqEnable.bits.RxDone = 1;
01170         irqEnable.bits.Timeout = 1;
01171         irqEnable.bits.CadDetected = 1;
01172         irqEnable.bits.CadDone = 1;
01173 
01174         buf[0] = 3;//irqEnable.word >> 8;    // enable bits
01175         buf[1] = 0xff;//irqEnable.word; // enable bits
01176         buf[2] = irqEnable.word >> 8;     // dio1
01177         buf[3] = irqEnable.word;  // dio1
01178         buf[4] = 0; // dio2
01179         buf[5] = 0; // dio2
01180         buf[6] = 0; // dio3
01181         buf[7] = 0; // dio3
01182         radio.xfer(OPCODE_SET_DIO_IRQ_PARAMS, 8, 0, buf);
01183     }
01184 
01185     radio.setCAD();
01186 }
01187 
01188 const button_item_t Radio::lora_cad_item = { _ITEM_BUTTON, "CAD", cad_push };
01189 
01190 static const char* const lora_cadsymbs[] = {
01191     " 1",
01192     " 2",
01193     " 4",
01194     " 8",
01195     "16",
01196     NULL
01197 };
01198 
01199 unsigned Radio::lora_cadsymbs_read(bool forWriting)
01200 {
01201     cadParams[0] = radio.readReg(REG_ADDR_LORA_CONFIG9, 1);
01202     cadParams[0] >>= 5;
01203     return cadParams[0];
01204 }
01205 
01206 menuMode_e Radio::lora_cadsymbs_write(unsigned sidx)
01207 {
01208     cadParams[0] = sidx;
01209     radio.xfer(OPCODE_SET_CAD_PARAM, 7, 0, cadParams);
01210     return MENUMODE_REDRAW;
01211 }
01212 
01213 const dropdown_item_t Radio::lora_cadsymbs_item = { _ITEM_DROPDOWN, lora_cadsymbs, lora_cadsymbs, lora_cadsymbs_read, lora_cadsymbs_write};
01214 
01215 void Radio::lora_cadpnratio_print()
01216 {
01217     cadParams[1] = radio.readReg(REG_ADDR_LORA_CAD_PN_RATIO, 1);
01218     printf("%u", cadParams[1]);
01219 }
01220 
01221 bool Radio::lora_cadpnratio_write(const char* txt)
01222 {
01223     unsigned n;
01224     sscanf(txt, "%u", &n);
01225     cadParams[1] = n;
01226     radio.xfer(OPCODE_SET_CAD_PARAM, 7, 0, cadParams);
01227     return false;
01228 }
01229 
01230 const value_item_t Radio::lora_cadpnratio_item = { _ITEM_VALUE, 4, lora_cadpnratio_print, lora_cadpnratio_write};
01231 
01232 void Radio::lora_cadmin_print()
01233 {
01234     cadParams[2] = radio.readReg(REG_ADDR_LORA_CAD_MINPEAK, 1);
01235     printf("%u", cadParams[2]);
01236 }
01237 
01238 bool Radio::lora_cadmin_write(const char* txt)
01239 {
01240     unsigned n;
01241     sscanf(txt, "%u", &n);
01242     cadParams[2] = n;
01243     radio.xfer(OPCODE_SET_CAD_PARAM, 7, 0, cadParams);
01244     return false;
01245 }
01246 
01247 const value_item_t Radio::lora_cadmin_item = { _ITEM_VALUE, 4, lora_cadmin_print, lora_cadmin_write};
01248 
01249 bool Radio::lora_cadexit_read()
01250 {
01251     return cadParams[3];
01252 }
01253 
01254 bool Radio::lora_cadexit_push()
01255 {
01256     if (cadParams[3])
01257         cadParams[3] = 0;
01258     else
01259         cadParams[3] = 1;
01260 
01261     radio.xfer(OPCODE_SET_CAD_PARAM, 7, 0, cadParams);
01262 
01263     return cadParams[3];
01264 }
01265 
01266 const toggle_item_t Radio::lora_cadexit_item = { _ITEM_TOGGLE, "CAD_ONLY", "CAD_RX  ", lora_cadexit_read, lora_cadexit_push};
01267 
01268 void Radio::lora_cadtimeout_print(void)
01269 {
01270     unsigned n;
01271 
01272     n = cadParams[4];
01273     n <<= 8;
01274     n += cadParams[5];
01275     n <<= 8;
01276     n += cadParams[6];
01277     printf("%u", n);
01278 }
01279 
01280 bool Radio::lora_cadtimeout_write(const char* txt)
01281 {
01282     unsigned n;
01283     float ticks;
01284 
01285     sscanf(txt, "%u", &n);
01286     ticks = n / 15.625;
01287     n = ticks;
01288 
01289     cadParams[4] = n >> 16;
01290     cadParams[5] = n >> 8;
01291     cadParams[6] = n;
01292 
01293     return false;
01294 }
01295 
01296 const value_item_t Radio::lora_cadtimeout_item = { _ITEM_VALUE, 4, lora_cadtimeout_print, lora_cadtimeout_write};
01297 
01298 const menu_t Radio::lora_menu[] = {
01299     { {FIRST_CHIP_MENU_ROW+2,  1},   NULL,      &lora_bw_item, FLAG_MSGTYPE_ALL },
01300     { {FIRST_CHIP_MENU_ROW+2, 12},  "sf:",      &lora_sf_item, FLAG_MSGTYPE_ALL },
01301     { {FIRST_CHIP_MENU_ROW+2, 20},  "cr:",      &lora_cr_item, FLAG_MSGTYPE_ALL },
01302     { {FIRST_CHIP_MENU_ROW+2, 30},   NULL, &lora_ppmOffset_item, FLAG_MSGTYPE_ALL },
01303 
01304     { {FIRST_CHIP_MENU_ROW+3,  1}, "PreambleLength:", &lora_pblLen_item, FLAG_MSGTYPE_ALL },
01305     { {FIRST_CHIP_MENU_ROW+3, 22},              NULL, &lora_headerType_item, FLAG_MSGTYPE_ALL },
01306     { {FIRST_CHIP_MENU_ROW+3, 32},              NULL, &lora_crcon_item, FLAG_MSGTYPE_ALL },
01307     { {FIRST_CHIP_MENU_ROW+3, 39},              NULL, &lora_inviq_item, FLAG_MSGTYPE_ALL },
01308     { {FIRST_CHIP_MENU_ROW+3, 49},            "ppg:", &lora_ppg_item, FLAG_MSGTYPE_ALL },
01309     { {FIRST_CHIP_MENU_ROW+3, 58},              NULL, &lora_sdmode_item, FLAG_MSGTYPE_ALL },
01310 
01311     { {FIRST_CHIP_MENU_ROW+4,  1},          NULL,        &lora_cad_item, FLAG_MSGTYPE_ALL },
01312     { {FIRST_CHIP_MENU_ROW+4,  5},    "symbols:",   &lora_cadsymbs_item, FLAG_MSGTYPE_ALL },
01313     { {FIRST_CHIP_MENU_ROW+4, 20}, "peak/noise:", &lora_cadpnratio_item, FLAG_MSGTYPE_ALL },
01314     { {FIRST_CHIP_MENU_ROW+4, 35},        "min:",     &lora_cadmin_item, FLAG_MSGTYPE_ALL },
01315     { {FIRST_CHIP_MENU_ROW+4, 45},       "exit:",    &lora_cadexit_item, FLAG_MSGTYPE_ALL },
01316     { {FIRST_CHIP_MENU_ROW+4, 62}, "timeout us:", &lora_cadtimeout_item, FLAG_MSGTYPE_ALL },
01317 
01318     { {0, 0}, NULL, NULL }
01319 };
01320 
01321 void Radio::test()
01322 {
01323     pktType = radio.getPacketType();
01324 
01325     if (pktType == PACKET_TYPE_GFSK) {
01326     } else if (pktType == PACKET_TYPE_LORA) {
01327     }
01328 }
01329 
01330 void Radio::gfsk_bitrate_print()
01331 {
01332     unsigned d = radio.readReg(REG_ADDR_BITRATE, 3);
01333     float f = d / 32.0;
01334 
01335     printf("%u", (unsigned)(XTAL_FREQ_HZ / f));
01336 
01337     mpFSK.gfsk.bitrateHi = d >> 16;
01338     mpFSK.gfsk.bitrateMid = d >> 8;
01339     mpFSK.gfsk.bitrateLo = d;
01340 }
01341 
01342 bool Radio::gfsk_bitrate_write(const char* txt)
01343 {
01344     unsigned bps, br;
01345 
01346     if (sscanf(txt, "%u", &bps) == 1) {
01347         br = 32 * (XTAL_FREQ_HZ / (float)bps);
01348         mpFSK.gfsk.bitrateHi = br >> 16;
01349         mpFSK.gfsk.bitrateMid = br >> 8;
01350         mpFSK.gfsk.bitrateLo = br;
01351         radio.xfer(OPCODE_SET_MODULATION_PARAMS, 8, 0, mpFSK.buf);
01352     }
01353     return false;
01354 }
01355 
01356 const value_item_t Radio::gfsk_bitrate_item = { _ITEM_VALUE, 8, gfsk_bitrate_print, gfsk_bitrate_write};
01357 
01358 static const char* const gfsk_bts[] = {
01359     "off", // 0
01360     "0.3", // 1
01361     "0.5", // 2
01362     "0.7", // 3
01363     "1.0", // 4
01364     NULL
01365 };
01366 
01367 unsigned Radio::gfsk_bt_read(bool forWriting)
01368 {
01369     shapeCfg_t shapeCfg;
01370     shapeCfg.octet = radio.readReg(REG_ADDR_SHAPECFG, 1);
01371     mpFSK.gfsk.PulseShape = shapeCfg.octet;
01372     if (shapeCfg.bits.pulse_shape)
01373         return shapeCfg.bits.bt + 1;
01374     else
01375         return 0;
01376 }
01377 
01378 menuMode_e Radio::gfsk_bt_write(unsigned sidx)
01379 {
01380     switch (sidx) {
01381         case 0: mpFSK.gfsk.PulseShape = GFSK_SHAPE_NONE; break;
01382         case 1: mpFSK.gfsk.PulseShape = GFSK_SHAPE_BT0_3; break;
01383         case 2: mpFSK.gfsk.PulseShape = GFSK_SHAPE_BT0_5; break;
01384         case 3: mpFSK.gfsk.PulseShape = GFSK_SHAPE_BT0_7; break;
01385         case 4: mpFSK.gfsk.PulseShape = GFSK_SHAPE_BT1_0; break;
01386     }
01387     radio.xfer(OPCODE_SET_MODULATION_PARAMS, 8, 0, mpFSK.buf);
01388     return MENUMODE_REDRAW;
01389 }
01390 
01391 const dropdown_item_t Radio::gfsk_bt_item = { _ITEM_DROPDOWN, gfsk_bts, gfsk_bts, gfsk_bt_read, gfsk_bt_write};
01392 
01393 static const uint8_t rx_bws[] = {
01394       GFSK_RX_BW_4800,   GFSK_RX_BW_5800,   GFSK_RX_BW_7300,   GFSK_RX_BW_9700,
01395      GFSK_RX_BW_11700,  GFSK_RX_BW_14600,  GFSK_RX_BW_19500,  GFSK_RX_BW_23400,
01396      GFSK_RX_BW_29300,  GFSK_RX_BW_39000,  GFSK_RX_BW_46900,  GFSK_RX_BW_58600,
01397      GFSK_RX_BW_78200,  GFSK_RX_BW_93800, GFSK_RX_BW_117300, GFSK_RX_BW_156200,
01398     GFSK_RX_BW_187200, GFSK_RX_BW_234300, GFSK_RX_BW_312000, GFSK_RX_BW_373600,
01399     GFSK_RX_BW_467000
01400 };
01401 
01402 static const char* const rxbw_str[] = {
01403     "  4.8KHz", "  5.8KHz", "  7.3KHz", "  9.7KHz",
01404     " 11.7KHz", " 14.6KHz", " 19.5KHz", " 23.4KHz",
01405     " 29.3KHz", " 39.0KHz", " 46.9KHz", " 58.6KHz",
01406     " 78.2KHz", " 93.8KHz", "117.3KHz", "156.2KHz",
01407     "187.2KHz", "234.3KHz", "312.0KHz", "373.6KHz",
01408     "467.0KHz",
01409     NULL
01410 };
01411 
01412 unsigned Radio::gfsk_rxbw_read(bool forWriting)
01413 {
01414     unsigned n;
01415     bwSel_t bwSel;
01416     bwSel.octet = radio.readReg(REG_ADDR_BWSEL, 1);
01417     mpFSK.gfsk.bandwidth = bwSel.octet;
01418 
01419     for (n = 0; n < sizeof(rx_bws); n++) {
01420         if (bwSel.octet == rx_bws[n])
01421             return n;
01422     }
01423     return sizeof(rx_bws);
01424 }
01425 
01426 menuMode_e Radio::gfsk_rxbw_write(unsigned sidx)
01427 {
01428     mpFSK.gfsk.bandwidth = rx_bws[sidx];
01429     radio.xfer(OPCODE_SET_MODULATION_PARAMS, 8, 0, mpFSK.buf);
01430     return MENUMODE_REDRAW;
01431 }
01432 
01433 const dropdown_item_t Radio::gfsk_rxbw_item = { _ITEM_DROPDOWN, rxbw_str, rxbw_str, gfsk_rxbw_read, gfsk_rxbw_write};
01434 
01435 void Radio::gfsk_fdev_print()
01436 {
01437     unsigned d = radio.readReg(REG_ADDR_FREQDEV, 3);
01438     printf("%u", (unsigned)(d * FREQ_STEP));
01439 }
01440 
01441 bool Radio::gfsk_fdev_write(const char* txt)
01442 {
01443     unsigned hz, fdev;
01444     if (sscanf(txt, "%u", &hz) == 1) {
01445         fdev = hz / FREQ_STEP;
01446         mpFSK.gfsk.fdevHi = fdev >> 16;
01447         mpFSK.gfsk.fdevMid = fdev >> 8;
01448         mpFSK.gfsk.fdevLo = fdev;
01449         radio.xfer(OPCODE_SET_MODULATION_PARAMS, 8, 0, mpFSK.buf);
01450     }
01451     return false;
01452 }
01453 
01454 const value_item_t Radio::gfsk_fdev_item = { _ITEM_VALUE, 8, gfsk_fdev_print, gfsk_fdev_write};
01455 
01456 void Radio::gfsk_pblLen_print()
01457 {
01458     unsigned n = radio.readReg(REG_ADDR_FSK_PREAMBLE_TXLEN , 2);
01459     ppFSK.gfsk.PreambleLengthHi = n << 8; // param1
01460     ppFSK.gfsk.PreambleLengthLo = n;// param2
01461     printf("%u", n);
01462 }
01463 
01464 bool Radio::gfsk_pblLen_write(const char* txt)
01465 {
01466     unsigned n;
01467     if (sscanf(txt, "%u", &n) == 1) {
01468         ppFSK.gfsk.PreambleLengthHi = n << 8; // param1
01469         ppFSK.gfsk.PreambleLengthLo = n;// param2
01470         radio.xfer(OPCODE_SET_PACKET_PARAMS, 9, 0, ppFSK.buf);
01471     }
01472     return false;
01473 }
01474 
01475 const value_item_t Radio::gfsk_pblLen_item = { _ITEM_VALUE, 5, gfsk_pblLen_print, gfsk_pblLen_write};
01476 
01477 static const char* const fsk_detlens[] = {
01478     " off  ",
01479     " 8bits",
01480     "16bits",
01481     "24bits",
01482     "32bits",
01483     NULL
01484 };
01485 
01486 unsigned Radio::gfsk_pblDetLen_read(bool forWriting)
01487 {
01488     pktCtrl1_t pktCtrl1;
01489     pktCtrl1.octet = radio.readReg(REG_ADDR_FSK_PKTCTRL1, 1);
01490     ppFSK.gfsk.PreambleDetectorLength = pktCtrl1.octet & 0x07;    // param3
01491     if (pktCtrl1.bits.preamble_det_on)
01492         return pktCtrl1.bits.preamble_len_rx + 1;
01493     else
01494         return 0;
01495 }
01496 
01497 menuMode_e Radio::gfsk_pblDetLen_write(unsigned sidx)
01498 {
01499     if (sidx == 0)
01500         ppFSK.gfsk.PreambleDetectorLength = 0;
01501     else
01502         ppFSK.gfsk.PreambleDetectorLength = sidx + 3;
01503 
01504     radio.xfer(OPCODE_SET_PACKET_PARAMS, 9, 0, ppFSK.buf);
01505     return MENUMODE_REDRAW;
01506 }
01507 
01508 const dropdown_item_t Radio::gfsk_pblDetLen_item = { _ITEM_DROPDOWN, fsk_detlens, fsk_detlens, gfsk_pblDetLen_read, gfsk_pblDetLen_write};
01509 
01510 void Radio::gfsk_swl_print()
01511 {
01512     ppFSK.gfsk.SyncWordLength = radio.readReg(REG_ADDR_FSK_SYNC_LEN, 1);// param4
01513     printf("%u", ppFSK.gfsk.SyncWordLength);
01514 }
01515 
01516 bool Radio::gfsk_swl_write(const char* txt)
01517 {
01518     unsigned n;
01519     unsigned r;
01520     r = sscanf(txt, "%u", &n);
01521     if (r == 1) {
01522         ppFSK.gfsk.SyncWordLength = n;
01523         radio.xfer(OPCODE_SET_PACKET_PARAMS, 9, 0, ppFSK.buf);
01524     }
01525     return false;
01526 }
01527 
01528 const value_item_t Radio::gfsk_swl_item = { _ITEM_VALUE, 3, gfsk_swl_print, gfsk_swl_write};
01529 
01530 void Radio::gfsk_syncword_print()
01531 {
01532     unsigned addr = REG_ADDR_SYNCADDR;
01533     uint8_t swl_bits = radio.readReg(REG_ADDR_FSK_SYNC_LEN, 1);
01534     if (swl_bits & 7) {
01535         swl_bits |= 7;
01536         swl_bits++;
01537     }
01538     while (swl_bits > 0) {
01539         printf("%02x", (unsigned)radio.readReg(addr++, 1));
01540         swl_bits -= 8;
01541     }
01542 }
01543 
01544 bool Radio::gfsk_syncword_write(const char* txt)
01545 {
01546     const char* ptr = txt;
01547     unsigned addr = REG_ADDR_SYNCADDR;
01548     int8_t swl_bits = radio.readReg(REG_ADDR_FSK_SYNC_LEN, 1);
01549     if (swl_bits & 7) {
01550         swl_bits |= 7;
01551         swl_bits++;
01552     }
01553     while (swl_bits > 0) {
01554         char buf[3];
01555         unsigned n;
01556         buf[0] = ptr[0];
01557         buf[1] = ptr[1];
01558         buf[2] = 0;
01559         sscanf(buf, "%x", &n);
01560         radio.writeReg(addr++, n, 1);
01561         ptr += 2;
01562         swl_bits -= 8;
01563     }
01564     return false;
01565 }
01566 
01567 const value_item_t Radio::gfsk_syncword_item = { _ITEM_VALUE, 17, gfsk_syncword_print, gfsk_syncword_write};
01568 
01569 bool Radio::gfsk_fixLen_read()
01570 {
01571     pktCtrl0_t pktCtrl0;
01572     pktCtrl0.octet = radio.readReg(REG_ADDR_FSK_PKTCTRL0, 1);
01573     ppFSK.gfsk.PacketType = pktCtrl0.bits.pkt_len_format;   // param6
01574     return pktCtrl0.bits.pkt_len_format;
01575 }
01576 
01577 bool Radio::gfsk_fixLen_push()
01578 {
01579     if (ppFSK.gfsk.PacketType)
01580         ppFSK.gfsk.PacketType = 0;
01581     else
01582         ppFSK.gfsk.PacketType = 1;
01583 
01584     radio.xfer(OPCODE_SET_PACKET_PARAMS, 9, 0, ppFSK.buf);
01585     return ppFSK.gfsk.PacketType;
01586 }
01587 
01588 const toggle_item_t Radio::gfsk_fixLen_item = { _ITEM_TOGGLE,
01589     "fixed   ",
01590     "variable",
01591     gfsk_fixLen_read, gfsk_fixLen_push
01592 };
01593 
01594 
01595 static const char* const addrcomps[] = {
01596     "          off        ",
01597     "NodeAddress          ",
01598     "NodeAddress+broadcast",
01599     NULL
01600 };
01601 
01602 unsigned Radio::gfsk_addrcomp_read(bool forWriting)
01603 {
01604     ppFSK.gfsk.AddrComp = radio.readReg(REG_ADDR_NODEADDRCOMP, 1);// param5
01605     return ppFSK.gfsk.AddrComp;
01606 }
01607 
01608 menuMode_e Radio::gfsk_addrcomp_write(unsigned sidx)
01609 {
01610     ppFSK.gfsk.AddrComp = sidx;
01611     radio.xfer(OPCODE_SET_PACKET_PARAMS, 9, 0, ppFSK.buf);
01612     return MENUMODE_REDRAW;
01613 }
01614 
01615 const dropdown_item_t Radio::gfsk_addrcomp_item = { _ITEM_DROPDOWN, addrcomps, addrcomps, gfsk_addrcomp_read, gfsk_addrcomp_write};
01616 
01617 void Radio::gfsk_nodeadrs_print()
01618 {
01619     printf("%02x", (unsigned)radio.readReg(REG_ADDR_NODEADDR, 1));
01620 }
01621 
01622 bool Radio::gfsk_nodeadrs_write(const char* txt)
01623 {
01624     unsigned v;
01625     if (sscanf(txt, "%x", &v) == 1)
01626         radio.writeReg(REG_ADDR_NODEADDR, v, 1);
01627 
01628     return false;
01629 }
01630 
01631 const value_item_t Radio::gfsk_nodeadrs_item = { _ITEM_VALUE, 3, gfsk_nodeadrs_print, gfsk_nodeadrs_write};
01632 
01633 void Radio::gfsk_broadcast_print()
01634 {
01635     printf("%02x", (unsigned)radio.readReg(REG_ADDR_BROADCAST, 1));
01636 }
01637 
01638 bool Radio::gfsk_broadcast_write(const char* txt)
01639 {
01640     unsigned v;
01641     if (sscanf(txt, "%x", &v) == 1)
01642         radio.writeReg(REG_ADDR_BROADCAST, v, 1);
01643 
01644     return false;
01645 }
01646 
01647 const value_item_t Radio::gfsk_broadcast_item = { _ITEM_VALUE, 3, gfsk_broadcast_print, gfsk_broadcast_write};
01648 
01649 static const char* crctypes[] = {
01650     "    off   ", // 0
01651     "1 Byte    ", // 1
01652     "2 Byte    ", // 2
01653     "1 Byte inv", // 3
01654     "2 Byte inv", // 4
01655     NULL
01656 };
01657 
01658 unsigned Radio::gfsk_crctype_read(bool forWriting)
01659 {
01660     pktCtrl2_t pktCtrl2;
01661     pktCtrl2.octet = radio.readReg(REG_ADDR_FSK_PKTCTRL2, 1);
01662     ppFSK.gfsk.CRCType = pktCtrl2.octet & 0x7; // param8
01663     switch (ppFSK.gfsk.CRCType) {
01664         case GFSK_CRC_OFF: return 0;
01665         case GFSK_CRC_1_BYTE: return 1;
01666         case GFSK_CRC_2_BYTE: return 2;
01667         case GFSK_CRC_1_BYTE_INV: return 3;
01668         case GFSK_CRC_2_BYTE_INV: return 4;
01669         default: return 5;
01670     }
01671 }
01672 
01673 menuMode_e Radio::gfsk_crctype_write(unsigned sidx)
01674 {
01675     switch (sidx) {
01676         case 0: ppFSK.gfsk.CRCType = GFSK_CRC_OFF; break;
01677         case 1: ppFSK.gfsk.CRCType = GFSK_CRC_1_BYTE; break;
01678         case 2: ppFSK.gfsk.CRCType = GFSK_CRC_2_BYTE; break;
01679         case 3: ppFSK.gfsk.CRCType = GFSK_CRC_1_BYTE_INV; break;
01680         case 4: ppFSK.gfsk.CRCType = GFSK_CRC_2_BYTE_INV; break;
01681     }
01682 
01683     radio.xfer(OPCODE_SET_PACKET_PARAMS, 9, 0, ppFSK.buf);
01684     return MENUMODE_REDRAW;
01685 }
01686 
01687 const dropdown_item_t Radio::gfsk_crctype_item = { _ITEM_DROPDOWN, crctypes, crctypes, gfsk_crctype_read, gfsk_crctype_write};
01688 
01689 bool Radio::gfsk_white_read()
01690 {
01691     pktCtrl2_t pktCtrl2;
01692     pktCtrl2.octet = radio.readReg(REG_ADDR_FSK_PKTCTRL2, 1);
01693     ppFSK.gfsk.Whitening = pktCtrl2.bits.whit_enable;   // param9
01694     return pktCtrl2.bits.whit_enable;
01695 }
01696 
01697 bool Radio::gfsk_white_push()
01698 {
01699     if (ppFSK.gfsk.Whitening)
01700         ppFSK.gfsk.Whitening = 0;
01701     else
01702         ppFSK.gfsk.Whitening = 1;
01703 
01704     radio.xfer(OPCODE_SET_PACKET_PARAMS, 9, 0, ppFSK.buf);
01705     return ppFSK.gfsk.Whitening;
01706 }
01707 
01708 const toggle_item_t Radio::gfsk_white_item = { _ITEM_TOGGLE, "Whitening", NULL, gfsk_white_read, gfsk_white_push};
01709 
01710 void Radio::gfsk_crcinit_print()
01711 {
01712     printf("%04x", (unsigned)radio.readReg(REG_ADDR_FSK_CRCINIT, 2));
01713 }
01714 
01715 bool Radio::gfsk_crcinit_write(const char* txt)
01716 {
01717     unsigned v;
01718     if (sscanf(txt, "%x", &v) == 1)
01719         radio.writeReg(REG_ADDR_FSK_CRCINIT, v, 2);
01720 
01721     return false;
01722 }
01723 
01724 const value_item_t Radio::gfsk_crcinit_item = { _ITEM_VALUE, 5, gfsk_crcinit_print, gfsk_crcinit_write};
01725 
01726 void Radio::gfsk_crcpoly_print()
01727 {
01728     printf("%04x", (unsigned)radio.readReg(REG_ADDR_FSK_CRCPOLY, 2));
01729 }
01730 
01731 bool Radio::gfsk_crcpoly_write(const char* txt)
01732 {
01733     unsigned v;
01734     if (sscanf(txt, "%x", &v) == 1)
01735         radio.writeReg(REG_ADDR_FSK_CRCPOLY, v, 2);
01736 
01737     return false;
01738 }
01739 
01740 const value_item_t Radio::gfsk_crcpoly_item = { _ITEM_VALUE, 5, gfsk_crcpoly_print, gfsk_crcpoly_write};
01741 
01742 void Radio::gfsk_whiteInit_print()
01743 {
01744     PktCtrl1a_t PktCtrl1a;
01745     PktCtrl1a.word = radio.readReg(REG_ADDR_FSK_PKTCTRL1A, 2);
01746     printf("%x", PktCtrl1a.bits.whit_init_val);
01747 }
01748 
01749 bool Radio::gfsk_whiteInit_write(const char* txt)
01750 {
01751     unsigned n;
01752     PktCtrl1a_t PktCtrl1a;
01753     PktCtrl1a.word = radio.readReg(REG_ADDR_FSK_PKTCTRL1A, 2);
01754     if (sscanf(txt, "%x", &n) == 1) {
01755         PktCtrl1a.bits.whit_init_val = n;
01756         radio.writeReg(REG_ADDR_FSK_PKTCTRL1A, PktCtrl1a.word, 2);
01757     }
01758     return false;
01759 }
01760 
01761 const value_item_t Radio::gfsk_whiteInit_item = { _ITEM_VALUE, 5, gfsk_whiteInit_print, gfsk_whiteInit_write};
01762 
01763 const menu_t Radio::gfsk_menu[] = {
01764     { {FIRST_CHIP_MENU_ROW+2,  1},    "bps:", &gfsk_bitrate_item, FLAG_MSGTYPE_ALL },
01765     { {FIRST_CHIP_MENU_ROW+2, 15},    "bt:",       &gfsk_bt_item, FLAG_MSGTYPE_ALL },
01766     { {FIRST_CHIP_MENU_ROW+2, 23},   "rxbw:",    &gfsk_rxbw_item, FLAG_MSGTYPE_ALL },
01767     { {FIRST_CHIP_MENU_ROW+2, 39},   "fdev:",    &gfsk_fdev_item, FLAG_MSGTYPE_ALL },
01768     { {FIRST_CHIP_MENU_ROW+2, 53},      NULL,  &gfsk_fixLen_item, FLAG_MSGTYPE_ALL },
01769 
01770     { {FIRST_CHIP_MENU_ROW+3,  1}, "PreambleLength:",  &gfsk_pblLen_item, FLAG_MSGTYPE_ALL },
01771     { {FIRST_CHIP_MENU_ROW+3, 21}, "PreambleDetectorLength:",  &gfsk_pblDetLen_item, FLAG_MSGTYPE_ALL },
01772     { {FIRST_CHIP_MENU_ROW+3, 51}, "SyncWordLength bits:",  &gfsk_swl_item, FLAG_MSGTYPE_ALL },
01773 
01774     { {FIRST_CHIP_MENU_ROW+4, 1}, "SyncWord:",  &gfsk_syncword_item, FLAG_MSGTYPE_ALL },
01775 
01776     { {FIRST_CHIP_MENU_ROW+5,  1}, "AddrComp:",   &gfsk_addrcomp_item, FLAG_MSGTYPE_ALL },
01777     { {FIRST_CHIP_MENU_ROW+5, 33}, "NodeAdrs:",   &gfsk_nodeadrs_item, FLAG_MSGTYPE_ALL },
01778     { {FIRST_CHIP_MENU_ROW+5, 47}, "broadcast:", &gfsk_broadcast_item, FLAG_MSGTYPE_ALL },
01779 
01780     { {FIRST_CHIP_MENU_ROW+6,   1}, "crcType:", &gfsk_crctype_item, FLAG_MSGTYPE_ALL },
01781     { {FIRST_CHIP_MENU_ROW+6,  21}, "crcInit:", &gfsk_crcinit_item, FLAG_MSGTYPE_ALL },
01782     { {FIRST_CHIP_MENU_ROW+6,  34}, "crcPoly:", &gfsk_crcpoly_item, FLAG_MSGTYPE_ALL },
01783 
01784     { {FIRST_CHIP_MENU_ROW+7,  1},          NULL, &gfsk_white_item, FLAG_MSGTYPE_ALL },
01785     { {FIRST_CHIP_MENU_ROW+7,  12}, "lfsr init:", &gfsk_whiteInit_item, FLAG_MSGTYPE_ALL },
01786 //12345678901234567890123456789012
01787 
01788     { {0, 0}, NULL, NULL }
01789 };
01790 
01791 const menu_t* Radio::get_modem_sub_menu() { return NULL; }
01792 
01793 const menu_t* Radio::get_modem_menu()
01794 {
01795     pktType = radio.getPacketType();
01796 
01797     if (pktType == PACKET_TYPE_LORA) {
01798         return lora_menu;
01799     } else if (pktType == PACKET_TYPE_GFSK) {
01800         return gfsk_menu;
01801     }
01802 
01803     return NULL;
01804 }
01805 
01806 unsigned Radio::read_register(unsigned addr)
01807 {
01808     return radio.readReg(addr, 1);
01809 }
01810 
01811 void Radio::write_register(unsigned addr, unsigned val)
01812 {
01813     radio.writeReg(addr, val, 1);
01814 }
01815 
01816 #endif /* ..SX126x_H */
01817