NAMote72 Utility Application – Serial Terminal Monitor control for NAMote72 (note: this application replaces the previous na_mote1 test code application)

Dependencies:   SX127x lib_gps lib_mma8451q lib_mpl3115a2 lib_sx9500 mbed

Fork of na_mote1 by wayne roberts

See wiki Page for a detailed

This is a link to the wiki page

Revision:
0:9c2b09ecb20f
Child:
1:b13a15a34c3f
diff -r 000000000000 -r 9c2b09ecb20f main.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp	Wed Oct 01 20:41:16 2014 +0000
@@ -0,0 +1,1549 @@
+#include "sx127x_lora.h"
+#include "sx127x_fsk.h"
+
+/*
+ * http://mbed.org/handbook/mbed-FRDM-KL25Z
+ */
+
+//DigitalOut green(LED_GREEN);
+
+Serial pc(USBTX, USBRX);
+
+uint8_t tx_cnt;
+char pcbuf[64];
+
+typedef enum {
+    APP_NONE = 0,
+    APP_CHAT
+} app_e;
+
+app_e app = APP_NONE;
+
+
+const uint32_t frfs[] = {   /* frequency hopping table */
+    MHZ_TO_FRF(903.0),
+    MHZ_TO_FRF(904.0),
+    MHZ_TO_FRF(905.0),
+    MHZ_TO_FRF(906.0),
+    MHZ_TO_FRF(907.0),
+    MHZ_TO_FRF(908.0),
+    MHZ_TO_FRF(909.0),
+    MHZ_TO_FRF(910.0),
+    MHZ_TO_FRF(911.0),
+    MHZ_TO_FRF(912.0),
+    MHZ_TO_FRF(913.0),
+    MHZ_TO_FRF(914.0),
+    MHZ_TO_FRF(915.0)
+};
+
+#define FSK_LARGE_PKT_THRESHOLD  0x3f
+
+/******************************************************************************/
+#define RADIO_RESET              PC_2 //NorAm_Mote Reset_sx
+#define RADIO_MOSI               PB_15 //NorAm_Mote SPI2 Mosi
+#define RADIO_MISO               PB_14 //NorAm_Mote SPI2 Miso
+#define RADIO_SCLK               PB_13 //NorAm_Mote  SPI2 Clk
+#define RADIO_NSS                PB_12 //NorAm_Mote SPI2 Nss
+
+#define RADIO_DIO_0              PC_6 //NorAm_Mote DIO0 
+#define RADIO_DIO_1              PC_10 //NorAm_Mote DIO1 
+#define RADIO_DIO_2              PC_8 //NorAm_Mote DIO2 
+#define RADIO_DIO_3              PB_4 //NorAm_Mote DIO3 
+#define RADIO_DIO_4              PB_5 //NorAm_Mote DIO4 
+#define RADIO_DIO_5              PB_6 //NorAm_Mote DIO5
+
+#define RFSW1                    PC_4 //NorAm_Mote RFSwitch_CNTR_1
+#define RFSW2                    PC_13 //NorAm_Mote RFSwitch_CNTR_2
+
+//  pin:       3     8     1      7    10    12     5   20    18
+//                 mosi,       miso,       sclk,        cs,         rst,        dio0,        dio1, fctx, fcps 
+//SX127x radio(D11,   D12, D13,    D10,  D7,   D2,   D3,  D8,  D9); // nucleo-L152RE
+SX127x radio(RADIO_MOSI, RADIO_MISO, RADIO_SCLK, RADIO_NSS, RADIO_RESET, RADIO_DIO_0, RADIO_DIO_1, RFSW1, RFSW2); // NA-mote
+SX127x_fsk fsk(radio);
+SX127x_lora lora(radio);
+
+void printLoraIrqs_(bool clear)
+{
+    //in radio class -- RegIrqFlags_t RegIrqFlags;
+
+    //already read RegIrqFlags.octet = radio.read_reg(REG_LR_IRQFLAGS);
+    printf("\r\nIrqFlags:");
+    if (lora.RegIrqFlags.bits.CadDetected)
+        printf("CadDetected ");
+    if (lora.RegIrqFlags.bits.FhssChangeChannel) {
+        //radio.RegHopChannel.octet = radio.read_reg(REG_LR_HOPCHANNEL);
+        printf("FhssChangeChannel:%d ", lora.RegHopChannel.bits.FhssPresentChannel);
+    }
+    if (lora.RegIrqFlags.bits.CadDone)
+        printf("CadDone ");
+    if (lora.RegIrqFlags.bits.TxDone)
+        printf("TxDone ");
+    if (lora.RegIrqFlags.bits.ValidHeader)
+        printf("ValidHeader ");
+    if (lora.RegIrqFlags.bits.PayloadCrcError)
+        printf("PayloadCrcError ");
+    if (lora.RegIrqFlags.bits.RxDone)
+        printf("RxDone ");  
+    if (lora.RegIrqFlags.bits.RxTimeout)
+        printf("RxTimeout ");
+
+    printf("\r\n");
+
+    if (clear)
+        radio.write_reg(REG_LR_IRQFLAGS, lora.RegIrqFlags.octet);
+
+}
+
+void lora_printCodingRate(bool from_rx)
+{
+    uint8_t d = lora.getCodingRate(from_rx);
+    printf("CodingRate:");
+    switch (d) {
+        case 1: printf("4/5 "); break;
+        case 2: printf("4/6 "); break;
+        case 3: printf("4/7 "); break;
+        case 4: printf("4/8 "); break;
+        default:
+            printf("%d ", d);
+            break;
+    }
+}
+
+void lora_printHeaderMode()
+{
+    if (lora.getHeaderMode())
+        printf("implicit ");
+    else
+        printf("explicit ");
+}
+
+void lora_printBw()
+{
+    uint8_t bw = lora.getBw();
+    
+    printf("Bw:");
+    if (radio.type == SX1276) {
+        switch (lora.RegModemConfig.sx1276bits.Bw) {
+            case 0: printf("7.8KHz "); break;
+            case 1: printf("10.4KHz "); break;
+            case 2: printf("15.6KHz "); break;
+            case 3: printf("20.8KHz "); break;
+            case 4: printf("31.25KHz "); break;
+            case 5: printf("41.7KHz "); break;
+            case 6: printf("62.5KHz "); break;
+            case 7: printf("125KHz "); break;
+            case 8: printf("250KHz "); break;
+            case 9: printf("500KHz "); break;
+            default: printf("%x ", lora.RegModemConfig.sx1276bits.Bw); break;
+        }
+    } else if (radio.type == SX1272) {
+        switch (lora.RegModemConfig.sx1272bits.Bw) {
+            case 0: printf("125KHz "); break;
+            case 1: printf("250KHz "); break;
+            case 2: printf("500KHz "); break;
+            case 3: printf("11b "); break;
+        }
+    }
+}
+
+void lora_printAllBw()
+{
+    int i, s;
+    
+    if (radio.type == SX1276) {
+        s = lora.RegModemConfig.sx1276bits.Bw;    
+        for (i = 0; i < 10; i++ ) {
+            lora.RegModemConfig.sx1276bits.Bw = i;
+            printf("%d ", i);
+            lora_printBw();
+            printf("\r\n");
+        }
+        lora.RegModemConfig.sx1276bits.Bw = s;
+    } else if (radio.type == SX1272) {
+        s = lora.RegModemConfig.sx1272bits.Bw;    
+        for (i = 0; i < 3; i++ ) {
+            lora.RegModemConfig.sx1272bits.Bw = i;
+            printf("%d ", i);
+            lora_printBw();
+            printf("\r\n");
+        }
+        lora.RegModemConfig.sx1272bits.Bw = s;    
+    }
+}
+
+void lora_printSf()
+{
+    // spreading factor same between sx127[26]
+    printf("sf:%d ", lora.getSf());
+}
+
+void lora_printRxPayloadCrcOn()
+{
+    bool on = lora.getRxPayloadCrcOn();
+    //printf("RxPayloadCrcOn:%s ", on ? "on" : "off");
+    if (on)
+        printf("RxPayloadCrcOn:1 = Tx CRC Enabled\r\n");
+    else
+        printf("RxPayloadCrcOn:1 = no Tx CRC\r\n");
+}
+
+void lora_printTxContinuousMode()
+{
+    printf("TxContinuousMode:%d ", lora.RegModemConfig2.sx1276bits.TxContinuousMode);    // same for sx1272 and sx1276
+}
+
+void lora_printAgcAutoOn()
+{
+    printf("AgcAutoOn:%d", lora.getAgcAutoOn());
+}
+
+void lora_print_dio()
+{
+    radio.RegDioMapping2.octet = radio.read_reg(REG_DIOMAPPING2);
+    printf("DIO5:");
+    switch (radio.RegDioMapping2.bits.Dio5Mapping) {
+        case 0: printf("ModeReady"); break;
+        case 1: printf("ClkOut"); break;
+        case 2: printf("ClkOut"); break;
+    }
+    printf(" DIO4:");
+    switch (radio.RegDioMapping2.bits.Dio4Mapping) {
+        case 0: printf("CadDetected"); break;
+        case 1: printf("PllLock"); break;
+        case 2: printf("PllLock"); break;
+    }    
+    radio.RegDioMapping1.octet = radio.read_reg(REG_DIOMAPPING1);
+    printf(" DIO3:");
+    switch (radio.RegDioMapping1.bits.Dio3Mapping) {
+        case 0: printf("CadDone"); break;
+        case 1: printf("ValidHeader"); break;
+        case 2: printf("PayloadCrcError"); break;
+    }    
+    printf(" DIO2:");
+    switch (radio.RegDioMapping1.bits.Dio2Mapping) {
+        case 0:
+        case 1:
+        case 2:
+            printf("FhssChangeChannel");
+            break;
+    }    
+    printf(" DIO1:");
+    switch (radio.RegDioMapping1.bits.Dio1Mapping) {
+        case 0: printf("RxTimeout"); break;
+        case 1: printf("FhssChangeChannel"); break;
+        case 2: printf("CadDetected"); break;
+    }    
+    printf(" DIO0:");
+    switch (radio.RegDioMapping1.bits.Dio0Mapping) {
+        case 0: printf("RxDone"); break;
+        case 1: printf("TxDone"); break;
+        case 2: printf("CadDone"); break;
+    }    
+    
+    printf("\r\n"); 
+}
+
+void fsk_print_dio()
+{
+    radio.RegDioMapping2.octet = radio.read_reg(REG_DIOMAPPING2);
+    
+    printf("DIO5:");
+    switch (radio.RegDioMapping2.bits.Dio5Mapping) {
+        case 0: printf("ClkOut"); break;
+        case 1: printf("PllLock"); break;
+        case 2:
+            if (fsk.RegPktConfig2.bits.DataModePacket)
+                printf("data");
+            else {
+                if (radio.RegDioMapping2.bits.MapPreambleDetect)
+                    printf("preamble");
+                else
+                    printf("rssi");
+            }
+            break;
+        case 3: printf("ModeReady"); break;
+    }
+    
+    printf(" DIO4:");
+    switch (radio.RegDioMapping2.bits.Dio4Mapping) {
+        case 0: printf("temp/eol"); break;
+        case 1: printf("PllLock"); break;
+        case 2: printf("TimeOut"); break;
+        case 3:
+            if (fsk.RegPktConfig2.bits.DataModePacket) {
+                if (radio.RegDioMapping2.bits.MapPreambleDetect)
+                    printf("preamble");
+                else
+                    printf("rssi");
+            } else
+                printf("ModeReady");
+            break;
+    }
+    
+    radio.RegDioMapping1.octet = radio.read_reg(REG_DIOMAPPING1);
+    
+    printf(" DIO3:");
+    switch (radio.RegDioMapping1.bits.Dio3Mapping) {
+        case 0: printf("Timeout"); break;
+        case 1:
+            if (radio.RegDioMapping2.bits.MapPreambleDetect)
+                printf("preamble");
+            else
+                printf("rssi");
+            break;
+        case 2: printf("?automode_status?"); break;
+        case 3: printf("TempChange/LowBat"); break;
+    }
+    
+    printf(" DIO2:");
+    if (fsk.RegPktConfig2.bits.DataModePacket) {
+        switch (radio.RegDioMapping1.bits.Dio2Mapping) {
+            case 0: printf("FifoFull"); break;
+            case 1: printf("RxReady"); break;
+            case 2: printf("FifoFull/rx-timeout"); break;
+            case 3: printf("FifoFull/rx-syncadrs"); break;
+        }
+    } else {
+        printf("Data");
+    }
+    
+    printf(" DIO1:");
+    if (fsk.RegPktConfig2.bits.DataModePacket) {
+        switch (radio.RegDioMapping1.bits.Dio1Mapping) {
+            case 0: printf("FifoThresh"); break;
+            case 1: printf("FifoEmpty"); break;
+            case 2: printf("FifoFull"); break;
+            case 3: printf("-3-"); break;
+        }
+    } else {
+        switch (radio.RegDioMapping1.bits.Dio1Mapping) {
+            case 0: printf("Dclk"); break;
+            case 1:
+                if (radio.RegDioMapping2.bits.MapPreambleDetect)
+                    printf("preamble");
+                else
+                    printf("rssi");
+                break;
+            case 2: printf("-2-"); break;
+            case 3: printf("-3-"); break;
+        }
+    }
+    
+    printf(" DIO0:");
+    if (fsk.RegPktConfig2.bits.DataModePacket) {
+        switch (radio.RegDioMapping1.bits.Dio0Mapping) {
+            case 0: printf("PayloadReady/PacketSent"); break;
+            case 1: printf("CrcOk"); break;
+            case 2: printf("-2-"); break;
+            case 3: printf("TempChange/LowBat"); break;
+        }
+    } else {
+        switch (radio.RegDioMapping1.bits.Dio0Mapping) {
+            case 0: printf("SyncAdrs/TxReady"); break;
+            case 1:
+                if (radio.RegDioMapping2.bits.MapPreambleDetect)
+                    printf("preamble");
+                else
+                    printf("rssi");
+                break;
+            case 2: printf("RxReady"); break;
+            case 3: printf("-3-"); break;
+        }
+    }
+    printf("\r\n"); 
+}
+
+void lora_print_status()
+{
+    uint8_t d;
+    
+    if (radio.type == SX1276)
+        printf("\r\nSX1276 ");
+    else if (radio.type == SX1272)
+        printf("\r\nSX1272 ");
+    
+    radio.RegOpMode.octet = radio.read_reg(REG_OPMODE);
+    if (!radio.RegOpMode.bits.LongRangeMode) {
+        printf("FSK\r\n");
+        return;
+    }
+    
+    lora_print_dio();
+    printf("LoRa ");
+    
+    // printing LoRa registers at 0x0d -> 0x3f
+
+    lora.RegModemConfig.octet = radio.read_reg(REG_LR_MODEMCONFIG);
+    lora.RegModemConfig2.octet = radio.read_reg(REG_LR_MODEMCONFIG2);
+
+    lora_printCodingRate(false); // false: transmitted coding rate
+    lora_printHeaderMode();
+    lora_printBw();
+    lora_printSf();
+    lora_printRxPayloadCrcOn();
+    // RegModemStat
+    printf("ModemStat:0x%02x\r\n", radio.read_reg(REG_LR_MODEMSTAT));
+
+    // fifo ptrs:
+    lora.RegPayloadLength = radio.read_reg(REG_LR_PAYLOADLENGTH);
+    lora.RegRxMaxPayloadLength = radio.read_reg(REG_LR_RX_MAX_PAYLOADLENGTH);
+    printf("fifoptr=0x%02x txbase=0x%02x rxbase=0x%02x payloadLength=0x%02x maxlen=0x%02x",
+        radio.read_reg(REG_LR_FIFOADDRPTR),
+        radio.read_reg(REG_LR_FIFOTXBASEADDR),
+        radio.read_reg(REG_LR_FIFORXBASEADDR),
+        lora.RegPayloadLength,
+        lora.RegRxMaxPayloadLength
+    );
+
+    lora.RegIrqFlags.octet = radio.read_reg(REG_LR_IRQFLAGS);
+    printLoraIrqs_(false);
+
+    lora.RegHopPeriod = radio.read_reg(REG_LR_HOPPERIOD);
+    if (lora.RegHopPeriod != 0) {
+        printf("\r\nHopPeriod:0x%02x\r\n", lora.RegHopPeriod);
+    }
+
+    printf("SymbTimeout:0x%03x ", radio.read_u16(REG_LR_MODEMCONFIG2) & 0x3ff);
+
+    lora.RegPreamble = radio.read_u16(REG_LR_PREAMBLEMSB);
+    printf("PreambleLength:%d ", lora.RegPreamble);
+
+    if (radio.RegOpMode.bits.Mode == RF_OPMODE_RECEIVER || radio.RegOpMode.bits.Mode == RF_OPMODE_RECEIVER_SINGLE) {
+        d = radio.read_reg(REG_LR_RSSIVALUE);
+        printf("rssi:%ddBm ", d-120);
+    }
+
+    lora_printTxContinuousMode();
+
+    printf("\r\n");
+    lora_printAgcAutoOn();
+    if (radio.type == SX1272) {
+        printf(" LowDataRateOptimize:%d\r\n", lora.RegModemConfig.sx1272bits.LowDataRateOptimize);
+    }
+
+    printf("\r\nHeaderCount:%d PacketCount:%d, ",
+        radio.read_u16(REG_LR_RXHEADERCNTVALUE_MSB), radio.read_u16(REG_LR_RXPACKETCNTVALUE_MSB));
+
+    printf("Lora detection threshold:%02x\r\n", radio.read_reg(REG_LR_DETECTION_THRESHOLD));
+    lora.RegTest31.octet = radio.read_reg(REG_LR_TEST31);
+    printf("detect_trig_same_peaks_nb:%d\r\n", lora.RegTest31.bits.detect_trig_same_peaks_nb);
+
+    if (radio.type == SX1272) {
+        lora.RegModemConfig.octet = radio.read_reg(REG_LR_MODEMCONFIG);
+        printf("LowDataRateOptimize:%d\r\n", lora.RegModemConfig.sx1272bits.LowDataRateOptimize);
+    } else if (radio.type == SX1276) {
+        lora.RegModemConfig3.octet = radio.read_reg(REG_LR_MODEMCONFIG3);
+        printf("LowDataRateOptimize:%d\r\n", lora.RegModemConfig3.sx1276bits.LowDataRateOptimize);        
+    }
+    
+    printf("\r\n");
+    //printf("A %02x\r\n", radio.RegModemConfig2.octet);
+}
+
+uint16_t
+fsk_get_PayloadLength(void)
+{
+    fsk.RegPktConfig2.word = radio.read_u16(REG_FSK_PACKETCONFIG2);
+
+    return fsk.RegPktConfig2.bits.PayloadLength;
+}
+
+void fsk_printAddressFiltering()
+{
+    uint8_t FSKRegNodeAdrs, FSKRegBroadcastAdrs;
+    
+    printf(" AddressFiltering:");
+    switch (fsk.RegPktConfig1.bits.AddressFiltering) {
+        case 0: printf("off"); break;
+        case 1: // NodeAddress
+            FSKRegNodeAdrs = radio.read_reg(REG_FSK_NODEADRS);
+            printf("NodeAdrs:%02x\n", FSKRegNodeAdrs);
+            break;
+        case 2: // NodeAddress & BroadcastAddress
+            FSKRegNodeAdrs = radio.read_reg(REG_FSK_NODEADRS);
+            printf("NodeAdrs:%02x ", FSKRegNodeAdrs);
+            FSKRegBroadcastAdrs = radio.read_reg(REG_FSK_BROADCASTADRS);
+            printf("BroadcastAdrs:%02x\n", FSKRegBroadcastAdrs );
+            break;
+        default:
+            printf("%d", fsk.RegPktConfig1.bits.AddressFiltering);
+            break;
+    }
+}
+
+void fsk_print_IrqFlags2()
+{
+    RegIrqFlags2_t RegIrqFlags2;
+    
+    printf("IrqFlags2: ");
+    RegIrqFlags2.octet = radio.read_reg(REG_FSK_IRQFLAGS2);
+    if (RegIrqFlags2.bits.FifoFull)
+        printf("FifoFull ");
+    if (RegIrqFlags2.bits.FifoEmpty)
+        printf("FifoEmpty ");
+    if (RegIrqFlags2.bits.FifoLevel)
+        printf("FifoLevel ");
+    if (RegIrqFlags2.bits.FifoOverrun)
+        printf("FifoOverrun ");
+    if (RegIrqFlags2.bits.PacketSent)
+        printf("PacketSent ");
+    if (RegIrqFlags2.bits.PayloadReady)
+        printf("PayloadReady ");
+    if (RegIrqFlags2.bits.CrcOk)
+        printf("CrcOk ");
+    if (RegIrqFlags2.bits.LowBat)
+        printf("LowBat ");
+    printf("\r\n");
+}
+
+void
+fsk_print_status()
+{
+    //uint16_t s;
+    RegIrqFlags1_t RegIrqFlags1;
+    
+    if (radio.RegOpMode.bits.LongRangeMode) {
+        printf("LoRa\r\n");
+        return;
+    }
+    
+    if (radio.RegOpMode.bits.ModulationType == 0) {
+        printf("FSK ");
+        switch (radio.RegOpMode.bits.ModulationShaping) {
+            case 1: printf("BT1.0 "); break;
+            case 2: printf("BT0.5 "); break;
+            case 3: printf("BT0.3 "); break;
+        }
+    } else if (radio.RegOpMode.bits.ModulationType == 1) {
+        printf("OOK ");
+    }
+
+    printf("%dbps fdev:%dHz\r\n", fsk.get_bitrate(), fsk.get_tx_fdev_hz());    
+    
+    fsk.RegPktConfig2.word = radio.read_u16(REG_FSK_PACKETCONFIG2);
+    
+    fsk_print_dio();
+    
+    printf("rxbw:%dHz ", fsk.get_rx_bw_hz(REG_FSK_RXBW));
+    printf("afcbw:%dHz\r\n", fsk.get_rx_bw_hz(REG_FSK_AFCBW));
+
+    fsk.RegRssiConfig.octet = radio.read_reg(REG_FSK_RSSICONFIG);
+    printf("RssiOffset:%ddB smoothing:%dsamples\r\n", fsk.RegRssiConfig.bits.RssiOffset, 1 << (fsk.RegRssiConfig.bits.RssiSmoothing+1));
+
+
+    fsk.RegSyncConfig.octet = radio.read_reg(REG_FSK_SYNCCONFIG);
+
+    if (fsk.RegPktConfig2.bits.DataModePacket) {
+        uint16_t len;
+        /* packet mode */
+        len = fsk_get_PayloadLength();
+        printf("packet RegPayloadLength:0x%03x ", len);
+
+        if (fsk.RegPktConfig2.bits.BeaconOn)
+            printf("BeaconOn ");
+
+        fsk.RegFifoThreshold.octet = radio.read_reg(REG_FSK_FIFOTHRESH);
+        printf("FifoThreshold:%d TxStartCondition:", fsk.RegFifoThreshold.bits.FifoThreshold);
+        if (fsk.RegFifoThreshold.bits.TxStartCondition)
+            printf("!FifoEmpty");
+        else
+            printf("FifoLevel");
+
+        printf("\r\nAutoRestartRxMode:");
+        switch (fsk.RegSyncConfig.bits.AutoRestartRxMode) {
+            case 0: printf("off "); break;
+            case 1: printf("no-pll-wait "); break;
+            case 2: printf("pll-wait "); break;
+            case 3: printf("3 "); break;
+        }
+        //...todo
+
+        printf("PreambleSize:%d ", radio.read_u16(REG_FSK_PREAMBLEMSB));
+
+        fsk.RegOokPeak.octet = radio.read_reg(REG_FSK_OOKPEAK);
+        if (fsk.RegOokPeak.bits.barker_en)
+            printf("barker ");
+        if (!fsk.RegOokPeak.bits.BitSyncOn)
+            printf("BitSyncOff ");
+        //...todo
+
+        fsk.RegPktConfig1.octet = radio.read_reg(REG_FSK_PACKETCONFIG1);
+        if (fsk.RegPktConfig1.bits.PacketFormatVariable)
+            printf("variable");
+        else
+            printf("fixed");
+        printf("-length\r\ncrc");
+        if (fsk.RegPktConfig1.bits.CrcOn) {
+            printf("On");
+        } else
+            printf("Off");
+        printf(" crctype:");
+        if (fsk.RegPktConfig1.bits.CrCWhiteningType)
+            printf("IBM");
+        else
+            printf("CCITT");
+        printf(" dcFree:");
+        switch (fsk.RegPktConfig1.bits.DcFree) {
+            case 0: printf("none "); break;
+            case 1: printf("Manchester "); break;
+            case 2: printf("Whitening "); break;
+            case 3: printf("reserved "); break;
+        }
+        fsk_printAddressFiltering();
+
+        printf("\r\n");
+        fsk_print_IrqFlags2();
+    } else {
+        /* continuous mode */
+        printf("continuous ");
+    }
+
+    fsk.RegPreambleDetect.octet = radio.read_reg(REG_FSK_PREAMBLEDETECT);
+    printf("PreambleDetect:");
+    if (fsk.RegPreambleDetect.bits.PreambleDetectorOn) {
+        printf("size=%d,tol=%d ",
+            fsk.RegPreambleDetect.bits.PreambleDetectorSize,
+            fsk.RegPreambleDetect.bits.PreambleDetectorTol);
+    } else
+        printf("Off ");
+
+    printf(" syncsize:%d ", fsk.RegSyncConfig.bits.SyncSize);
+    printf(" : %02x ", radio.read_reg(REG_FSK_SYNCVALUE1));
+    printf("%02x ", radio.read_reg(REG_FSK_SYNCVALUE2));
+    printf("%02x ", radio.read_reg(REG_FSK_SYNCVALUE3));
+    printf("%02x ", radio.read_reg(REG_FSK_SYNCVALUE4));
+    printf("\r\n");   // end sync config
+
+    fsk.RegAfcFei.octet = radio.read_reg(REG_FSK_AFCFEI);
+    printf("afcAutoClear:");
+    if (fsk.RegAfcFei.bits.AfcAutoClearOn)
+        printf("On");
+    else
+        printf("OFF");
+    printf(" afc:%dHz ", (int)(FREQ_STEP_HZ * radio.read_s16(REG_FSK_AFCMSB)));
+
+    printf("fei:%dHz\r\n", (int)(FREQ_STEP_HZ * radio.read_s16(REG_FSK_FEIMSB)));
+
+    fsk.RegRxConfig.octet = radio.read_reg(REG_FSK_RXCONFIG);
+    printf("RxTrigger:");
+    switch (fsk.RegRxConfig.bits.RxTrigger) {
+        case 0: printf("none "); break;
+        case 1: printf("rssi "); break;
+        case 6: printf("preamble "); break;
+        case 7: printf("both "); break;
+        default: printf("-%d- ", fsk.RegRxConfig.bits.RxTrigger); break;
+    }
+    printf("AfcAuto:");
+    if (fsk.RegRxConfig.bits.AfcAutoOn)
+        printf("On ");
+    else
+        printf("OFF ");
+    if (!fsk.RegRxConfig.bits.AgcAutoOn) {
+        radio.RegLna.octet = radio.read_reg(REG_LNA);
+        printf("AgcAutoOff:G%d ", radio.RegLna.bits.LnaGain);
+    }
+
+    fsk.RegTimerResol.octet = radio.read_reg(REG_FSK_TIMERRESOL);
+    if (fsk.RegTimerResol.bits.hlm_started)
+        printf("hlm_started ");
+    else
+        printf("hlm_stopped ");
+
+    fsk.RegRssiThresh = radio.read_reg(REG_FSK_RSSITHRESH);
+    printf("rssiThreshold:-%.1f@%02x ", fsk.RegRssiThresh / 2.0, REG_FSK_RSSITHRESH);
+
+    radio.RegOpMode.octet = radio.read_reg(REG_OPMODE);
+    if (radio.RegOpMode.bits.Mode == RF_OPMODE_RECEIVER ||
+        radio.RegOpMode.bits.Mode == RF_OPMODE_SYNTHESIZER_RX)
+    {
+        printf("rssi:-%.1f ", radio.read_reg(REG_FSK_RSSIVALUE) / 2.0);
+    }
+
+    fsk.RegSeqConfig1.octet = radio.read_reg(REG_FSK_SEQCONFIG1);
+    printf("\r\nsequencer: ");
+    printf("FromStart:");
+    switch (fsk.RegSeqConfig1.bits.FromStart) {
+        case 0:
+            printf("lowPowerSelection-");
+            if (fsk.RegSeqConfig1.bits.LowPowerSelection)
+                printf("idle");
+            else
+                printf("sequencerOff");
+            break;
+        case 1: printf("rx"); break;
+        case 2: printf("tx"); break;
+        case 3: printf("tx on fifolevel"); break;
+    }
+    printf(" lowPowerSelection:");
+    if (fsk.RegSeqConfig1.bits.LowPowerSelection)
+        printf("idle");
+    else
+        printf("SequencerOff");
+    if (fsk.RegSeqConfig1.bits.FromStart != 0 && 
+        fsk.RegSeqConfig1.bits.LowPowerSelection != 0)
+    {   // if sequencer enabled:
+        printf("\r\nsequencer: IdleMode:");
+        if (fsk.RegSeqConfig1.bits.IdleMode)
+            printf("Sleep");
+        else
+            printf("standby");
+        printf("\r\nsequencer: FromIdle to:");
+        if (fsk.RegSeqConfig1.bits.FromIdle)
+            printf("rx");
+        else
+            printf("tx");
+        printf("\r\nsequencer: FromTransmit to:");
+        if (fsk.RegSeqConfig1.bits.FromTransmit)
+            printf("rx-on-PacketSent");
+        else {
+            printf("lowPowerSelection-");
+            if (fsk.RegSeqConfig1.bits.LowPowerSelection)
+                printf("idle");
+            else
+                printf("SequencerOff");
+            printf("-on-PacketSent");
+        }
+        fsk.RegSeqConfig2.octet = radio.read_reg(REG_FSK_SEQCONFIG2);
+        printf("\r\nsequencer: FromReceive:");
+        switch (fsk.RegSeqConfig2.bits.FromReceive) {
+            case 1: printf("PacketRecevied on PayloadReady"); break;
+            case 2: 
+                printf("lowPowerSelection-");
+                if (fsk.RegSeqConfig1.bits.LowPowerSelection)
+                    printf("idle");
+                else
+                    printf("SequencerOff");
+                printf("-on-payloadReady");
+                break;
+            case 3: printf("PacketRecevied-on-CrcOk"); break;
+            case 4: printf("SequencerOff-on-Rssi"); break;
+            case 5: printf("SequencerOff-on-SyncAddress"); break;
+            case 6: printf("SequencerOff-PreambleDetect"); break;
+            default: printf("-%d-", fsk.RegSeqConfig2.bits.FromReceive); break;
+        }
+        printf("\r\nsequencer: FromRxTimeout:");
+        switch (fsk.RegSeqConfig2.bits.FromRxTimeout) {
+            case 0: printf("rx"); break;
+            case 1: printf("tx"); break;
+            case 2:
+                printf("lowPowerSelection-");
+                if (fsk.RegSeqConfig1.bits.LowPowerSelection)
+                    printf("idle");
+                else
+                    printf("SequencerOff");
+                break;
+            case 3: printf("SequencerOff"); break;
+        }
+        printf("\r\nsequencer: FromPacketReceived to:");
+        switch (fsk.RegSeqConfig2.bits.FromPacketReceived) {
+            case 0: printf("SequencerOff"); break;
+            case 1: printf("tx on FifoEmpty"); break;
+            case 2:
+                printf("lowPowerSelection-");
+                if (fsk.RegSeqConfig1.bits.LowPowerSelection)
+                printf("idle");
+                else
+                printf("sequencerOff");
+                break;
+            case 3: printf("rx via fs"); break;
+            case 4: printf("rx"); break;
+        }
+
+        fsk.RegTimerResol.octet = radio.read_reg(REG_FSK_TIMERRESOL);
+        printf("\r\nsequencer: timer1:");
+        switch (fsk.RegTimerResol.bits.timer1_resol) {
+            case 0: printf("off"); break;
+            case 1: printf("%dus", radio.read_reg(REG_FSK_TIMER1COEF) * 64); break;
+            case 2: printf("%.1fms", radio.read_reg(REG_FSK_TIMER1COEF) * 4.1); break;
+            case 3: printf("%.1fs", radio.read_reg(REG_FSK_TIMER1COEF) * 0.262); break;
+        }
+
+        printf(" timer2:");
+        switch (fsk.RegTimerResol.bits.timer2_resol) {
+            case 0: printf("off"); break;
+            case 1: printf("%dus", radio.read_reg(REG_FSK_TIMER2COEF) * 64); break;
+            case 2: printf("%.1fms", radio.read_reg(REG_FSK_TIMER2COEF) * 4.1); break;
+            case 3: printf("%.1fs", radio.read_reg(REG_FSK_TIMER2COEF) * 0.262); break;
+        }
+    } // ..if sequencer enabled
+
+    printf("\r\nIrqFlags1:");
+    RegIrqFlags1.octet = radio.read_reg(REG_FSK_IRQFLAGS1);
+    if (RegIrqFlags1.bits.ModeReady)
+        printf("ModeReady ");
+    if (RegIrqFlags1.bits.RxReady)
+        printf("RxReady ");
+    if (RegIrqFlags1.bits.TxReady)
+        printf("TxReady ");
+    if (RegIrqFlags1.bits.PllLock)
+        printf("PllLock ");
+    if (RegIrqFlags1.bits.Rssi)
+        printf("Rssi ");
+    if (RegIrqFlags1.bits.Timeout)
+        printf("Timeout ");
+    if (RegIrqFlags1.bits.PreambleDetect)
+        printf("PreambleDetect ");
+    if (RegIrqFlags1.bits.SyncAddressMatch)
+        printf("SyncAddressMatch ");
+
+    printf("\r\n");
+
+/* TODO    if (!SX1272FSK->RegPktConfig1.bits.PacketFormatVariable) { // if fixed-length packet format:
+        s = fsk_get_PayloadLength();
+        if (s > FSK_LARGE_PKT_THRESHOLD)
+            flags.fifo_flow_ctl = 1;
+        else
+            flags.fifo_flow_ctl = 0;
+    }*/
+
+    fsk.RegImageCal.octet = radio.read_reg(REG_FSK_IMAGECAL);
+    if (fsk.RegImageCal.bits.TempMonitorOff) {
+        printf("TempMonitorOff[\r0m\n");
+    } else {
+        printf("TempThreshold:");
+        switch (fsk.RegImageCal.bits.TempThreshold) {
+            case 0: printf("5C"); break;
+            case 1: printf("10C"); break;
+            case 2: printf("15C"); break;
+            case 3: printf("20C"); break;
+        }
+        printf("\r\n");
+    }
+    if (fsk.RegImageCal.bits.ImageCalRunning)
+        printf("ImageCalRunning[\r0m\n");
+
+/*    printf("flags.fifo_flow_ctl:%d pktidx:%d rx_pktlen:%d", flags.fifo_flow_ctl, pktidx, rx_pktlen);
+    printf("\n");
+
+    //printf("DIO0_PIN:%d\n", digitalRead(DIO0_PIN));
+    printf("pkt_buf_len=%d remaining=%d\n", pk*/
+}
+
+void printOpMode()
+{
+    radio.RegOpMode.octet = radio.read_reg(REG_OPMODE);
+    switch (radio.RegOpMode.bits.Mode) {
+        case RF_OPMODE_SLEEP: printf("sleep"); break;
+        case RF_OPMODE_STANDBY: printf("stby"); break;
+        case RF_OPMODE_SYNTHESIZER_TX: printf("fstx"); break;
+        case RF_OPMODE_TRANSMITTER: printf("tx"); break;
+        case RF_OPMODE_SYNTHESIZER_RX: printf("fsrx"); break;
+        case RF_OPMODE_RECEIVER: printf("rx"); break;
+        case 6:
+            if (radio.RegOpMode.bits.LongRangeMode)
+                printf("rxs");
+            else
+                printf("-6-");
+            break;  // todo: different lora/fsk
+        case 7:
+            if (radio.RegOpMode.bits.LongRangeMode)
+                printf("cad");
+            else
+                printf("-7-");
+            break;  // todo: different lora/fsk
+    }
+}
+
+void
+printPa()
+{
+    radio.RegPaConfig.octet = radio.read_reg(REG_PACONFIG);
+    if (radio.RegPaConfig.bits.PaSelect) {
+        float output_dBm = 17 - (15-radio.RegPaConfig.bits.OutputPower);
+        printf(" PABOOST OutputPower=%.1fdBm", output_dBm);
+    } else {
+        float pmax = (0.6*radio.RegPaConfig.bits.MaxPower) + 10.8;
+        float output_dBm = pmax - (15-radio.RegPaConfig.bits.OutputPower);
+        printf(" RFO pmax=%.1fdBm OutputPower=%.1fdBm", pmax, output_dBm);
+    }
+}
+
+void /* things always present, whether lora or fsk */
+common_print_status()
+{
+    printf("version:0x%02x %.3fMHz ", radio.read_reg(REG_VERSION), radio.get_frf_MHz());
+    printOpMode();
+
+    printPa();
+
+    radio.RegOcp.octet = radio.read_reg(REG_OCP);
+    if (radio.RegOcp.bits.OcpOn) {
+        int imax = 0;
+        if (radio.RegOcp.bits.OcpTrim < 16)
+            imax = 45 + (5 * radio.RegOcp.bits.OcpTrim);
+        else if (radio.RegOcp.bits.OcpTrim < 28)
+            imax = -30 + (10 * radio.RegOcp.bits.OcpTrim);
+        else
+            imax = 240;
+        printf(" OcpOn %dmA ", imax);
+    } else
+        printf(" OcpOFF ");
+
+    printf("\r\n");
+
+}
+
+void print_rx_buf(int len)
+{
+    int i;
+
+    printf("000:");
+    for (i = 0; i < len; i++) {
+        //printf("(%d)%02x ", i % 16, rx_buf[i]);
+        printf("%02x ", radio.rx_buf[i]);
+        if (i % 16 == 15 && i != len-1)
+            printf("\r\n%03d:", i+1);
+
+    }
+    printf("\r\n");
+}
+
+void
+service_radio()
+{
+    service_action_e act;
+    
+    if (radio.RegOpMode.bits.LongRangeMode) {
+
+        act = lora.service();
+    
+        switch (act) {
+            case SERVICE_READ_FIFO:
+                float dbm;
+                if (app == APP_NONE) {     
+                    printLoraIrqs_(false);
+                    if (lora.RegHopPeriod > 0) {
+                        lora.RegHopChannel.octet = radio.read_reg(REG_LR_HOPCHANNEL);
+                        printf("HopCH:%d ", lora.RegHopChannel.bits.FhssPresentChannel);
+                    }
+                    lora_printCodingRate(true);  // true: of received packet
+                    dbm = lora.get_pkt_rssi();
+                    printf(" crc%s %.1fdB  %.1fdBm\r\n",
+                        lora.RegHopChannel.bits.RxPayloadCrcOn ? "On" : "OFF",
+                        lora.RegPktSnrValue / 4.0,
+                        dbm
+                    );
+                    print_rx_buf(lora.RegRxNbBytes);
+                } else if (app == APP_CHAT) {
+                    if (lora.RegHopChannel.bits.RxPayloadCrcOn) {
+                        if (lora.RegIrqFlags.bits.PayloadCrcError)
+                            printf("crcError\r\n");
+                        else {
+                            int n = lora.RegRxNbBytes;
+                            radio.rx_buf[n++] = '\r';
+                            radio.rx_buf[n++] = '\n';
+                            radio.rx_buf[n] = 0; // null terminate
+                            printf((char *)radio.rx_buf);
+                        }
+                    } else
+                        printf("crcOff\r\n");
+                        
+                    // clear Irq flags
+                    radio.write_reg(REG_LR_IRQFLAGS, lora.RegIrqFlags.octet);
+                    // should still be in receive mode
+                }
+                break;
+            case SERVICE_TX_DONE:
+                if (app == APP_CHAT) {
+                    lora.start_rx();
+                }
+                break;
+            case SERVICE_ERROR:
+                printf("error\r\n");
+                break;
+        } // ...switch (act)
+    } else {
+        /* FSK: */
+        act = fsk.service();
+        
+         switch (act) {
+             case SERVICE_READ_FIFO:
+                if (app == APP_CHAT) {
+                    int n = fsk.rx_buf_length;
+                    radio.rx_buf[n++] = '\r';
+                    radio.rx_buf[n++] = '\n';
+                    radio.rx_buf[n] = 0; // null terminate
+                    printf((char *)radio.rx_buf);                    
+                } else {
+                    int i;
+                    if (fsk.RegRxConfig.bits.AfcAutoOn)
+                        printf("%dHz ", (int)(FREQ_STEP_HZ * fsk.RegAfcValue));
+                    printf("%d: ", fsk.rx_buf_length);
+                    for (i = 0; i < fsk.rx_buf_length; i++)
+                        printf("%02x ", radio.rx_buf[i]);
+                    printf("\r\n");
+                }
+                break;
+            case SERVICE_TX_DONE:
+                if (app == APP_CHAT) {
+                    fsk.start_rx();
+                }
+                break;                
+         } // ...switch (act)
+    }
+}
+
+int get_kbd_str(char* buf, int size)
+{
+    char c;
+    int i;
+    static int prev_len;
+    
+    for (i = 0;;) {
+        if (pc.readable()) {
+            c = pc.getc();
+            if (c == 8 && i > 0) {
+                pc.putc(8);
+                pc.putc(' ');
+                pc.putc(8);
+                i--;
+            } else if (c == '\r') {
+                if (i == 0) {
+                    return prev_len; // repeat previous
+                } else {
+                    buf[i] = 0; // null terminate
+                    prev_len = i;
+                    return i;
+                }
+            } else if (c == 3) {
+                // ctrl-C abort
+                return -1;
+            } else if (i < size) {
+                buf[i++] = c;
+                pc.putc(c);
+            }
+        } else {
+            service_radio();
+        }
+    } // ...for()
+}
+
+void
+console_chat()
+{
+    int i, len = get_kbd_str(pcbuf, sizeof(pcbuf));
+    if (len < 0) {
+        printf("chat abort\r\n");
+        app = APP_NONE;
+        return;
+    } else {
+        for (i = 0; i < len; i++)
+            radio.tx_buf[i] = pcbuf[i];
+        if (radio.RegOpMode.bits.LongRangeMode) {
+            lora.RegPayloadLength = len;
+            radio.write_reg(REG_LR_PAYLOADLENGTH, lora.RegPayloadLength);
+            lora.start_tx(len);
+        } else {
+            fsk.start_tx(len);
+        }
+        printf("\r\n");
+    }
+}
+
+void
+console()
+{
+    int len, i;
+    uint32_t ui;
+    uint8_t a, d;
+    static uint16_t fsk_tx_length;
+        
+    len = get_kbd_str(pcbuf, sizeof(pcbuf));
+    if (len < 0) {
+        printf("abort\r\n");
+        return;
+    }
+    
+    printf("\r\n");
+    if (len == 1) {
+        switch (pcbuf[0]) {
+            case 'i':
+                printf("init\r\n");
+                radio.init();
+                if (!radio.RegOpMode.bits.LongRangeMode) {
+                    fsk.init();   // put FSK modem to some functioning default
+                } else {
+                    // lora configuration is more simple
+                }
+                break;
+            case 'h':
+                printf("hw_reset()\r\n");
+                radio.hw_reset();
+                break;
+            case 'R':
+                // read all registers
+                for (a = 1; a < 0x71; a++) {
+                    d = radio.read_reg(a);
+                    //update_shadow_regs(selected_radio, a, d); 
+                    printf("%02x: %02x\r\n", a, d);
+                }
+                break;
+            case 'T':
+                if (radio.RegOpMode.bits.LongRangeMode) {
+                    lora.RegModemConfig2.octet = radio.read_reg(REG_LR_MODEMCONFIG2);
+                    //printf("a %02x\r\n", radio.RegModemConfig2.octet);
+                    lora.RegModemConfig2.sx1276bits.TxContinuousMode ^= 1;   // same for sx1272 and sx1276
+                    //printf("b %02x\r\n", radio.RegModemConfig2.octet);
+                    radio.write_reg(REG_LR_MODEMCONFIG2, lora.RegModemConfig2.octet);
+                    lora.RegModemConfig2.octet = radio.read_reg(REG_LR_MODEMCONFIG);
+                    //printf("c %02x\r\n", radio.RegModemConfig2.octet);
+                    lora_printTxContinuousMode();
+                    printf("\r\n");
+                }
+                break;
+            case 'C':
+                if (radio.RegOpMode.bits.LongRangeMode) {
+                    lora.setRxPayloadCrcOn(!lora.getRxPayloadCrcOn());
+                    lora_printRxPayloadCrcOn();
+                } else {
+                    printf("CrcOn:");
+                    fsk.RegPktConfig1.bits.CrcOn ^= 1;
+                    radio.write_reg(REG_FSK_PACKETCONFIG1, fsk.RegPktConfig1.octet);
+                    if (fsk.RegPktConfig1.bits.CrcOn)
+                        printf("On\r\n");
+                    else
+                        printf("Off\r\n");
+                    if (fsk.RegPktConfig2.bits.DataModePacket && radio.RegOpMode.bits.Mode == RF_OPMODE_RECEIVER) {
+                        fsk.config_dio0_for_pktmode_rx();
+                    }
+                }
+                printf("\r\n");
+                break;
+            case 'B':
+                radio.RegPaConfig.bits.PaSelect ^= 1;
+                radio.write_reg(REG_PACONFIG, radio.RegPaConfig.octet);
+                printPa();
+                printf("\r\n");
+                break;
+            case 'L':  
+                if (radio.RegOpMode.bits.LongRangeMode)
+                    fsk.enable();
+                else
+                    lora.enable();
+
+                radio.RegOpMode.octet = radio.read_reg(REG_OPMODE);
+                if (radio.RegOpMode.bits.LongRangeMode)
+                    printf("LoRa\r\n");
+                else
+                    printf("FSK\r\n");                
+                break;
+            case 's':
+                if (!radio.RegOpMode.bits.LongRangeMode) {
+                    fsk.RegFifoThreshold.bits.TxStartCondition ^= 1;
+                    radio.write_reg(REG_FSK_FIFOTHRESH, fsk.RegFifoThreshold.octet);
+                    printf("TxStartCondition:");
+                    if (fsk.RegFifoThreshold.bits.TxStartCondition)
+                        printf("!FifoEmpty\r\n");
+                    else
+                        printf("FifoLevel\r\n");                    
+                }
+                break;
+            case 'f':
+                if (!radio.RegOpMode.bits.LongRangeMode) {
+                    printf("PacketFormat:");
+                    fsk.RegPktConfig1.bits.PacketFormatVariable ^= 1;
+                    radio.write_reg(REG_FSK_PACKETCONFIG1, fsk.RegPktConfig1.octet);
+                    if (fsk.RegPktConfig1.bits.PacketFormatVariable)
+                        printf("variable\r\n");
+                    else
+                        printf("fixed\r\n");
+                    /*if (radio.RegOpMode.bits.Mode == RF_OPMODE_RECEIVER)
+                        reset_flow();*/
+                }
+                break;
+            case 'E':
+                if (!radio.RegOpMode.bits.LongRangeMode) {
+                    RegIrqFlags2_t RegIrqFlags2;
+                    RegIrqFlags2.octet = radio.read_reg(REG_FSK_IRQFLAGS2);
+                    while (!RegIrqFlags2.bits.FifoEmpty) {
+                        if (pc.readable())
+                            break;
+                        printf("%02x\r\n", radio.read_reg(REG_FIFO));
+                        RegIrqFlags2.octet = radio.read_reg(REG_FSK_IRQFLAGS2);
+                    }
+                }
+                break;
+            case 'A':
+                if (!radio.RegOpMode.bits.LongRangeMode) {
+                    fsk.RegRxConfig.bits.AfcAutoOn ^= 1;
+                    radio.write_reg(REG_FSK_RXCONFIG, fsk.RegRxConfig.octet);
+                    printf("AfcAuto:");
+                    if (fsk.RegRxConfig.bits.AfcAutoOn)
+                        printf("On\r\n");
+                    else
+                        printf("OFF\r\n");
+                    break;
+                }
+                break;
+            case '?':
+                printf("L           toggle LongRangeMode/FSK\r\n");
+                printf("i           radio_init\r\n");
+                printf("h           hw_reset\r\n");
+                printf("tx[%%d]    transmit\r\n");
+                printf("rx          receive\r\n");   
+                printf("C           toggle crcOn\r\n");
+                printf("op[%%d]    get/set output power\r\n");
+                printf("d[0-5]      change DIO pin assignment\r\n");
+                printf("frf[%%f}   get/set operating frequency (MHz)\r\n");
+                if (radio.RegOpMode.bits.LongRangeMode) {
+                    printf("pl[%%d]    LORA get/set RegPayloadLength\r\n");
+                    printf("cr[1234]    LORA set coding rate \r\n");
+                    printf("bw[%%d]    LORA get/set bandwidth\r\n");
+                    printf("sf[%%d]    LORA get/set spreading factor\r\n");
+                    printf("T           LORA toggle TxContinuousMode\r\n");
+                    printf("hp[%%d]    LORA get/set hop period\r\n");
+                    printf("hm          LORA toggle explicit/explicit header mode\r\n");
+                } else {
+                    printf("bw[a][%%d] FSK get-set rxbw (bwa=afcbw)\r\n");
+                    printf("br[%%d]    FSK get-set bitrate\r\n");
+                    printf("fdev[%%d]    FSK get-set TX frequency deviation (hz)\r\n");
+                    printf("rt          FSK change RxTrigger\r\n");
+                    printf("pd          FSK enable/disable preamble detector\r\n");
+                    printf("pt          FSK get-set PreambleDetectorTol\r\n");
+                    printf("ss[%%d]    FSK get-set SyncSize\r\n");
+                    printf("S[%%x]     FSK get-set sync word\r\n");
+                    printf("s           FSK toggle TxStartCondition\r\n");
+                    printf("f           FSK toggle PacketFormat fixed-variable\r\n");
+                    printf("E           FSK empty out the fifo\r\n");
+                    printf("ac          FSK AfcClear\r\n");
+                    printf("A           FSK toggle AfcAutoOn\r\n");
+                    printf("mp          FSK toggle MapPreambleDetect\r\n");
+                    printf("ar          FSK change AutoRestartRxMode\r\n");
+                    printf("alc          FSK toggle AfcAutoClearOn\r\n");
+                    printf("pre[%%d}    FSK get-set TX preamble length\r\n");
+                }
+                break;
+            case '.':
+                if (radio.RegOpMode.bits.LongRangeMode)
+                    lora_print_status();
+                else
+                    fsk_print_status();
+                common_print_status();
+                break;
+        } // ...switch (pcbuf[0])
+    } else {
+        if (pcbuf[0] == 't' && pcbuf[1] == 'x') { // TX
+            if (radio.RegOpMode.bits.LongRangeMode) {
+                if (pcbuf[2] >= '0' && pcbuf[2] <= '9') {
+                    sscanf(pcbuf+2, "%d", &i);
+                    lora.RegPayloadLength = i;
+                }
+                tx_cnt++;
+                for (i = 0; i < lora.RegPayloadLength; i++)
+                    radio.tx_buf[i] = tx_cnt;
+                lora.start_tx(lora.RegPayloadLength);
+            } else {    // FSK:
+                if (pcbuf[2] >= '0' && pcbuf[2] <= '9') {
+                    sscanf(pcbuf+2, "%d", &i);
+                    fsk_tx_length = i;
+                }
+                if (radio.RegOpMode.bits.Mode != RF_OPMODE_TRANSMITTER) { // if not already busy transmitting
+                    tx_cnt++;
+                    for (i = 0; i < fsk_tx_length; i++) {
+                        radio.tx_buf[i] = tx_cnt;
+                    }
+                    fsk.start_tx(fsk_tx_length);
+                }
+            }
+        } else if (pcbuf[0] == 'h' && pcbuf[1] == 'p' && radio.RegOpMode.bits.LongRangeMode) {
+            if (pcbuf[2] >= '0' && pcbuf[2] <= '9') {
+                sscanf(pcbuf+2, "%d", &i);
+                lora.RegHopPeriod = i;
+                radio.write_reg(REG_LR_HOPPERIOD, lora.RegHopPeriod);
+                if (radio.RegDioMapping1.bits.Dio1Mapping != 1) {
+                    radio.RegDioMapping1.bits.Dio1Mapping = 1;
+                    radio.write_reg(REG_DIOMAPPING1, radio.RegDioMapping1.octet);
+                }
+            }
+            lora.RegHopPeriod = radio.read_reg(REG_LR_HOPPERIOD);
+            printf("HopPeriod:0x%02x\r\n", lora.RegHopPeriod);
+        } else if (pcbuf[0] == 'r' && pcbuf[1] == 't' && !radio.RegOpMode.bits.LongRangeMode) {
+            printf("RxTrigger:");
+            switch (fsk.RegRxConfig.bits.RxTrigger) {
+                case 0: fsk.RegRxConfig.bits.RxTrigger = 1;
+                    printf("rssi\r\n");
+                    break;
+                case 1: fsk.RegRxConfig.bits.RxTrigger = 6;
+                    printf("preamble\r\n");
+                    break;
+                case 6: fsk.RegRxConfig.bits.RxTrigger = 7;
+                    printf("both\r\n");
+                    break;
+                case 7: fsk.RegRxConfig.bits.RxTrigger = 0;
+                    printf("none\r\n");
+                    break;
+                default: fsk.RegRxConfig.bits.RxTrigger = 0;
+                    printf("none\r\n");
+                    break;
+                }
+            radio.write_reg(REG_FSK_RXCONFIG, fsk.RegRxConfig.octet);            
+        } else if (pcbuf[0] == 'r' && pcbuf[1] == 'x') { // RX
+            if (radio.RegOpMode.bits.LongRangeMode)
+                lora.start_rx();
+            else
+                fsk.start_rx();
+        } else if (pcbuf[0] == 'r' && pcbuf[1] == ' ') { // read single register
+            sscanf(pcbuf+2, "%x", &i);
+            printf("%02x: %02x\r\n", i, radio.read_reg(i));
+        } else if (pcbuf[0] == 'w' && pcbuf[1] == ' ') { // write single register
+            sscanf(pcbuf+2, "%x %x", &i, &len);
+            radio.write_reg(i, len);
+            printf("%02x: %02x\r\n", i, radio.read_reg(i));
+        } else if (pcbuf[0] == 'm' && pcbuf[1] == 'p' && !radio.RegOpMode.bits.LongRangeMode) {
+            radio.RegDioMapping2.bits.MapPreambleDetect ^= 1;
+            radio.write_reg(REG_DIOMAPPING2, radio.RegDioMapping2.octet);
+            printf("MapPreambleDetect:");
+            if (radio.RegDioMapping2.bits.MapPreambleDetect)
+                printf("preamble\r\n");
+            else
+                printf("rssi\r\n");
+        } else if (pcbuf[0] == 'o' && pcbuf[1] == 'p') {
+            if (pcbuf[2] >= '0' && pcbuf[2] <= '9') {
+                sscanf(pcbuf+2, "%d", &i);
+                radio.RegPaConfig.bits.OutputPower = i;
+                radio.write_reg(REG_PACONFIG, radio.RegPaConfig.octet);
+            }
+            radio.RegPaConfig.octet = radio.read_reg(REG_PACONFIG);
+            printf("OutputPower:%d\r\n", radio.RegPaConfig.bits.OutputPower);
+        } else if (pcbuf[0] == 'c' && pcbuf[1] == 'r' && radio.RegOpMode.bits.LongRangeMode) {
+            if (pcbuf[2] >= '0' && pcbuf[2] <= '9')
+                lora.setCodingRate(pcbuf[2] - '0');
+             lora.RegModemConfig.octet = radio.read_reg(REG_LR_MODEMCONFIG);
+             lora_printCodingRate(false);    // false: transmitted
+             printf("\r\n");
+        } else if (pcbuf[0] == 'h' && pcbuf[1] == 'm' && radio.RegOpMode.bits.LongRangeMode) {    // toggle implicit/explicit
+            lora.setHeaderMode(!lora.getHeaderMode());
+            lora.RegModemConfig.octet = radio.read_reg(REG_LR_MODEMCONFIG);
+            lora_printHeaderMode();
+            printf("\r\n");
+        } else if (pcbuf[0] == 'a' && pcbuf[1] == 'l' && !radio.RegOpMode.bits.LongRangeMode) {
+            fsk.RegAfcFei.bits.AfcAutoClearOn ^= 1;
+            printf("AfcAutoClearOn: ");
+            radio.write_reg(REG_FSK_AFCFEI, fsk.RegAfcFei.octet);
+            if (fsk.RegAfcFei.bits.AfcAutoClearOn)
+                printf("ON\r\n");
+            else
+                printf("off\r\n");
+        } else if (pcbuf[0] == 'a' && pcbuf[1] == 'r' && !radio.RegOpMode.bits.LongRangeMode) {
+            fsk.RegSyncConfig.bits.AutoRestartRxMode++;
+            radio.write_reg(REG_FSK_SYNCCONFIG, fsk.RegSyncConfig.octet);
+            fsk.RegSyncConfig.octet = radio.read_reg(REG_FSK_SYNCCONFIG);
+            printf("AutoRestartRxMode:");
+            switch (fsk.RegSyncConfig.bits.AutoRestartRxMode) {
+                case 0: printf("off "); break;
+                case 1: printf("no-pll-wait "); break;
+                case 2: printf("pll-wait "); break;
+                case 3: printf("3 "); break;
+            }
+            printf("\r\n");            
+        } else if (pcbuf[0] == 'a' && pcbuf[1] == 'c' && !radio.RegOpMode.bits.LongRangeMode) {
+            printf("clear afc: ");
+            fsk.RegAfcFei.bits.AfcClear = 1;
+            radio.write_reg(REG_FSK_AFCFEI, fsk.RegAfcFei.octet);
+            fsk.RegAfcFei.bits.AfcClear = 0; 
+            printf("%dHz\r\n", (int)(FREQ_STEP_HZ * radio.read_s16(REG_FSK_AFCMSB)));
+        } else if (pcbuf[0] == 'b' && pcbuf[1] == 'r' && !radio.RegOpMode.bits.LongRangeMode) {
+            if (pcbuf[2] >= '0' && pcbuf[2] <= '9') {
+                sscanf(&pcbuf[2], "%d", &i);
+                fsk.set_bitrate(i);
+            }
+            printf("%dbps\r\n", fsk.get_bitrate());             
+        } else if (pcbuf[0] == 'b' && pcbuf[1] == 'w') {
+            if (radio.RegOpMode.bits.LongRangeMode) {
+                if (pcbuf[2] >= '0' && pcbuf[2] <= '9') {
+                    radio.set_opmode(RF_OPMODE_STANDBY);
+                    sscanf(&pcbuf[2], "%d", &i);
+                    lora.setBw(i);
+                } else
+                    lora_printAllBw();
+                lora.RegModemConfig.octet = radio.read_reg(REG_LR_MODEMCONFIG);
+                printf("current ");
+                lora_printBw();
+                printf("\r\n");
+            } else { // FSK:
+                if (pcbuf[2] == 'a') {
+                    if (pcbuf[3] >= '0' && pcbuf[3] <= '9') {
+                        radio.set_opmode(RF_OPMODE_STANDBY);
+                        sscanf(&pcbuf[3], "%d", &i);
+                        fsk.set_rx_dcc_bw_hz(i, 1);
+                    }
+                    printf("afcbw:%dHz\r\n", fsk.get_rx_bw_hz(REG_FSK_AFCBW));
+                } else {
+                    if (pcbuf[2] >= '0' && pcbuf[2] <= '9') {
+                        radio.set_opmode(RF_OPMODE_STANDBY);
+                        sscanf(&pcbuf[2], "%d", &i);
+                        fsk.set_rx_dcc_bw_hz(i, 0);
+                    }
+                    printf("rxbw:%dHz\r\n", fsk.get_rx_bw_hz(REG_FSK_RXBW));
+                }
+            }
+        } else if (pcbuf[0] == 'v' && pcbuf[1] == 'h') {
+            lora.poll_vh ^= 1;
+            printf("poll_vh:%d\r\n", lora.poll_vh);
+        } else if (pcbuf[0] == 'S' && !radio.RegOpMode.bits.LongRangeMode) {
+            if (pcbuf[1] == '0') {
+                sscanf(pcbuf+1, "%x", &ui);
+                if (ui < 0x100) {
+                    fsk.RegSyncConfig.bits.SyncSize = 0;
+                    radio.write_reg(REG_FSK_SYNCVALUE1, ui);
+                } else if (ui < 0x10000) {
+                    fsk.RegSyncConfig.bits.SyncSize = 1;
+                    radio.write_reg(REG_FSK_SYNCVALUE2, ui & 0xff);
+                    radio.write_reg(REG_FSK_SYNCVALUE1, ui >> 8);
+                } else if (ui < 0x1000000) {
+                    fsk.RegSyncConfig.bits.SyncSize = 2;
+                    radio.write_reg(REG_FSK_SYNCVALUE3, ui & 0xff);
+                    radio.write_reg(REG_FSK_SYNCVALUE2, (ui >> 8) & 0xff);
+                    radio.write_reg(REG_FSK_SYNCVALUE1, ui >> 16);                              
+                } else {
+                    fsk.RegSyncConfig.bits.SyncSize = 3;
+                    radio.write_reg(REG_FSK_SYNCVALUE4, ui & 0xff);
+                    radio.write_reg(REG_FSK_SYNCVALUE3, (ui >> 8) & 0xff);
+                    radio.write_reg(REG_FSK_SYNCVALUE2, (ui >> 16) & 0xff);
+                    radio.write_reg(REG_FSK_SYNCVALUE1, ui >> 24);                       
+                }
+                radio.write_reg(REG_FSK_SYNCCONFIG, fsk.RegSyncConfig.octet);
+            }
+            fsk.RegSyncConfig.octet = radio.read_reg(REG_FSK_SYNCCONFIG);
+            printf("%d: ", fsk.RegSyncConfig.bits.SyncSize);
+            for (i = 0; i <= fsk.RegSyncConfig.bits.SyncSize; i++)
+                printf("%02x ", radio.read_reg(REG_FSK_SYNCVALUE1+i));
+            printf("\r\n");
+        } else if (pcbuf[0] == 's' && pcbuf[1] == 's' && !radio.RegOpMode.bits.LongRangeMode) {
+            if (pcbuf[2] >= '0' && pcbuf[2] <= '9') {
+                sscanf(pcbuf+2, "%d", &i);
+                fsk.RegSyncConfig.bits.SyncSize = i;
+                radio.write_reg(REG_FSK_SYNCCONFIG, fsk.RegSyncConfig.octet);
+            }
+            fsk.RegSyncConfig.octet = radio.read_reg(REG_FSK_SYNCCONFIG);
+            printf("SyncSize:%d\r\n", fsk.RegSyncConfig.bits.SyncSize);
+        } else if (pcbuf[0] == 's' && pcbuf[1] == 'f' && radio.RegOpMode.bits.LongRangeMode) {
+            if (pcbuf[2] >= '0' && pcbuf[2] <= '9') {
+                sscanf(pcbuf+2, "%d", &i);
+                lora.setSf(i);
+                if (i == 6 && !lora.getHeaderMode()) {
+                    printf("SF6: to implicit header mode\r\n");
+                    lora.setHeaderMode(true);
+                }
+            }
+            lora.RegModemConfig2.octet = radio.read_reg(REG_LR_MODEMCONFIG2);
+            lora_printSf();
+            printf("\r\n");
+        } else if (pcbuf[0] == 'f' && pcbuf[1] == 'd' && pcbuf[2] == 'e' && !radio.RegOpMode.bits.LongRangeMode) {
+            if (pcbuf[4] >= '0' && pcbuf[4] <= '9') {
+                sscanf(pcbuf+4, "%d", &i);
+                fsk.set_tx_fdev_hz(i);
+            }
+            printf("fdev:%dHz\r\n", fsk.get_tx_fdev_hz());
+        } else if (pcbuf[0] == 'f' && pcbuf[1] == 'r' && pcbuf[2] == 'f') {
+            if (pcbuf[3] >= '0' && pcbuf[3] <= '9') {
+                float MHz;
+                sscanf(pcbuf+3, "%f", &MHz);
+                //printf("MHz:%f\r\n", MHz);
+                radio.set_frf_MHz(MHz);
+            }
+            printf("%fMHz\r\n", radio.get_frf_MHz());
+        } else if (pcbuf[0] == 'p' && pcbuf[1] == 'r' && pcbuf[2] == 'e') {
+            if (radio.RegOpMode.bits.LongRangeMode) {
+                if (pcbuf[3] >= '0' && pcbuf[3] <= '9') {
+                    sscanf(pcbuf+3, "%d", &i);
+                    radio.write_u16(REG_LR_PREAMBLEMSB, i);
+                }
+                lora.RegPreamble = radio.read_u16(REG_LR_PREAMBLEMSB);
+                printf("lora PreambleLength:%d\r\n", lora.RegPreamble);                
+            } else {
+                if (pcbuf[3] >= '0' && pcbuf[3] <= '9') {
+                    sscanf(pcbuf+3, "%d", &i);
+                    radio.write_u16(REG_FSK_PREAMBLEMSB, i);
+                }
+                printf("FSK TX PreambleSize:%d\r\n", radio.read_u16(REG_FSK_PREAMBLEMSB));
+            }
+        } else if (pcbuf[0] == 'p' && pcbuf[1] == 't' && !radio.RegOpMode.bits.LongRangeMode) {
+            if (pcbuf[2] >= '0' && pcbuf[2] <= '9') {
+                sscanf(pcbuf+2, "%d", &i);
+                fsk.RegPreambleDetect.bits.PreambleDetectorTol = i;
+                radio.write_reg(REG_FSK_PREAMBLEDETECT, fsk.RegPreambleDetect.octet);
+            }
+            fsk.RegPreambleDetect.octet = radio.read_reg(REG_FSK_PREAMBLEDETECT);
+            printf("PreambleDetectorTol:%d\r\n", fsk.RegPreambleDetect.bits.PreambleDetectorTol);
+        } else if (pcbuf[0] == 'p' && pcbuf[1] == 'd' && !radio.RegOpMode.bits.LongRangeMode) {
+            fsk.RegPreambleDetect.bits.PreambleDetectorOn ^= 1;
+            radio.write_reg(REG_FSK_PREAMBLEDETECT, fsk.RegPreambleDetect.octet);
+            printf("PreambleDetector:");
+            if (fsk.RegPreambleDetect.bits.PreambleDetectorOn)
+                printf("On\r\n");
+            else
+                printf("OFF\r\n");            
+        } else if (pcbuf[0] == 'p' && pcbuf[1] == 'l' && radio.RegOpMode.bits.LongRangeMode) {
+            if (pcbuf[2] >= '0' && pcbuf[2] <= '9') {
+                sscanf(pcbuf+2, "%d", &i);
+                lora.RegPayloadLength = i;
+                radio.write_reg(REG_LR_PAYLOADLENGTH, lora.RegPayloadLength);             
+            }
+            lora.RegPayloadLength = radio.read_reg(REG_LR_PAYLOADLENGTH);
+            printf("PayloadLength:%d\r\n", lora.RegPayloadLength);
+        } else if (pcbuf[0] == 'd' && pcbuf[1] >= '0' && pcbuf[1] <= '5') {
+            switch (pcbuf[1]) {
+                case '0':
+                    radio.RegDioMapping1.bits.Dio0Mapping++;
+                    radio.write_reg(REG_DIOMAPPING1, radio.RegDioMapping1.octet);
+                    break;
+                case '1':
+                    radio.RegDioMapping1.bits.Dio1Mapping++;
+                    radio.write_reg(REG_DIOMAPPING1, radio.RegDioMapping1.octet);
+                    break;    
+                case '2':
+                    radio.RegDioMapping1.bits.Dio2Mapping++;
+                    radio.write_reg(REG_DIOMAPPING1, radio.RegDioMapping1.octet);
+                    break;
+                case '3':
+                    radio.RegDioMapping1.bits.Dio3Mapping++;
+                    radio.write_reg(REG_DIOMAPPING1, radio.RegDioMapping1.octet);
+                    break;
+                case '4':
+                    radio.RegDioMapping2.bits.Dio4Mapping++;
+                    radio.write_reg(REG_DIOMAPPING1, radio.RegDioMapping2.octet);
+                    break; 
+                case '5':
+                    radio.RegDioMapping2.bits.Dio5Mapping++;
+                    radio.write_reg(REG_DIOMAPPING1, radio.RegDioMapping2.octet);
+                    break;                                                                                             
+            } // ...switch (pcbuf[1])
+            if (radio.RegOpMode.bits.LongRangeMode)
+                lora_print_dio();
+            else
+                fsk_print_dio();
+        } else if (pcbuf[0] == 's' && pcbuf[1] == 't' && pcbuf[2] == 'b') {
+            radio.set_opmode(RF_OPMODE_STANDBY);
+        } else if (pcbuf[0] == 's' && pcbuf[1] == 'l' && pcbuf[2] == 'e') {
+            radio.set_opmode(RF_OPMODE_SLEEP);
+        } else if (pcbuf[0] == 'c' && pcbuf[1] == 'h' && pcbuf[2] == 'a') {
+            app = APP_CHAT;
+            lora.start_rx();
+            printf("chat start\r\n");
+        }           
+    }
+    printf("> ");
+    fflush(stdout);
+        
+}
+
+int main()
+{  
+
+    pc.baud(57600);
+    
+    radio.frfs = frfs;
+
+    while(1) {
+        switch (app) {
+            case APP_NONE:
+                console();
+                break;
+            case APP_CHAT:
+                console_chat();
+                break;
+        } // ...switch (app)
+    } // ...while(1)
+}
+