Terminal for sending and receiving data via Semtech SX1276 chip. It uses the FRDM-KL25Z board, with a Modtronix inAir9 SX1276 board, and Modtronix SHD3I shield. The inAir9 module is mounted in iMod port 3 of the SHD3I module. The SHD3I shield is mounted on the FRDM-KL25Z board.

Dependencies:   SX127x_modtronix mbed

Fork of chat_sx127x by wayne roberts

Revision:
0:be215de91a68
Child:
1:1cd0afbed23c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp	Wed Mar 26 01:13:30 2014 +0000
@@ -0,0 +1,729 @@
+#include "sx127x.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 my_frf_a = 914.0 / FREQ_STEP_MHZ;
+const uint32_t my_frf_b = 915.0 / FREQ_STEP_MHZ;*/
+const uint32_t frfs[] = {
+    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)
+};
+
+/******************************************************************************/
+
+//  pin:      3     8     1      7    10    12     5   20    18
+//           mosi, miso, sclk,   cs,  rst,  dio0, dio1, fctx, fcps 
+SX127x radio(PTD2, PTD3, PTD1, PTD0, PTD5, PTA13, PTD4, PTC9, PTC8);
+
+void printLoraIrqs_(bool clear)
+{
+    //in radio class -- RegIrqFlags_t RegIrqFlags;
+
+    //already read RegIrqFlags.octet = radio.read_reg(REG_LR_IRQFLAGS);
+    printf("\r\nIrqFlags:");
+    if (radio.RegIrqFlags.bits.CadDetected)
+        printf("CadDetected ");
+    if (radio.RegIrqFlags.bits.FhssChangeChannel) {
+        //radio.RegHopChannel.octet = radio.read_reg(REG_LR_HOPCHANNEL);
+        printf("FhssChangeChannel:%d ", radio.RegHopChannel.bits.FhssPresentChannel);
+    }
+    if (radio.RegIrqFlags.bits.CadDone)
+        printf("CadDone ");
+    if (radio.RegIrqFlags.bits.TxDone)
+        printf("TxDone ");
+    if (radio.RegIrqFlags.bits.ValidHeader)
+        printf("ValidHeader ");
+    if (radio.RegIrqFlags.bits.PayloadCrcError)
+        printf("PayloadCrcError ");
+    if (radio.RegIrqFlags.bits.RxDone)
+        printf("RxDone ");  
+    if (radio.RegIrqFlags.bits.RxTimeout)
+        printf("RxTimeout ");
+
+    printf("\r\n");
+
+    if (clear)
+        radio.write_reg(REG_LR_IRQFLAGS, radio.RegIrqFlags.octet);
+
+}
+
+void printCodingRate(bool from_rx)
+{
+    uint8_t d = radio.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 printHeaderMode()
+{
+    if (radio.getHeaderMode())
+        printf("implicit ");
+    else
+        printf("explicit ");
+}
+
+void printBw()
+{
+    uint8_t bw = radio.getBw();
+    
+    printf("Bw:");
+    if (radio.type == SX1276) {
+        switch (radio.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 ", radio.RegModemConfig.sx1276bits.Bw); break;
+        }
+    } else if (radio.type == SX1272) {
+        switch (radio.RegModemConfig.sx1272bits.Bw) {
+            case 0: printf("125KHz "); break;
+            case 1: printf("250KHz "); break;
+            case 2: printf("500KHz "); break;
+            case 3: printf("11b "); break;
+        }
+    }
+}
+
+void printAllBw()
+{
+    int i, s;
+    
+    if (radio.type == SX1276) {
+        s = radio.RegModemConfig.sx1276bits.Bw;    
+        for (i = 0; i < 10; i++ ) {
+            radio.RegModemConfig.sx1276bits.Bw = i;
+            printf("%d ", i);
+            printBw();
+            printf("\r\n");
+        }
+        radio.RegModemConfig.sx1276bits.Bw = s;
+    } else if (radio.type == SX1272) {
+        s = radio.RegModemConfig.sx1272bits.Bw;    
+        for (i = 0; i < 3; i++ ) {
+            radio.RegModemConfig.sx1272bits.Bw = i;
+            printf("%d ", i);
+            printBw();
+            printf("\r\n");
+        }
+        radio.RegModemConfig.sx1272bits.Bw = s;    
+    }
+}
+
+void printSf()
+{
+    // spreading factor same between sx127[26]
+    printf("sf:%d ", radio.getSf());
+}
+
+void printRxPayloadCrcOn()
+{
+    bool on = radio.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 printTxContinuousMode()
+{
+    printf("TxContinuousMode:%d ", radio.RegModemConfig2.sx1276bits.TxContinuousMode);    // same for sx1272 and sx1276
+}
+
+void printAgcAutoOn()
+{
+    printf("AgcAutoOn:%d", radio.getAgcAutoOn());
+}
+
+void 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 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;
+    }
+    
+    print_dio();
+    printf("LoRa ");
+    
+    // printing LoRa registers at 0x0d -> 0x3f
+
+    radio.RegModemConfig.octet = radio.read_reg(REG_LR_MODEMCONFIG);
+    radio.RegModemConfig2.octet = radio.read_reg(REG_LR_MODEMCONFIG2);
+
+    printCodingRate(false); // false: transmitted coding rate
+    printHeaderMode();
+    printBw();
+    printSf();
+    printRxPayloadCrcOn();
+    // RegModemStat
+    printf("ModemStat:0x%02x\r\n", radio.read_reg(REG_LR_MODEMSTAT));
+
+    // fifo ptrs:
+    radio.RegPayloadLength = radio.read_reg(REG_LR_PAYLOADLENGTH);
+    radio.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),
+        radio.RegPayloadLength,
+        radio.RegRxMaxPayloadLength
+    );
+
+    radio.RegIrqFlags.octet = radio.read_reg(REG_LR_IRQFLAGS);
+    printLoraIrqs_(false);
+
+    radio.RegHopPeriod = radio.read_reg(REG_LR_HOPPERIOD);
+    if (radio.RegHopPeriod != 0) {
+        printf("\r\nHopPeriod:0x%02x\r\n", radio.RegHopPeriod);
+    }
+
+    printf("SymbTimeout:0x%03x ", radio.read_u16(REG_LR_MODEMCONFIG2) & 0x3ff);
+
+    radio.RegPreamble = radio.read_u16(REG_LR_PREAMBLEMSB);
+    printf("PreambleLength:0x%03x ", radio.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);
+    }
+
+    printTxContinuousMode();
+
+    printf("\r\n");
+    printAgcAutoOn();
+    if (radio.type == SX1272) {
+        printf(" LowDataRateOptimize:%d\r\n", radio.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));
+    radio.RegTest31.octet = radio.read_reg(REG_LR_TEST31);
+    printf("detect_trig_same_peaks_nb:%d\r\n", radio.RegTest31.bits.detect_trig_same_peaks_nb);
+
+    if (radio.type == SX1272) {
+        radio.RegModemConfig.octet = radio.read_reg(REG_LR_MODEMCONFIG);
+        printf("LowDataRateOptimize:%d\r\n", radio.RegModemConfig.sx1272bits.LowDataRateOptimize);
+    } else if (radio.type == SX1276) {
+        radio.RegModemConfig3.octet = radio.read_reg(REG_LR_MODEMCONFIG3);
+        printf("LowDataRateOptimize:%d\r\n", radio.RegModemConfig3.sx1276bits.LowDataRateOptimize);        
+    }
+    
+    printf("\r\n");
+    //printf("A %02x\r\n", radio.RegModemConfig2.octet);
+}
+
+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 = radio.service();
+    
+    switch (act) {
+        case SERVICE_READ_FIFO:
+            if (app == APP_NONE) {     
+                printLoraIrqs_(false);
+                if (radio.RegHopPeriod > 0) {
+                    radio.RegHopChannel.octet = radio.read_reg(REG_LR_HOPCHANNEL);
+                    printf("HopCH:%d ", radio.RegHopChannel.bits.FhssPresentChannel);
+                }
+                printCodingRate(true);  // true: of received packet
+                printf(" crc%s %.1fdB %ddBm\r\n",
+                    radio.RegHopChannel.bits.RxPayloadCrcOn ? "On" : "OFF",
+                    radio.RegPktSnrValue / 4.0,
+                    radio.RegPktRssiValue - 137
+                );
+                print_rx_buf(radio.RegRxNbBytes);
+            } else if (app == APP_CHAT) {
+                if (radio.RegHopChannel.bits.RxPayloadCrcOn) {
+                    if (radio.RegIrqFlags.bits.PayloadCrcError)
+                        printf("crcError\r\n");
+                    else {
+                        int n = radio.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, radio.RegIrqFlags.octet);
+                // should still be in receive mode
+            }
+            break;
+        case SERVICE_TX_DONE:
+            if (app == APP_CHAT) {
+                radio.lora_start_rx();
+            }
+            break;
+        case SERVICE_ERROR:
+            printf("error\r\n");
+            break;
+    } // ...switch (act)
+}
+
+void user_init(void)
+{
+    // set desired spreadingfactor, bandwidth, MHz, etc.
+}
+
+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];
+        radio.RegPayloadLength = len;
+        radio.write_reg(REG_LR_PAYLOADLENGTH, radio.RegPayloadLength);  
+        radio.lora_start_tx(len);
+        printf("\r\n");
+    }
+}
+
+void
+console()
+{
+    int len, i;
+    uint8_t a, d;
+        
+    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':
+                radio.init();
+                user_init();
+                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':
+                radio.RegModemConfig2.octet = radio.read_reg(REG_LR_MODEMCONFIG2);
+                //printf("a %02x\r\n", radio.RegModemConfig2.octet);
+                radio.RegModemConfig2.sx1276bits.TxContinuousMode ^= 1;   // same for sx1272 and sx1276
+                //printf("b %02x\r\n", radio.RegModemConfig2.octet);
+                radio.write_reg(REG_LR_MODEMCONFIG2, radio.RegModemConfig2.octet);
+                radio.RegModemConfig2.octet = radio.read_reg(REG_LR_MODEMCONFIG);
+                //printf("c %02x\r\n", radio.RegModemConfig2.octet);
+                printTxContinuousMode();
+                printf("\r\n");
+                break;
+            case 'C':
+                radio.setRxPayloadCrcOn(!radio.getRxPayloadCrcOn());
+                printRxPayloadCrcOn();
+                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 '?':
+                printf("i           radio_init\r\n");
+                printf("h           hw_reset\r\n");
+                printf("hm          toggle explicit/explicit header mode\r\n");
+                printf("tx[ %%d]     transmit\r\n");
+                printf("rx          receive\r\n");
+                printf("cr[1234]    set coding rate\r\n");
+                printf("bw[%%d]      get/set bandwidth\r\n");
+                printf("sf[%%d]      get/set spreading factor\r\n");
+                printf("pl[%%d]      get/set RegPayloadLength\r\n");
+                printf("C           toggle crcOn\r\n");
+                printf("T           toggle TxContinuousMode\r\n");
+                printf("op[%%d]     get/set output power\r\n");
+                printf("hp[%%d]     get/set hop period\r\n");
+                printf("d[0-5]      change DIO pin assignment\r\n");                               
+                break;
+            case '.':
+                lora_print_status();
+                common_print_status();
+                break;
+        } // ...switch (pcbuf[0])
+    } else {
+        if (pcbuf[0] == 't' && pcbuf[1] == 'x') { // TX
+            if (pcbuf[2] == ' ') {
+                sscanf(pcbuf+3, "%d", &i);
+                radio.RegPayloadLength = i;
+            }
+            tx_cnt++;
+            for (i = 0; i < radio.RegPayloadLength; i++)
+                radio.tx_buf[i] = tx_cnt;
+            radio.lora_start_tx(radio.RegPayloadLength);
+        } else if (pcbuf[0] == 'h' && pcbuf[1] == 'p') { //
+            if (pcbuf[2] >= '0' && pcbuf[2] <= '9') {
+                sscanf(pcbuf+2, "%d", &i);
+                radio.RegHopPeriod = i;
+                radio.write_reg(REG_LR_HOPPERIOD, radio.RegHopPeriod);
+                if (radio.RegDioMapping1.bits.Dio1Mapping != 1) {
+                    radio.RegDioMapping1.bits.Dio1Mapping = 1;
+                    radio.write_reg(REG_DIOMAPPING1, radio.RegDioMapping1.octet);
+                }
+            }
+            radio.RegHopPeriod = radio.read_reg(REG_LR_HOPPERIOD);
+            printf("HopPeriod:0x%02x\r\n", radio.RegHopPeriod);
+        } else if (pcbuf[0] == 'r' && pcbuf[1] == 'x') { // RX
+            radio.lora_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] == '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') {
+            if (pcbuf[2] >= '0' && pcbuf[2] <= '9')
+                radio.setCodingRate(pcbuf[2] - '0');
+             radio.RegModemConfig.octet = radio.read_reg(REG_LR_MODEMCONFIG);
+             printCodingRate(false);    // false: transmitted
+             printf("\r\n");
+        } else if (pcbuf[0] == 'h' && pcbuf[1] == 'm') {    // toggle implicit/explicit
+            radio.setHeaderMode(!radio.getHeaderMode());
+            radio.RegModemConfig.octet = radio.read_reg(REG_LR_MODEMCONFIG);
+            printHeaderMode();
+            printf("\r\n");
+        } else if (pcbuf[0] == 'b' && pcbuf[1] == 'w') {
+            if (pcbuf[2] >= '0' && pcbuf[2] <= '9') {
+                radio.set_opmode(RF_OPMODE_STANDBY);
+                sscanf(&pcbuf[2], "%d", &i);
+                radio.setBw(i);
+            } else
+                printAllBw();
+            radio.RegModemConfig.octet = radio.read_reg(REG_LR_MODEMCONFIG);
+            printf("current ");
+            printBw();
+            printf("\r\n");
+        } else if (pcbuf[0] == 'v' && pcbuf[1] == 'h') {
+            radio.poll_vh ^= 1;
+            printf("poll_vh:%d\r\n", radio.poll_vh);
+        } else if (pcbuf[0] == 's' && pcbuf[1] == 'f') {
+            if (pcbuf[2] >= '0' && pcbuf[2] <= '9') {
+                sscanf(pcbuf+2, "%d", &i);
+                radio.setSf(i);
+                if (i == 6 && !radio.getHeaderMode()) {
+                    printf("SF6: to implicit header mode\r\n");
+                    radio.setHeaderMode(true);
+                }
+            }
+            radio.RegModemConfig2.octet = radio.read_reg(REG_LR_MODEMCONFIG2);
+            printSf();
+            printf("\r\n");
+        } 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);
+            } else
+                printf("%fMHz\r\n", radio.get_frf_MHz());
+        } else if (pcbuf[0] == 'p' && pcbuf[1] == 'l') {
+            if (pcbuf[2] >= '0' && pcbuf[2] <= '9') {
+                sscanf(pcbuf+2, "%d", &i);
+                radio.RegPayloadLength = i;
+                radio.write_reg(REG_LR_PAYLOADLENGTH, radio.RegPayloadLength);             
+            }
+            radio.RegPayloadLength = radio.read_reg(REG_LR_PAYLOADLENGTH);
+            printf("PayloadLength:%d\r\n", radio.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])
+            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;
+            radio.lora_start_rx();
+            printf("chat start\r\n");
+        }           
+    }
+    printf("> ");
+    fflush(stdout);
+        
+}
+
+int main()
+{  
+
+    pc.baud(57600);
+    user_init();
+    
+    radio.frfs = frfs;
+
+    while(1) {
+        switch (app) {
+            case APP_NONE:
+                console();
+                break;
+            case APP_CHAT:
+                console_chat();
+                break;
+        } // ...switch (app)
+    } // ...while(1)
+}
+