コード例 #1
0
uint8_t sx125x_read(uint8_t channel, uint8_t addr) {
    int reg_add, reg_dat, reg_cs, reg_rb;
    int32_t read_value;

    /* checking input parameters */
    if (channel >= LGW_RF_CHAIN_NB) {
        DEBUG_MSG("ERROR: INVALID RF_CHAIN\n");
        return 0;
    }
    if (addr >= 0x7F) {
        DEBUG_MSG("ERROR: ADDRESS OUT OF RANGE\n");
        return 0;
    }

    /* selecting the target radio */
    switch (channel) {
    case 0:
        reg_add = LGW_SPI_RADIO_A__ADDR;
        reg_dat = LGW_SPI_RADIO_A__DATA;
        reg_cs  = LGW_SPI_RADIO_A__CS;
        reg_rb  = LGW_SPI_RADIO_A__DATA_READBACK;
        break;

    case 1:
        reg_add = LGW_SPI_RADIO_B__ADDR;
        reg_dat = LGW_SPI_RADIO_B__DATA;
        reg_cs  = LGW_SPI_RADIO_B__CS;
        reg_rb  = LGW_SPI_RADIO_B__DATA_READBACK;
        break;

    default:
        DEBUG_PRINTF("ERROR: UNEXPECTED VALUE %d IN SWITCH STATEMENT\n", channel);
        return 0;
    }

    /* SPI master data read procedure */
    lgw_reg_w(reg_cs, 0);
    lgw_reg_w(reg_add, addr); /* MSB at 0 for read operation */
    lgw_reg_w(reg_dat, 0);
    lgw_reg_w(reg_cs, 1);
    lgw_reg_w(reg_cs, 0);
    lgw_reg_r(reg_rb, &read_value);

    return (uint8_t)read_value;
}
コード例 #2
0
ファイル: util_spi_stress.c プロジェクト: AcSiP/lora_gateway
int main(int argc, char **argv)
{
    int i;
    int xi = 0;

    /* application option */
    int test_number = 1;
    int cycle_number = 0;
    int repeats_per_cycle = 1000;
    bool error = false;

    /* in/out variables */
    int32_t test_value;
    int32_t read_value;
    int32_t rb1, rb2, rb3; /* interstitial readbacks, to flush buffers if needed */

    /* data buffer */
    int32_t test_addr;
    uint8_t test_buff[BUFF_SIZE];
    uint8_t read_buff[BUFF_SIZE];

    /* parse command line options */
    while ((i = getopt (argc, argv, "ht:")) != -1) {
        switch (i) {
            case 'h':
                usage();
                return EXIT_FAILURE;
                break;

            case 't':
                i = sscanf(optarg, "%i", &xi);
                if ((i != 1) || (xi < 1) || (xi > 4)) {
                    MSG("ERROR: invalid test number\n");
                    return EXIT_FAILURE;
                } else {
                    test_number = xi;
                }
                break;

            default:
                MSG("ERROR: argument parsing use -h option for help\n");
                usage();
                return EXIT_FAILURE;
        }
    }
    MSG("INFO: Starting LoRa concentrator SPI stress-test number %i\n", test_number);

    /* configure signal handling */
    sigemptyset(&sigact.sa_mask);
    sigact.sa_flags = 0;
    sigact.sa_handler = sig_handler;
    sigaction(SIGQUIT, &sigact, NULL);
    sigaction(SIGINT, &sigact, NULL);
    sigaction(SIGTERM, &sigact, NULL);

    /* start SPI link */
    i = lgw_connect();
    if (i != LGW_REG_SUCCESS) {
        MSG("ERROR: lgw_connect() did not return SUCCESS");
        return EXIT_FAILURE;
    }

    if (test_number == 1) {
        /* single 8b register R/W stress test */
        while ((quit_sig != 1) && (exit_sig != 1)) {
            printf("Cycle %i > ", cycle_number);
            for (i=0; i<repeats_per_cycle; ++i) {
                test_value = (rand() % 256);
                lgw_reg_w(LGW_IMPLICIT_PAYLOAD_LENGHT, test_value);
                lgw_reg_r(LGW_IMPLICIT_PAYLOAD_LENGHT, &read_value);
                if (read_value != test_value) {
                    error = true;
                    break;
                }
            }
            if (error) {
                printf("error during the %ith iteration: write 0x%02X, read 0x%02X\n", i+1, test_value, read_value);
                printf("Repeat read of target register:");
                for (i=0; i<READS_WHEN_ERROR; ++i) {
                    lgw_reg_r(LGW_IMPLICIT_PAYLOAD_LENGHT, &read_value);
                    printf(" 0x%02X", read_value);
                }
                printf("\n");
                return EXIT_FAILURE;
            } else {
                printf("did %i R/W on an 8 bits reg with no error\n", repeats_per_cycle);
                ++cycle_number;
            }
        }
    } else if (test_number == 2) {
        /* single 8b register R/W with interstitial VERSION check stress test */
        while ((quit_sig != 1) && (exit_sig != 1)) {
            printf("Cycle %i > ", cycle_number);
            for (i=0; i<repeats_per_cycle; ++i) {
                test_value = (rand() % 256);
                lgw_reg_r(LGW_VERSION, &rb1);
                lgw_reg_w(LGW_IMPLICIT_PAYLOAD_LENGHT, test_value);
                lgw_reg_r(LGW_VERSION, &rb2);
                lgw_reg_r(LGW_IMPLICIT_PAYLOAD_LENGHT, &read_value);
                lgw_reg_r(LGW_VERSION, &rb3);
                if ((rb1 != VERS) || (rb2 != VERS) || (rb3 != VERS) || (read_value != test_value)) {
                    error = true;
                    break;
                }
            }
            if (error) {
                printf("error during the %ith iteration: write %02X, read %02X, version (%i, %i, %i)\n", i+1, test_value, read_value, rb1, rb2, rb3);
                printf("Repeat read of target register:");
                for (i=0; i<READS_WHEN_ERROR; ++i) {
                    lgw_reg_r(LGW_IMPLICIT_PAYLOAD_LENGHT, &read_value);
                    printf(" 0x%02X", read_value);
                }
                printf("\n");
                return EXIT_FAILURE;
            } else {
                printf("did %i R/W on an 8 bits reg with no error\n", repeats_per_cycle);
                ++cycle_number;
            }
        }
    } else if (test_number == 3) {
        /* 32b register R/W stress test */
        while ((quit_sig != 1) && (exit_sig != 1)) {
            printf("Cycle %i > ", cycle_number);
            for (i=0; i<repeats_per_cycle; ++i) {
                test_value = (rand() & 0x0000FFFF);
                test_value += (int32_t)(rand() & 0x0000FFFF) << 16;
                lgw_reg_w(LGW_FSK_REF_PATTERN_LSB, test_value);
                lgw_reg_r(LGW_FSK_REF_PATTERN_LSB, &read_value);
                if (read_value != test_value) {
                    error = true;
                    break;
                }
            }
            if (error) {
                printf("error during the %ith iteration: write 0x%08X, read 0x%08X\n", i+1, test_value, read_value);
                printf("Repeat read of target register:");
                for (i=0; i<READS_WHEN_ERROR; ++i) {
                    lgw_reg_r(LGW_FSK_REF_PATTERN_LSB, &read_value);
                    printf(" 0x%08X", read_value);
                }
                printf("\n");
                return EXIT_FAILURE;
            } else {
                printf("did %i R/W on a 32 bits reg with no error\n", repeats_per_cycle);
                ++cycle_number;
            }
        }
    } else if (test_number == 4) {
        /* databuffer R/W stress test */
        while ((quit_sig != 1) && (exit_sig != 1)) {
            for (i=0; i<BUFF_SIZE; ++i) {
                test_buff[i] = rand() & 0xFF;
            }
            printf("Cycle %i > ", cycle_number);
            test_addr = rand() & 0xFFFF;
            lgw_reg_w(LGW_RX_DATA_BUF_ADDR, test_addr); /* write at random offset in memory */
            lgw_reg_wb(LGW_RX_DATA_BUF_DATA, test_buff, BUFF_SIZE);
            lgw_reg_w(LGW_RX_DATA_BUF_ADDR, test_addr); /* go back to start of segment */
            lgw_reg_rb(LGW_RX_DATA_BUF_DATA, read_buff, BUFF_SIZE);
            for (i=0; ((i<BUFF_SIZE) && (test_buff[i] == read_buff[i])); ++i);
            if (i != BUFF_SIZE) {
                printf("error during the buffer comparison\n");
                printf("Written values:\n");
                for (i=0; i<BUFF_SIZE; ++i) {
                    printf(" %02X ", test_buff[i]);
                    if (i%16 == 15) printf("\n");
                }
                printf("\n");
                printf("Read values:\n");
                for (i=0; i<BUFF_SIZE; ++i) {
                    printf(" %02X ", read_buff[i]);
                    if (i%16 == 15) printf("\n");
                }
                printf("\n");
                lgw_reg_w(LGW_RX_DATA_BUF_ADDR, test_addr); /* go back to start of segment */
                lgw_reg_rb(LGW_RX_DATA_BUF_DATA, read_buff, BUFF_SIZE);
                printf("Re-read values:\n");
                for (i=0; i<BUFF_SIZE; ++i) {
                    printf(" %02X ", read_buff[i]);
                    if (i%16 == 15) printf("\n");
                }
                printf("\n");
                return EXIT_FAILURE;
            } else {
                printf("did a %i-byte R/W on a data buffer with no error\n", BUFF_SIZE);
                ++cycle_number;
            }
        }
    } else {
        MSG("ERROR: invalid test number");
        usage();
    }

    /* close SPI link */
    i = lgw_disconnect();
    if (i != LGW_REG_SUCCESS) {
        MSG("ERROR: lgw_disconnect() did not return SUCCESS");
        return EXIT_FAILURE;
    }

    MSG("INFO: Exiting LoRa concentrator SPI stress-test program\n");
    return EXIT_SUCCESS;
}
コード例 #3
0
int main(int argc, char **argv)
{
    static struct sigaction sigact; /* SIGQUIT&SIGINT&SIGTERM signal handling */

    int i; /* loop and temporary variables */

    /* Parameter parsing */
    int option_index = 0;
    static struct option long_options[] = {
        {"dig", 1, 0, 0},
        {"dac", 1, 0, 0},
        {"mix", 1, 0, 0},
        {"pa", 1, 0, 0},
        {"mod", 1, 0, 0},
        {"sf", 1, 0, 0},
        {"bw", 1, 0, 0},
        {"br", 1, 0, 0},
        {"fdev", 1, 0, 0},
        {"bt", 1, 0, 0},
        {"notch", 1, 0, 0},
        {0, 0, 0, 0}
    };
    unsigned int arg_u;
    float arg_f;
    char arg_s[64];

    /* Application parameters */
    uint32_t freq_hz = DEFAULT_FREQ_HZ;
    uint8_t g_dig = DEFAULT_DIGITAL_GAIN;
    uint8_t g_dac = DEFAULT_DAC_GAIN;
    uint8_t g_mix = DEFAULT_MIXER_GAIN;
    uint8_t g_pa = DEFAULT_PA_GAIN;
    char mod[64] = DEFAULT_MODULATION;
    uint8_t sf = DEFAULT_SF;
    unsigned int bw_khz = DEFAULT_BW_KHZ;
    float br_kbps = DEFAULT_BR_KBPS;
    uint8_t fdev_khz = DEFAULT_FDEV_KHZ;
    uint8_t bt = DEFAULT_BT;
    uint32_t tx_notch_freq = DEFAULT_NOTCH_FREQ;

    int32_t offset_i, offset_q;

    /* RF configuration (TX fail if RF chain is not enabled) */
    enum lgw_radio_type_e radio_type = LGW_RADIO_TYPE_SX1257;
    struct lgw_conf_board_s boardconf;
    struct lgw_conf_rxrf_s rfconf;
    struct lgw_tx_gain_lut_s txlut;
    struct lgw_pkt_tx_s txpkt;


    /* Parse command line options */
    while ((i = getopt_long (argc, argv, "hud::f:r:", long_options, &option_index)) != -1) {
        switch (i) {
            case 'h':
                printf("~~~ Library version string~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n");
                printf(" %s\n", lgw_version_info());
                printf("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n");
                printf(" -f      <float>  Tx RF frequency in MHz [800:1000]\n");
                printf(" -r      <int>    Radio type (SX1255:1255, SX1257:1257)\n");
                printf(" --notch <uint>   Tx notch filter frequency in KhZ [126..250]\n");
                printf(" --dig   <uint>   Digital gain trim, [0:3]\n");
                printf("                   0:1, 1:7/8, 2:3/4, 3:1/2\n");
                printf(" --mix   <uint>   Radio Tx mixer gain trim, [0:15]\n");
                printf("                   15 corresponds to maximum gain, 1 LSB corresponds to 2dB step\n");
                printf(" --pa    <uint>   PA gain trim, [0:3]\n");
                printf(" --mod   <char>   Modulation type ['LORA','FSK','CW']\n");
                printf(" --sf    <uint>   LoRa Spreading Factor, [7:12]\n");
                printf(" --bw    <uint>   LoRa bandwidth in kHz, [125,250,500]\n");
                printf(" --br    <float>  FSK bitrate in kbps, [0.5:250]\n");
                printf(" --fdev  <uint>   FSK frequency deviation in kHz, [1:250]\n");
                printf(" --bt    <uint>   FSK gaussian filter BT trim, [0:3]\n");
                printf("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n");
                return EXIT_SUCCESS;
                break;

            case 0:
                if (strcmp(long_options[option_index].name,"dig") == 0) {
                    i = sscanf(optarg, "%u", &arg_u);
                    if ((i != 1) || (arg_u > 3)) {
                        printf("ERROR: argument parsing of --dig argument. Use -h to print help\n");
                        return EXIT_FAILURE;
                    }
                    else
                    {
                        g_dig = (uint8_t)arg_u;
                    }
                }
                else if (strcmp(long_options[option_index].name,"dac") == 0) {
                    i = sscanf(optarg, "%u", &arg_u);
                    if ((i != 1) || (arg_u > 3)) {
                        printf("ERROR: argument parsing of --dac argument. Use -h to print help\n");
                        return EXIT_FAILURE;
                    }
                    else {
                        g_dac = (uint8_t)arg_u;
                    }
                }
                else if (strcmp(long_options[option_index].name,"mix") == 0) {
                    i = sscanf(optarg, "%u", &arg_u);
                    if ((i != 1) || (arg_u > 15)) {
                        printf("ERROR: argument parsing of --mix argument. Use -h to print help\n");
                        return EXIT_FAILURE;
                    }
                    else {
                        g_mix = (uint8_t)arg_u;
                    }
                }
                else if (strcmp(long_options[option_index].name,"pa") == 0) {
                    i = sscanf(optarg, "%u", &arg_u);
                    if ((i != 1) || (arg_u > 3)) {
                        printf("ERROR: argument parsing of --pa argument. Use -h to print help\n");
                        return EXIT_FAILURE;
                    }
                    else {
                        g_pa = arg_u;
                    }
                }
                else if (strcmp(long_options[option_index].name,"mod") == 0) {
                    i = sscanf(optarg, "%s", arg_s);
                    if ((i != 1) || ((strcmp(arg_s,"LORA") != 0) && (strcmp(arg_s,"FSK") != 0)  && (strcmp(arg_s,"CW") != 0))) {
                        printf("ERROR: argument parsing of --mod argument. Use -h to print help\n");
                        return EXIT_FAILURE;
                    }
                    else {
                        sprintf(mod, "%s", arg_s);
                    }
                }
                else if (strcmp(long_options[option_index].name,"sf") == 0) {
                    i = sscanf(optarg, "%u", &arg_u);
                    if ((i != 1) || (arg_u < 7) || (arg_u > 12)) {
                        printf("ERROR: argument parsing of --sf argument. Use -h to print help\n");
                        return EXIT_FAILURE;
                    }
                    else {
                        sf = (uint8_t)arg_u;
                    }
                }
                else if (strcmp(long_options[option_index].name,"bw") == 0) {
                    i = sscanf(optarg, "%u", &arg_u);
                    if ((i != 1) || ((arg_u != 125) && (arg_u != 250) && (arg_u != 500))) {
                        printf("ERROR: argument parsing of --bw argument. Use -h to print help\n");
                        return EXIT_FAILURE;
                    }
                    else {
                        bw_khz = arg_u;
                    }
                }
                else if (strcmp(long_options[option_index].name,"br") == 0) {
                    i = sscanf(optarg, "%f", &arg_f);
                    if ((i != 1) || (arg_f < 0.5) || (arg_f > 250)) {
                        printf("ERROR: argument parsing of --br argument. Use -h to print help\n");
                        return EXIT_FAILURE;
                    }
                    else {
                        br_kbps = arg_f;
                    }
                }
                else if (strcmp(long_options[option_index].name,"fdev") == 0) {
                    i = sscanf(optarg, "%u", &arg_u);
                    if ((i != 1) || (arg_u < 1) || (arg_u > 250)) {
                        printf("ERROR: argument parsing of --fdev argument. Use -h to print help\n");
                        return EXIT_FAILURE;
                    }
                    else {
                        fdev_khz = (uint8_t)arg_u;
                    }
                }
                else if (strcmp(long_options[option_index].name,"bt") == 0) {
                    i = sscanf(optarg, "%u", &arg_u);
                    if ((i != 1) || (arg_u > 3)) {
                        printf("ERROR: argument parsing of --bt argument. Use -h to print help\n");
                        return EXIT_FAILURE;
                    }
                    else {
                        bt = (uint8_t)arg_u;
                    }
                }
                else if (strcmp(long_options[option_index].name,"notch") == 0) {
                    i = sscanf(optarg, "%u", &arg_u);
                    if ((i != 1) || ((arg_u < 126) || (arg_u > 250))) {
                        printf("ERROR: argument parsing of --notch argument. Use -h to print help\n");
                        return EXIT_FAILURE;
                    }
                    else {
                        tx_notch_freq = (uint32_t)arg_u * 1000U;
                    }
                }
                else {
                    printf("ERROR: argument parsing options. Use -h to print help\n");
                    return EXIT_FAILURE;
                }
                break;

        case 'f':
            i = sscanf(optarg, "%f", &arg_f);
            if ((i != 1) || (arg_f < 1)) {
                printf("ERROR: argument parsing of -f argument. Use -h to print help\n");
                return EXIT_FAILURE;
            }
            else {
                freq_hz = (uint32_t)((arg_f * 1e6) + 0.5);
            }
            break;

        case 'r':
            i = sscanf(optarg, "%u", &arg_u);
            switch (arg_u) {
                case 1255:
                    radio_type = LGW_RADIO_TYPE_SX1255;
                    break;
                case 1257:
                    radio_type = LGW_RADIO_TYPE_SX1257;
                    break;
                default:
                    printf("ERROR: argument parsing of -r argument. Use -h to print help\n");
                    return EXIT_FAILURE;
            }
            break;

        default:
            printf("ERROR: argument parsing options. Use -h to print help\n");
            return EXIT_FAILURE;
        }
    }

    /* Configure signal handling */
    sigemptyset( &sigact.sa_mask );
    sigact.sa_flags = 0;
    sigact.sa_handler = sig_handler;
    sigaction( SIGQUIT, &sigact, NULL );
    sigaction( SIGINT, &sigact, NULL );
    sigaction( SIGTERM, &sigact, NULL );

    /* Board config */
    memset(&boardconf, 0, sizeof(boardconf));
    boardconf.lorawan_public = true;
    boardconf.clksrc = 1; /* Radio B is source by default */
    lgw_board_setconf(boardconf);

    /* RF config */
    memset(&rfconf, 0, sizeof(rfconf));
    rfconf.enable = true;
    rfconf.freq_hz = freq_hz;
    rfconf.rssi_offset = DEFAULT_RSSI_OFFSET;
    rfconf.type = radio_type;
    rfconf.tx_enable = true;
    rfconf.tx_notch_freq = tx_notch_freq;
    lgw_rxrf_setconf(TX_RF_CHAIN, rfconf);

    /* Tx gain LUT */
    memset(&txlut, 0, sizeof txlut);
    txlut.size = 1;
    txlut.lut[0].dig_gain = g_dig;
    txlut.lut[0].pa_gain = g_pa;
    txlut.lut[0].dac_gain = g_dac;
    txlut.lut[0].mix_gain = g_mix;
    txlut.lut[0].rf_power = 0;
    lgw_txgain_setconf(&txlut);

    /* Start the concentrator */
    i = lgw_start();
    if (i == LGW_HAL_SUCCESS) {
        MSG("INFO: concentrator started, packet can be sent\n");
    } else {
        MSG("ERROR: failed to start the concentrator\n");
        return EXIT_FAILURE;
    }

    /* fill-up payload and parameters */
    memset(&txpkt, 0, sizeof(txpkt));
    txpkt.freq_hz = freq_hz;
    txpkt.tx_mode = IMMEDIATE;
    txpkt.rf_chain = TX_RF_CHAIN;
    txpkt.rf_power = 0;
    if (strcmp(mod, "FSK") == 0) {
        txpkt.modulation = MOD_FSK;
        txpkt.datarate = br_kbps * 1e3;
    } else {
        txpkt.modulation = MOD_LORA;
        switch (bw_khz) {
            case 125: txpkt.bandwidth = BW_125KHZ; break;
            case 250: txpkt.bandwidth = BW_250KHZ; break;
            case 500: txpkt.bandwidth = BW_500KHZ; break;
            default:
                MSG("ERROR: invalid 'bw' variable\n");
                return EXIT_FAILURE;
        }
        switch (sf) {
            case  7: txpkt.datarate = DR_LORA_SF7;  break;
            case  8: txpkt.datarate = DR_LORA_SF8;  break;
            case  9: txpkt.datarate = DR_LORA_SF9;  break;
            case 10: txpkt.datarate = DR_LORA_SF10; break;
            case 11: txpkt.datarate = DR_LORA_SF11; break;
            case 12: txpkt.datarate = DR_LORA_SF12; break;
            default:
                MSG("ERROR: invalid 'sf' variable\n");
                return EXIT_FAILURE;
        }
    }
    txpkt.coderate = CR_LORA_4_5;
    txpkt.f_dev = fdev_khz;
    txpkt.preamble = 65535;
    txpkt.invert_pol = false;
    txpkt.no_crc = true;
    txpkt.no_header = true;
    txpkt.size = 1;
    txpkt.payload[0] = 0;

    /* Overwrite settings */
    lgw_reg_w(LGW_TX_MODE, 1); /* Tx continuous */
    lgw_reg_w(LGW_FSK_TX_GAUSSIAN_SELECT_BT, bt);
    if (strcmp(mod, "CW") == 0) {
        /* Enable signal generator with DC */
        lgw_reg_w(LGW_SIG_GEN_FREQ, 0);
        lgw_reg_w(LGW_SIG_GEN_EN, 1);
        lgw_reg_w(LGW_TX_OFFSET_I, 0);
        lgw_reg_w(LGW_TX_OFFSET_Q, 0);
    }

    /* Send packet */
    i = lgw_send(txpkt);

    /* Recap all settings */
    printf("SX1301 library version: %s\n", lgw_version_info());
    if (strcmp(mod, "LORA") == 0) {
        printf("Modulation: LORA SF:%d BW:%d kHz\n", sf, bw_khz);
    }
    else if (strcmp(mod, "FSK") == 0) {
        printf("Modulation: FSK BR:%3.3f kbps FDEV:%d kHz BT:%d\n", br_kbps, fdev_khz, bt);
    }
    else if (strcmp(mod, "CW") == 0) {
        printf("Modulation: CW\n");
    }
    switch(rfconf.type) {
        case LGW_RADIO_TYPE_SX1255:
            printf("Radio Type: SX1255\n");
            break;
        case LGW_RADIO_TYPE_SX1257:
            printf("Radio Type: SX1257\n");
            break;
        default:
            printf("ERROR: undefined radio type\n");
            break;
    }
    printf("Frequency: %4.3f MHz\n", freq_hz/1e6);
    printf("TX Gains: Digital:%d DAC:%d Mixer:%d PA:%d\n", g_dig, g_dac, g_mix, g_pa);
    if (strcmp(mod, "CW") != 0) {
        lgw_reg_r(LGW_TX_OFFSET_I, &offset_i);
        lgw_reg_r(LGW_TX_OFFSET_Q, &offset_q);
        printf("Calibrated DC offsets: I:%d Q:%d\n", offset_i, offset_q);
    }

    /* waiting for user input */
    while ((quit_sig != 1) && (exit_sig != 1)) {
        wait_ms(100);
    }

    /* clean up before leaving */
    lgw_stop();

    return 0;
}
コード例 #4
0
int main(int argc, char **argv)
{
	int i; /* temporary variable(s) */
	int32_t reg_val;
	
	/* user chosen parameters */
	double f1 = 0.0;
	double f2 = 0.0;
	double fs = 0.0;
	
	/* frequency scan parameters (default values) */
	uint32_t f_start = rf_rx_lowfreq_[RF_CHAIN]; /* in Hz */
	uint32_t f_stop = rf_rx_upfreq_[RF_CHAIN]; /* in Hz */
	uint32_t f_step = 200000; /* 200 kHz step by default */
	
	/* RSSI measurement results */
	int8_t rssi_max; /* max RSSI during X measurements */
	int high_count; /* nb of measurements above a threshold defined by maximum RSSI */
	
	/* clock, log file and log rotation management */
	FILE * log_file = NULL;
	char log_file_name[64];
	char iso_date[20];
	time_t now_time;
	
	/* variables for PLL register calculation */
	uint32_t f_target; /* loop variable */
	uint32_t freq_hz;
	uint32_t part_int;
	uint32_t part_frac;
	int cpt_attempts = 0;
	
	/* parse command line options */
	while ((i = getopt (argc, argv, "hf:")) != -1) {
		switch (i) {
			case 'h':
				usage();
				return EXIT_SUCCESS;
			
			case 'f':
				sscanf(optarg, "%lf:%lf:%lf", &f1, &f2, &fs);
				/* check configuration sanity */
				if (f2 < f1) {
					MSG("ERROR: stop frequency must be bigger than start frequency\n");
					return EXIT_FAILURE;
				}
				if ((f1 < 30.0) || (f1 > 3000.0)) {
					MSG("ERROR: invalid start frequency %f MHz\n", f1);
					return EXIT_FAILURE;
				}
				if ((f2 < 30.0) || (f2 > 3000.0)) {
					MSG("ERROR: invalid stop frequency %f MHz\n", f2);
					return EXIT_FAILURE;
				}
				f_start = (uint32_t)((f1*1e6) + 0.5); /* .5 Hz offset to get rounding instead of truncating */
				f_stop = (uint32_t)((f2*1e6) + 0.5);
				if (fs > 0.01) {
					f_step = (uint32_t)((fs*1e6) + 0.5);
				}
				break;
			
			default:
				MSG("ERROR: argument parsing use -h option for help\n");
				usage();
				return EXIT_FAILURE;
		}
	}
	printf("Scanning from %u Hz to %u Hz with a %u Hz frequency step\n", f_start, f_stop, f_step);
	
	/* configure signal handling */
	sigemptyset(&sigact.sa_mask);
	sigact.sa_flags = 0;
	sigact.sa_handler = sig_handler;
	sigaction(SIGQUIT, &sigact, NULL);
	sigaction(SIGINT, &sigact, NULL);
	sigaction(SIGTERM, &sigact, NULL);
	
	/* establish connection with concentrator and reset it */
	if (lgw_connect() == LGW_REG_ERROR) {
		MSG("ERROR: fail to connect to concentrator board\n");
		return EXIT_FAILURE;
	}
	lgw_soft_reset();
	
	/* Ungate concentrator clock, switch on the radios and reset them */
	lgw_reg_w(LGW_GLOBAL_EN, 1);
	lgw_reg_w(LGW_RADIO_A_EN,1);
	lgw_reg_w(LGW_RADIO_B_EN,1);
	wait_ms(500);
	lgw_reg_w(LGW_RADIO_RST,1);
	wait_ms(5);
	lgw_reg_w(LGW_RADIO_RST,0);
	wait_ms(5);
	
	/* enter basic parameters for the radio */
	sx125x_write_(RF_CHAIN, 0x10, SX125x_TX_DAC_CLK_SEL + SX125x_CLK_OUT*2);
	sx125x_write_(RF_CHAIN, 0x0C, 0 + SX125x_RX_BB_GAIN*2 + SX125x_RX_LNA_GAIN*32); /* not required, firmware should take care of that */
	sx125x_write_(RF_CHAIN, 0x0D, SX125x_RXBB_BW + SX125x_RX_ADC_TRIM*4 + SX125x_RX_ADC_BW*32);
	
	/* configure the IF and concentrator parameters */
	lgw_reg_w(LGW_IF_FREQ_0, -282); /* default -384 */
	lgw_reg_w(LGW_IF_FREQ_1, -128); /* default -128 */
	
	lgw_reg_w(LGW_RSSI_BB_FILTER_ALPHA,9); /* default 7 */
	lgw_reg_w(LGW_RSSI_DEC_FILTER_ALPHA,7); /* default 5 */
	lgw_reg_w(LGW_RSSI_CHANN_FILTER_ALPHA,3); /* default 8 */
	lgw_reg_w(LGW_RSSI_CHANN_DEFAULT_VALUE,90); /* default 100 */
	lgw_reg_w(LGW_RSSI_DEC_DEFAULT_VALUE,90); /* default 100 */
	
	/* Load firmware */
	load_firmware_(MCU_AGC, rssi_firmware, MCU_AGC_FW_BYTE);
	lgw_reg_w(LGW_FORCE_HOST_FE_CTRL,0);
	lgw_reg_w(LGW_FORCE_DEC_FILTER_GAIN,0);
	
	/* open log file */
	time(&now_time);
	strftime(iso_date,ARRAY_SIZE(iso_date),"%Y%m%dT%H%M%SZ",gmtime(&now_time)); /* format yyyymmddThhmmssZ */
	sprintf(log_file_name, "band_survey_%s.csv", iso_date);
	log_file = fopen(log_file_name, "a"); /* create log file, append if file already exist */
	if (log_file == NULL) {
		MSG("ERROR: impossible to create log file %s\n", log_file_name);
		return EXIT_FAILURE;
	}
	i = fprintf(log_file, "\"Frequency (Hz)\",\"RSSI (dB)\",\"high meas (nb)\"\n");
	if (i < 0) {
		MSG("ERROR: impossible to write to log file %s\n", log_file_name);
		return EXIT_FAILURE;
	}
	
	/* main loop */
	f_target = f_start;
	
	while ((quit_sig != 1) && (exit_sig != 1) && (f_target <= f_stop)) {
		
		/* set PLL to target frequency */
		freq_hz = f_target - MEAS_IF;
		
		#if (CFG_RADIO_1257 == 1)
		part_int = freq_hz / (SX125x_32MHz_FRAC << 8); /* integer part, gives the MSB */
		part_frac = ((freq_hz % (SX125x_32MHz_FRAC << 8)) << 8) / SX125x_32MHz_FRAC; /* fractional part, gives middle part and LSB */
		#elif (CFG_RADIO_1255 == 1)
		part_int = freq_hz / (SX125x_32MHz_FRAC << 7); /* integer part, gives the MSB */
		part_frac = ((freq_hz % (SX125x_32MHz_FRAC << 7)) << 9) / SX125x_32MHz_FRAC; /* fractional part, gives middle part and LSB */
		#endif
		
		sx125x_write_(RF_CHAIN, 0x01,0xFF & part_int); /* Most Significant Byte */
		sx125x_write_(RF_CHAIN, 0x02,0xFF & (part_frac >> 8)); /* middle byte */
		sx125x_write_(RF_CHAIN, 0x03,0xFF & part_frac); /* Least Significant Byte */
		
		/* start and PLL lock */
		cpt_attempts = 0;
		do {
			if (cpt_attempts >= PLL_LOCK_MAX_ATTEMPTS) {
				MSG("ERROR: fail to lock PLL\n");
				return -1;
			}
			sx125x_write_(RF_CHAIN, 0x00, 1); /* enable Xtal oscillator */
			sx125x_write_(RF_CHAIN, 0x00, 3); /* Enable RX (PLL+FE) */
			++cpt_attempts;
			wait_ms(1);
		} while((sx125x_read_(RF_CHAIN, 0x11) & 0x02) == 0);
		
		/* give control of the radio to the MCU and get it out of reset */
		lgw_reg_w(LGW_FORCE_HOST_RADIO_CTRL,0);
		lgw_reg_w(LGW_MCU_RST_1, 0);
		
		/* wait for the firmware to finish running and fetch the result */
		do {
			wait_ms(1);
			lgw_reg_r(LGW_MCU_AGC_STATUS, &reg_val);
		} while (reg_val != 1);
		
		lgw_reg_w(LGW_DBG_AGC_MCU_RAM_ADDR,0x20);
		lgw_reg_r(LGW_DBG_AGC_MCU_RAM_DATA, &reg_val);
		rssi_max = (int8_t)reg_val;
		
		lgw_reg_w(LGW_DBG_AGC_MCU_RAM_ADDR,0x21);
		lgw_reg_r(LGW_DBG_AGC_MCU_RAM_DATA, &reg_val);
		high_count = reg_val;
		
		lgw_reg_w(LGW_DBG_AGC_MCU_RAM_ADDR,0x22);
		lgw_reg_r(LGW_DBG_AGC_MCU_RAM_DATA, &reg_val);
		high_count += (reg_val << 8);
		
		/* log the measurement */
		i = fprintf(log_file, "%u, %i, %u\n", f_target, rssi_max, high_count);
		if (i < 0) {
			MSG("ERROR: impossible to write to log file %s\n", log_file_name);
			return EXIT_FAILURE;
		}
		
		/* reset MCU and take back control of radio */
		lgw_reg_w(LGW_MCU_RST_1, 1);
		lgw_reg_w(LGW_FORCE_HOST_RADIO_CTRL,1);
		
		/* iterate loop */
		f_target += f_step;
	}
	
	fclose(log_file);
	lgw_soft_reset();
	lgw_disconnect();
	
	printf("Exiting band survey program\n");
	return EXIT_SUCCESS;
}