void test_coderate(){ int i,j,next_coderate; sleep(3); for(i=0 ; i < 4 ; i ++){ switch(i){ case 0 : next_coderate=CR_LORA_4_5; break; case 1 : next_coderate=CR_LORA_4_6; break; case 2 : next_coderate=CR_LORA_4_7; break; case 3 : next_coderate=CR_LORA_4_8; break; default : break; } construct_start_msg(join_response.bandwidth, next_coderate,join_response.datarate, 14, join_response.size); lgw_send(join_response); sleep(1); join_response.coderate=next_coderate; for(j=0 ; j < MSG_PER_SETTING ; j++){ sleep(1); construct_msg(); lgw_send(join_response); } sleep(1); } construct_end_msg(); lgw_send(join_response); }
void test_bandwidth(){ int i,j,next_bandwidth; sleep(2); for(i=0 ; i < 2 ; i ++){ sleep(1); switch(i){ case 0 : next_bandwidth=BW_125KHZ; break; case 1 : next_bandwidth=BW_250KHZ; break; default : break; } construct_start_msg(next_bandwidth, join_response.coderate,join_response.datarate, 14, join_response.size); lgw_send(join_response); sleep(1); join_response.bandwidth=next_bandwidth; for(j=0 ; j < MSG_PER_SETTING ; j++){ sleep(1); construct_msg(); lgw_send(join_response); } } construct_end_msg(); lgw_send(join_response); }
void test_power(){ int i,j,next_power; sleep(2); for(i=0 ; i < 8 ; i ++){ next_power = 2 + i*2; construct_start_msg(join_response.bandwidth, join_response.coderate,join_response.datarate, next_power, join_response.size); lgw_send(join_response); sleep(1); join_response.rf_power = next_power; for(j=0 ; j < MSG_PER_SETTING; j++){ sleep(1); construct_msg(); lgw_send(join_response); } sleep(1); } construct_end_msg(); lgw_send(join_response); }
void test_packet(){ int i,j,next_packet_size; sleep(6); for(i=1 ; i < 10 ; i ++){ next_packet_size = i*5; construct_start_msg(join_response.bandwidth, join_response.coderate,join_response.datarate, 14, next_packet_size); lgw_send(join_response); sleep(1); join_response.payload[0] = 1; join_response.size=next_packet_size; for(j=0 ; j < MSG_PER_SETTING ; j++){ sleep(2); lgw_send(join_response); } sleep(2); } sleep(2); construct_end_msg(); lgw_send(join_response); }
void test_sf(){ int i,j,next_datarate; sleep(6); for(i=0 ; i < 6 ; i ++){ switch(i){ case 5 : next_datarate=DR_LORA_SF7; break; case 4 : next_datarate=DR_LORA_SF8; break; case 3 : next_datarate=DR_LORA_SF9; break; case 2 : next_datarate=DR_LORA_SF10; break; case 1 : next_datarate=DR_LORA_SF11; break; case 0 : next_datarate=DR_LORA_SF12; break; default : break; } construct_start_msg(join_response.bandwidth, join_response.coderate,next_datarate, 14, join_response.size); lgw_send(join_response); sleep(1); join_response.datarate=next_datarate; for(j=0 ; j < MSG_PER_SETTING ; j++){ sleep(1); construct_msg(); lgw_send(join_response); } sleep(1); } construct_end_msg(); lgw_send(join_response); }
void send_join_response(struct lgw_pkt_rx_s* received) { struct lgw_pkt_tx_s join_response; join_response.freq_hz = JOIN_RESPONSE_FREQ; join_response.tx_mode = TIMESTAMPED; join_response.count_us = received->count_us + JOIN_RESPONSE_DELAY; join_response.rf_chain = JOIN_RF_CHAIN; join_response.rf_power = JOIN_RESPONSE_POWER; join_response.modulation = MOD_LORA; join_response.bandwidth = BW_125KHZ; join_response.datarate = DR_LORA_SF12; join_response.coderate = CR_LORA_4_5; join_response.invert_pol = true; // join_response.f_dev: only for FSK join_response.preamble = 8; join_response.no_crc = false; join_response.no_header = false; join_response.size = 3; join_response.payload[0]= 0; join_response.payload[1]= 1; join_response.payload[2]= 2; lgw_send(join_response); }
void send_join_response(struct lgw_pkt_rx_s* received) { setParamTx(received); lgw_send(join_response); join_response.tx_mode = IMMEDIATE; UPDATE_TEST(); }
int main(int argc, char **argv) { int i; uint8_t status_var; /* user entry parameters */ int xi = 0; double xd = 0.0; /* application parameters */ uint32_t f_target = 0; /* target frequency - invalid default value, has to be specified by user */ int sf = 10; /* SF10 by default */ int cr = 1; /* CR1 aka 4/5 by default */ int bw = 125; /* 125kHz bandwidth by default */ int pow = 14; /* 14 dBm by default */ int preamb = 8; /* 8 symbol preamble by default */ int pl_size = 16; /* 16 bytes payload by default */ int delay = 1000; /* 1 second between packets by default */ int repeat = -1; /* by default, repeat until stopped */ bool invert = false; /* RF configuration (TX fail if RF chain is not enabled) */ enum lgw_radio_type_e radio_type = LGW_RADIO_TYPE_NONE; uint8_t clocksource = 1; /* Radio B is source by default */ struct lgw_conf_board_s boardconf; struct lgw_conf_rxrf_s rfconf; /* allocate memory for packet sending */ struct lgw_pkt_tx_s txpkt; /* array containing 1 outbound packet + metadata */ /* loop variables (also use as counters in the packet payload) */ uint16_t cycle_count = 0; /* parse command line options */ while ((i = getopt (argc, argv, "hif:b:s:c:p:l:z:t:x:r:k")) != -1) { switch (i) { case 'h': usage(); return EXIT_FAILURE; break; case 'f': /* -f <float> target frequency in MHz */ i = sscanf(optarg, "%lf", &xd); if ((i != 1) || (xd < 30.0) || (xd > 3000.0)) { MSG("ERROR: invalid TX frequency\n"); usage(); return EXIT_FAILURE; } else { f_target = (uint32_t)((xd*1e6) + 0.5); /* .5 Hz offset to get rounding instead of truncating */ } break; case 'b': /* -b <int> Modulation bandwidth in kHz */ i = sscanf(optarg, "%i", &xi); if ((i != 1) || ((xi != 125)&&(xi != 250)&&(xi != 500))) { MSG("ERROR: invalid LoRa bandwidth\n"); usage(); return EXIT_FAILURE; } else { bw = xi; } break; case 's': /* -s <int> Spreading Factor */ i = sscanf(optarg, "%i", &xi); if ((i != 1) || (xi < 7) || (xi > 12)) { MSG("ERROR: invalid spreading factor\n"); usage(); return EXIT_FAILURE; } else { sf = xi; } break; case 'c': /* -c <int> Coding Rate */ i = sscanf(optarg, "%i", &xi); if ((i != 1) || (xi < 1) || (xi > 4)) { MSG("ERROR: invalid coding rate\n"); usage(); return EXIT_FAILURE; } else { cr = xi; } break; case 'p': /* -p <int> RF power */ i = sscanf(optarg, "%i", &xi); if ((i != 1) || (xi < -60) || (xi > 60)) { MSG("ERROR: invalid RF power\n"); usage(); return EXIT_FAILURE; } else { pow = xi; } break; case 'l': /* -r <uint> preamble length (symbols) */ i = sscanf(optarg, "%i", &xi); if ((i != 1) || (xi < 6)) { MSG("ERROR: preamble length must be >6 symbols \n"); usage(); return EXIT_FAILURE; } else { preamb = xi; } break; case 'z': /* -z <uint> payload length (bytes) */ i = sscanf(optarg, "%i", &xi); if ((i != 1) || (xi <= 0)) { MSG("ERROR: invalid payload size\n"); usage(); return EXIT_FAILURE; } else { pl_size = xi; } break; case 't': /* -t <int> pause between packets (ms) */ i = sscanf(optarg, "%i", &xi); if ((i != 1) || (xi < 0)) { MSG("ERROR: invalid time between packets\n"); usage(); return EXIT_FAILURE; } else { delay = xi; } break; case 'x': /* -x <int> numbers of times the sequence is repeated */ i = sscanf(optarg, "%i", &xi); if ((i != 1) || (xi < -1)) { MSG("ERROR: invalid number of repeats\n"); usage(); return EXIT_FAILURE; } else { repeat = xi; } break; case 'r': /* <int> Radio type (1255, 1257) */ sscanf(optarg, "%i", &xi); switch (xi) { case 1255: radio_type = LGW_RADIO_TYPE_SX1255; break; case 1257: radio_type = LGW_RADIO_TYPE_SX1257; break; default: printf("ERROR: invalid radio type\n"); usage(); return EXIT_FAILURE; } break; case 'i': /* -i send packet using inverted modulation polarity */ invert = true; break; case 'k': /* <int> Concentrator clock source (Radio A or Radio B) */ sscanf(optarg, "%i", &xi); clocksource = (uint8_t)xi; break; default: MSG("ERROR: argument parsing\n"); usage(); return EXIT_FAILURE; } } /* check parameter sanity */ if (f_target == 0) { MSG("ERROR: frequency parameter not set, please use -f option to specify it.\n"); return EXIT_FAILURE; } if (radio_type == LGW_RADIO_TYPE_NONE) { MSG("ERROR: radio type parameter not properly set, please use -r option to specify it.\n"); return EXIT_FAILURE; } printf("Sending %i packets on %u Hz (BW %i kHz, SF %i, CR %i, %i bytes payload, %i symbols preamble) at %i dBm, with %i ms between each\n", repeat, f_target, bw, sf, cr, pl_size, preamb, pow, delay); /* 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); /* starting the concentrator */ /* board config */ memset(&boardconf, 0, sizeof(boardconf)); boardconf.lorawan_public = true; boardconf.clksrc = clocksource; lgw_board_setconf(boardconf); /* RF config */ memset(&rfconf, 0, sizeof(rfconf)); rfconf.enable = true; rfconf.freq_hz = f_target; rfconf.rssi_offset = DEFAULT_RSSI_OFFSET; rfconf.type = radio_type; rfconf.tx_enable = true; lgw_rxrf_setconf(RF_CHAIN, rfconf); 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 = f_target; txpkt.tx_mode = IMMEDIATE; txpkt.rf_chain = RF_CHAIN; txpkt.rf_power = pow; txpkt.modulation = MOD_LORA; switch (bw) { 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; } switch (cr) { case 1: txpkt.coderate = CR_LORA_4_5; break; case 2: txpkt.coderate = CR_LORA_4_6; break; case 3: txpkt.coderate = CR_LORA_4_7; break; case 4: txpkt.coderate = CR_LORA_4_8; break; default: MSG("ERROR: invalid 'cr' variable\n"); return EXIT_FAILURE; } txpkt.invert_pol = invert; txpkt.preamble = preamb; txpkt.size = pl_size; strcpy((char *)txpkt.payload, "TEST**abcdefghijklmnopqrstuvwxyz#0123456789#ABCDEFGHIJKLMNOPQRSTUVWXYZ#0123456789#abcdefghijklmnopqrstuvwxyz#0123456789#ABCDEFGHIJKLMNOPQRSTUVWXYZ#0123456789#abcdefghijklmnopqrstuvwxyz#0123456789#ABCDEFGHIJKLMNOPQRSTUVWXYZ#0123456789#abcdefghijklmnopqrs#" ); /* abc.. is for padding */ /* main loop */ cycle_count = 0; while ((repeat == -1) || (cycle_count < repeat)) { ++cycle_count; /* refresh counters in payload (big endian, for readability) */ txpkt.payload[4] = (uint8_t)(cycle_count >> 8); /* MSB */ txpkt.payload[5] = (uint8_t)(cycle_count & 0x00FF); /* LSB */ /* send packet */ printf("Sending packet number %u ...", cycle_count); i = lgw_send(txpkt); /* non-blocking scheduling of TX packet */ if (i != LGW_HAL_SUCCESS) { printf("ERROR\n"); return EXIT_FAILURE; } /* wait for packet to finish sending */ do { wait_ms(5); lgw_status(TX_STATUS, &status_var); /* get TX status */ } while (status_var != TX_FREE); printf("OK\n"); /* wait inter-packet delay */ wait_ms(delay); /* exit loop on user signals */ if ((quit_sig == 1) || (exit_sig == 1)) { break; } } /* clean up before leaving */ lgw_stop(); printf("Exiting LoRa concentrator TX test program\n"); return EXIT_SUCCESS; }
int main(int argc, char **argv) { int i; uint8_t status_var; /* user entry parameters */ int xi = 0; double xd = 0.0; uint32_t f_min; uint32_t f_max; /* application parameters */ uint32_t f_target = lowfreq[RF_CHAIN]/2 + upfreq[RF_CHAIN]/2; /* target frequency */ int sf = 10; /* SF10 by default */ int bw = 125; /* 125kHz bandwidth by default */ int pow = 14; /* 14 dBm by default */ int preamb = 8; /* 8 symbol preamble by default */ int pl_size = 16; /* 16 bytes payload by default */ int delay = 1000; /* 1 second between packets by default */ int repeat = -1; /* by default, repeat until stopped */ bool invert = false; /* RF configuration (TX fail if RF chain is not enabled) */ const struct lgw_conf_rxrf_s rfconf = {true, lowfreq[RF_CHAIN]}; /* allocate memory for packet sending */ struct lgw_pkt_tx_s txpkt; /* array containing 1 outbound packet + metadata */ /* loop variables (also use as counters in the packet payload) */ uint16_t cycle_count = 0; /* parse command line options */ while ((i = getopt (argc, argv, "hf:s:b:p:r:z:t:x:i")) != -1) { switch (i) { case 'h': usage(); return EXIT_FAILURE; break; case 'f': /* -f <float> target frequency in MHz */ i = sscanf(optarg, "%lf", &xd); if ((i != 1) || (xd < 30.0) || (xd > 3000.0)) { MSG("ERROR: invalid TX frequency\n"); usage(); return EXIT_FAILURE; } else { f_target = (uint32_t)((xd*1e6) + 0.5); /* .5 Hz offset to get rounding instead of truncating */ } break; case 's': /* -s <int> Spreading Factor */ i = sscanf(optarg, "%i", &xi); if ((i != 1) || (xi < 7) || (xi > 12)) { MSG("ERROR: invalid spreading factor\n"); usage(); return EXIT_FAILURE; } else { sf = xi; } break; case 'b': /* -b <int> Modulation bandwidth in kHz */ i = sscanf(optarg, "%i", &xi); if ((i != 1) || ((xi != 125)&&(xi != 250)&&(xi != 500))) { MSG("ERROR: invalid LoRa bandwidth\n"); usage(); return EXIT_FAILURE; } else { bw = xi; } break; case 'p': /* -p <int> RF power */ i = sscanf(optarg, "%i", &xi); if ((i != 1) || (xi < -60) || (xi > 60)) { MSG("ERROR: invalid RF power\n"); usage(); return EXIT_FAILURE; } else { pow = xi; } break; case 'r': /* -r <uint> preamble length (symbols) */ i = sscanf(optarg, "%i", &xi); if ((i != 1) || (xi < 6)) { MSG("ERROR: preamble length must be >6 symbols \n"); usage(); return EXIT_FAILURE; } else { preamb = xi; } break; case 'z': /* -z <uint> payload length (bytes) */ i = sscanf(optarg, "%i", &xi); if ((i != 1) || (xi <= 0)) { MSG("ERROR: invalid payload size\n"); usage(); return EXIT_FAILURE; } else { pl_size = xi; } break; case 't': /* -t <int> pause between packets (ms) */ i = sscanf(optarg, "%i", &xi); if ((i != 1) || (xi < 0)) { MSG("ERROR: invalid time between packets\n"); usage(); return EXIT_FAILURE; } else { delay = xi; } break; case 'x': /* -x <int> numbers of times the sequence is repeated */ i = sscanf(optarg, "%i", &xi); if ((i != 1) || (xi < -1)) { MSG("ERROR: invalid number of repeats\n"); usage(); return EXIT_FAILURE; } else { repeat = xi; } break; case 'i': /* -i send packet using inverted modulation polarity */ invert = true; break; default: MSG("ERROR: argument parsing\n"); usage(); return EXIT_FAILURE; } } /* check parameter sanity */ f_min = lowfreq[RF_CHAIN] + (500 * bw); f_max = upfreq[RF_CHAIN] - (500 * bw); if ((f_target < f_min) || (f_target > f_max)) { MSG("ERROR: frequency out of authorized band (accounting for modulation bandwidth)\n"); return EXIT_FAILURE; } printf("Sending %i packets on %u Hz (BW %i kHz, SF %i, %i bytes payload, %i symbols preamble) at %i dBm, with %i ms between each\n", repeat, f_target, bw, sf, pl_size, preamb, pow, delay); /* 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); /* starting the concentrator */ lgw_rxrf_setconf(RF_CHAIN, rfconf); 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 = f_target; txpkt.tx_mode = IMMEDIATE; txpkt.rf_chain = RF_CHAIN; txpkt.rf_power = pow; txpkt.modulation = MOD_LORA; switch (bw) { 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.invert_pol = invert; txpkt.preamble = preamb; txpkt.size = pl_size; strcpy((char *)txpkt.payload, "TEST**abcdefghijklmnopqrstuvwxyz0123456789" ); /* abc.. is for padding */ /* main loop */ cycle_count = 0; while ((repeat == -1) || (cycle_count < repeat)) { ++cycle_count; /* refresh counters in payload (big endian, for readability) */ txpkt.payload[4] = (uint8_t)(cycle_count >> 8); /* MSB */ txpkt.payload[5] = (uint8_t)(cycle_count & 0x00FF); /* LSB */ /* send packet */ printf("Sending packet number %u ...", cycle_count); i = lgw_send(txpkt); /* non-blocking scheduling of TX packet */ if (i != LGW_HAL_SUCCESS) { printf("ERROR\n"); return EXIT_FAILURE; } /* wait for packet to finish sending */ do { wait_ms(5); lgw_status(TX_STATUS, &status_var); /* get TX status */ } while (status_var != TX_FREE); printf("OK\n"); /* wait inter-packet delay */ wait_ms(delay); /* exit loop on user signals */ if ((quit_sig == 1) || (exit_sig == 1)) { break; } } /* clean up before leaving */ lgw_stop(); printf("Exiting LoRa concentrator TX test program\n"); return EXIT_SUCCESS; }
int main() { struct sigaction sigact; /* SIGQUIT&SIGINT&SIGTERM signal handling */ struct lgw_conf_rxrf_s rfconf; struct lgw_conf_rxif_s ifconf; struct lgw_pkt_rx_s rxpkt[4]; /* array containing up to 4 inbound packets metadata */ struct lgw_pkt_tx_s txpkt; /* configuration and metadata for an outbound packet */ struct lgw_pkt_rx_s *p; /* pointer on a RX packet */ int i, j; int nb_pkt; uint32_t tx_cnt = 0; unsigned long loop_cnt = 0; uint8_t status_var = 0; /* 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); /* beginning of LoRa concentrator-specific code */ printf("Beginning of test for loragw_hal.c\n"); printf("*** Library version information ***\n%s\n\n", lgw_version_info()); /* set configuration for RF chains */ memset(&rfconf, 0, sizeof(rfconf)); rfconf.enable = true; rfconf.freq_hz = F_RX_0; lgw_rxrf_setconf(0, rfconf); /* radio A, f0 */ rfconf.enable = true; rfconf.freq_hz = F_RX_1; lgw_rxrf_setconf(1, rfconf); /* radio B, f1 */ /* set configuration for LoRa multi-SF channels (bandwidth cannot be set) */ memset(&ifconf, 0, sizeof(ifconf)); ifconf.enable = true; ifconf.rf_chain = 0; ifconf.freq_hz = -300000; ifconf.datarate = DR_LORA_MULTI; lgw_rxif_setconf(0, ifconf); /* chain 0: LoRa 125kHz, all SF, on f0 - 0.3 MHz */ ifconf.enable = true; ifconf.rf_chain = 0; ifconf.freq_hz = 300000; ifconf.datarate = DR_LORA_MULTI; lgw_rxif_setconf(1, ifconf); /* chain 1: LoRa 125kHz, all SF, on f0 + 0.3 MHz */ ifconf.enable = true; ifconf.rf_chain = 1; ifconf.freq_hz = -300000; ifconf.datarate = DR_LORA_MULTI; lgw_rxif_setconf(2, ifconf); /* chain 2: LoRa 125kHz, all SF, on f1 - 0.3 MHz */ ifconf.enable = true; ifconf.rf_chain = 1; ifconf.freq_hz = 300000; ifconf.datarate = DR_LORA_MULTI; lgw_rxif_setconf(3, ifconf); /* chain 3: LoRa 125kHz, all SF, on f1 + 0.3 MHz */ #if (LGW_MULTI_NB >= 8) ifconf.enable = true; ifconf.rf_chain = 0; ifconf.freq_hz = -100000; ifconf.datarate = DR_LORA_MULTI; lgw_rxif_setconf(4, ifconf); /* chain 4: LoRa 125kHz, all SF, on f0 - 0.1 MHz */ ifconf.enable = true; ifconf.rf_chain = 0; ifconf.freq_hz = 100000; ifconf.datarate = DR_LORA_MULTI; lgw_rxif_setconf(5, ifconf); /* chain 5: LoRa 125kHz, all SF, on f0 + 0.1 MHz */ ifconf.enable = true; ifconf.rf_chain = 1; ifconf.freq_hz = -100000; ifconf.datarate = DR_LORA_MULTI; lgw_rxif_setconf(6, ifconf); /* chain 6: LoRa 125kHz, all SF, on f1 - 0.1 MHz */ ifconf.enable = true; ifconf.rf_chain = 1; ifconf.freq_hz = 100000; ifconf.datarate = DR_LORA_MULTI; lgw_rxif_setconf(7, ifconf); /* chain 7: LoRa 125kHz, all SF, on f1 + 0.1 MHz */ #endif /* set configuration for LoRa 'stand alone' channel */ memset(&ifconf, 0, sizeof(ifconf)); ifconf.enable = true; ifconf.rf_chain = 0; ifconf.freq_hz = 0; ifconf.bandwidth = BW_250KHZ; ifconf.datarate = DR_LORA_SF10; lgw_rxif_setconf(8, ifconf); /* chain 8: LoRa 250kHz, SF10, on f0 MHz */ /* set configuration for FSK channel */ memset(&ifconf, 0, sizeof(ifconf)); ifconf.enable = true; ifconf.rf_chain = 1; ifconf.freq_hz = 0; ifconf.bandwidth = BW_250KHZ; ifconf.datarate = 64000; lgw_rxif_setconf(9, ifconf); /* chain 9: FSK 64kbps, on f1 MHz */ /* set configuration for TX packet */ memset(&txpkt, 0, sizeof(txpkt)); txpkt.freq_hz = F_TX; txpkt.tx_mode = IMMEDIATE; txpkt.rf_power = 10; txpkt.modulation = MOD_LORA; txpkt.bandwidth = BW_250KHZ; txpkt.datarate = DR_LORA_SF10; txpkt.coderate = CR_LORA_4_5; strcpy((char *)txpkt.payload, "TX.TEST.LORA.GW.????" ); txpkt.size = 20; txpkt.preamble = 6; txpkt.rf_chain = 0; /* memset(&txpkt, 0, sizeof(txpkt)); txpkt.freq_hz = F_TX; txpkt.tx_mode = IMMEDIATE; txpkt.rf_power = 10; txpkt.modulation = MOD_FSK; txpkt.f_dev = 50; txpkt.datarate = 64000; strcpy((char *)txpkt.payload, "TX.TEST.LORA.GW.????" ); txpkt.size = 20; txpkt.preamble = 4; txpkt.rf_chain = 0; */ /* connect, configure and start the LoRa concentrator */ i = lgw_start(); if (i == LGW_HAL_SUCCESS) { printf("*** Concentrator started ***\n"); } else { printf("*** Impossible to start concentrator ***\n"); return -1; } /* once configured, dump content of registers to a file, for reference */ // FILE * reg_dump = NULL; // reg_dump = fopen("reg_dump.log", "w"); // if (reg_dump != NULL) { // lgw_reg_check(reg_dump); // fclose(reg_dump); // } while ((quit_sig != 1) && (exit_sig != 1)) { loop_cnt++; /* fetch N packets */ nb_pkt = lgw_receive(ARRAY_SIZE(rxpkt), rxpkt); if (nb_pkt == 0) { wait_ms(300); } else { /* display received packets */ for(i=0; i < nb_pkt; ++i) { p = &rxpkt[i]; printf("---\nRcv pkt #%d >>", i+1); if (p->status == STAT_CRC_OK) { printf(" if_chain:%2d", p->if_chain); printf(" tstamp:%010u", p->count_us); printf(" size:%3u", p->size); switch (p-> modulation) { case MOD_LORA: printf(" LoRa"); break; case MOD_FSK: printf(" FSK"); break; default: printf(" modulation?"); } switch (p->datarate) { case DR_LORA_SF7: printf(" SF7"); break; case DR_LORA_SF8: printf(" SF8"); break; case DR_LORA_SF9: printf(" SF9"); break; case DR_LORA_SF10: printf(" SF10"); break; case DR_LORA_SF11: printf(" SF11"); break; case DR_LORA_SF12: printf(" SF12"); break; default: printf(" datarate?"); } switch (p->coderate) { case CR_LORA_4_5: printf(" CR1(4/5)"); break; case CR_LORA_4_6: printf(" CR2(2/3)"); break; case CR_LORA_4_7: printf(" CR3(4/7)"); break; case CR_LORA_4_8: printf(" CR4(1/2)"); break; default: printf(" coderate?"); } printf("\n"); printf(" RSSI:%+6.1f SNR:%+5.1f (min:%+5.1f, max:%+5.1f) payload:\n", p->rssi, p->snr, p->snr_min, p->snr_max); for (j = 0; j < p->size; ++j) { printf(" %02X", p->payload[j]); } printf(" #\n"); } else if (p->status == STAT_CRC_BAD) { printf(" if_chain:%2d", p->if_chain); printf(" tstamp:%010u", p->count_us); printf(" size:%3u\n", p->size); printf(" CRC error, damaged packet\n\n"); } else if (p->status == STAT_NO_CRC){ printf(" if_chain:%2d", p->if_chain); printf(" tstamp:%010u", p->count_us); printf(" size:%3u\n", p->size); printf(" no CRC\n\n"); } else { printf(" if_chain:%2d", p->if_chain); printf(" tstamp:%010u", p->count_us); printf(" size:%3u\n", p->size); printf(" invalid status ?!?\n\n"); } } } /* send a packet every X loop */ if (loop_cnt%16 == 0) { /* 32b counter in the payload, big endian */ txpkt.payload[16] = 0xff & (tx_cnt >> 24); txpkt.payload[17] = 0xff & (tx_cnt >> 16); txpkt.payload[18] = 0xff & (tx_cnt >> 8); txpkt.payload[19] = 0xff & tx_cnt; i = lgw_send(txpkt); /* non-blocking scheduling of TX packet */ j = 0; printf("+++\nSending packet #%d, rf path %d, return %d\nstatus -> ", tx_cnt, txpkt.rf_chain, i); do { ++j; wait_ms(100); lgw_status(TX_STATUS, &status_var); /* get TX status */ printf("%d:", status_var); } while ((status_var != TX_FREE) && (j < 100)); ++tx_cnt; printf("\nTX finished\n"); } }
int main(int argc, char **argv) { struct sigaction sigact; /* SIGQUIT&SIGINT&SIGTERM signal handling */ struct lgw_conf_board_s boardconf; struct lgw_conf_rxrf_s rfconf; struct lgw_conf_rxif_s ifconf; struct lgw_pkt_rx_s rxpkt[4]; /* array containing up to 4 inbound packets metadata */ struct lgw_pkt_tx_s txpkt; /* configuration and metadata for an outbound packet */ struct lgw_pkt_rx_s *p; /* pointer on a RX packet */ int i, j; int nb_pkt; uint32_t fa = 0, fb = 0, ft = 0; enum lgw_radio_type_e radio_type = LGW_RADIO_TYPE_NONE; uint8_t clocksource = 0; /* Radio A is source in MTAC-LORA */ uint32_t tx_cnt = 0; unsigned long loop_cnt = 0; uint8_t status_var = 0; double xd = 0.0; int xi = 0; /* parse command line options */ while ((i = getopt (argc, argv, "ha:b:t:r:k:")) != -1) { switch (i) { case 'h': usage(); return -1; break; case 'a': /* <float> Radio A RX frequency in MHz */ sscanf(optarg, "%lf", &xd); fa = (uint32_t)((xd*1e6) + 0.5); /* .5 Hz offset to get rounding instead of truncating */ break; case 'b': /* <float> Radio B RX frequency in MHz */ sscanf(optarg, "%lf", &xd); fb = (uint32_t)((xd*1e6) + 0.5); /* .5 Hz offset to get rounding instead of truncating */ break; case 't': /* <float> Radio TX frequency in MHz */ sscanf(optarg, "%lf", &xd); ft = (uint32_t)((xd*1e6) + 0.5); /* .5 Hz offset to get rounding instead of truncating */ break; case 'r': /* <int> Radio type (1255, 1257) */ sscanf(optarg, "%i", &xi); switch (xi) { case 1255: radio_type = LGW_RADIO_TYPE_SX1255; break; case 1257: radio_type = LGW_RADIO_TYPE_SX1257; break; default: printf("ERROR: invalid radio type\n"); usage(); return -1; } break; case 'k': /* <int> Concentrator clock source (Radio A or Radio B) */ sscanf(optarg, "%i", &xi); clocksource = (uint8_t)xi; break; default: printf("ERROR: argument parsing\n"); usage(); return -1; } } /* check input parameters */ if ((fa == 0) || (fb == 0) || (ft == 0)) { printf("ERROR: missing frequency input parameter:\n"); printf(" Radio A RX: %u\n", fa); printf(" Radio B RX: %u\n", fb); printf(" Radio TX: %u\n", ft); usage(); return -1; } if (radio_type == LGW_RADIO_TYPE_NONE) { printf("ERROR: missing radio type parameter:\n"); usage(); return -1; } /* 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); /* beginning of LoRa concentrator-specific code */ printf("Beginning of test for loragw_hal.c\n"); printf("*** Library version information ***\n%s\n\n", lgw_version_info()); /* set configuration for board */ memset(&boardconf, 0, sizeof(boardconf)); boardconf.lorawan_public = true; boardconf.clksrc = clocksource; lgw_board_setconf(boardconf); /* set configuration for RF chains */ memset(&rfconf, 0, sizeof(rfconf)); rfconf.enable = true; rfconf.freq_hz = fa; rfconf.rssi_offset = DEFAULT_RSSI_OFFSET; rfconf.type = radio_type; rfconf.tx_enable = true; lgw_rxrf_setconf(0, rfconf); /* radio A, f0 */ rfconf.enable = true; rfconf.freq_hz = fb; rfconf.rssi_offset = DEFAULT_RSSI_OFFSET; rfconf.type = radio_type; rfconf.tx_enable = false; lgw_rxrf_setconf(1, rfconf); /* radio B, f1 */ /* set configuration for LoRa multi-SF channels (bandwidth cannot be set) */ memset(&ifconf, 0, sizeof(ifconf)); ifconf.enable = true; ifconf.rf_chain = 0; ifconf.freq_hz = -300000; ifconf.datarate = DR_LORA_MULTI; lgw_rxif_setconf(0, ifconf); /* chain 0: LoRa 125kHz, all SF, on f0 - 0.3 MHz */ ifconf.enable = true; ifconf.rf_chain = 0; ifconf.freq_hz = 300000; ifconf.datarate = DR_LORA_MULTI; lgw_rxif_setconf(1, ifconf); /* chain 1: LoRa 125kHz, all SF, on f0 + 0.3 MHz */ ifconf.enable = true; ifconf.rf_chain = 1; ifconf.freq_hz = -300000; ifconf.datarate = DR_LORA_MULTI; lgw_rxif_setconf(2, ifconf); /* chain 2: LoRa 125kHz, all SF, on f1 - 0.3 MHz */ ifconf.enable = true; ifconf.rf_chain = 1; ifconf.freq_hz = 300000; ifconf.datarate = DR_LORA_MULTI; lgw_rxif_setconf(3, ifconf); /* chain 3: LoRa 125kHz, all SF, on f1 + 0.3 MHz */ ifconf.enable = true; ifconf.rf_chain = 0; ifconf.freq_hz = -100000; ifconf.datarate = DR_LORA_MULTI; lgw_rxif_setconf(4, ifconf); /* chain 4: LoRa 125kHz, all SF, on f0 - 0.1 MHz */ ifconf.enable = true; ifconf.rf_chain = 0; ifconf.freq_hz = 100000; ifconf.datarate = DR_LORA_MULTI; lgw_rxif_setconf(5, ifconf); /* chain 5: LoRa 125kHz, all SF, on f0 + 0.1 MHz */ ifconf.enable = true; ifconf.rf_chain = 1; ifconf.freq_hz = -100000; ifconf.datarate = DR_LORA_MULTI; lgw_rxif_setconf(6, ifconf); /* chain 6: LoRa 125kHz, all SF, on f1 - 0.1 MHz */ ifconf.enable = true; ifconf.rf_chain = 1; ifconf.freq_hz = 100000; ifconf.datarate = DR_LORA_MULTI; lgw_rxif_setconf(7, ifconf); /* chain 7: LoRa 125kHz, all SF, on f1 + 0.1 MHz */ /* set configuration for LoRa 'stand alone' channel */ memset(&ifconf, 0, sizeof(ifconf)); ifconf.enable = true; ifconf.rf_chain = 0; ifconf.freq_hz = 0; ifconf.bandwidth = BW_250KHZ; ifconf.datarate = DR_LORA_SF10; lgw_rxif_setconf(8, ifconf); /* chain 8: LoRa 250kHz, SF10, on f0 MHz */ /* set configuration for FSK channel */ memset(&ifconf, 0, sizeof(ifconf)); ifconf.enable = true; ifconf.rf_chain = 1; ifconf.freq_hz = 0; ifconf.bandwidth = BW_250KHZ; ifconf.datarate = 64000; lgw_rxif_setconf(9, ifconf); /* chain 9: FSK 64kbps, on f1 MHz */ /* set configuration for TX packet */ memset(&txpkt, 0, sizeof(txpkt)); txpkt.freq_hz = ft; txpkt.tx_mode = IMMEDIATE; txpkt.rf_power = 10; txpkt.modulation = MOD_LORA; txpkt.bandwidth = BW_250KHZ; txpkt.datarate = DR_LORA_SF10; txpkt.coderate = CR_LORA_4_5; strcpy((char *)txpkt.payload, "TX.TEST.LORA.GW.????" ); txpkt.size = 20; txpkt.preamble = 6; txpkt.rf_chain = 0; /* memset(&txpkt, 0, sizeof(txpkt)); txpkt.freq_hz = F_TX; txpkt.tx_mode = IMMEDIATE; txpkt.rf_power = 10; txpkt.modulation = MOD_FSK; txpkt.f_dev = 50; txpkt.datarate = 64000; strcpy((char *)txpkt.payload, "TX.TEST.LORA.GW.????" ); txpkt.size = 20; txpkt.preamble = 4; txpkt.rf_chain = 0; */ /* connect, configure and start the LoRa concentrator */ i = lgw_start(); if (i == LGW_HAL_SUCCESS) { printf("*** Concentrator started ***\n"); } else { printf("*** Impossible to start concentrator ***\n"); return -1; } /* once configured, dump content of registers to a file, for reference */ // FILE * reg_dump = NULL; // reg_dump = fopen("reg_dump.log", "w"); // if (reg_dump != NULL) { // lgw_reg_check(reg_dump); // fclose(reg_dump); // } while ((quit_sig != 1) && (exit_sig != 1)) { loop_cnt++; /* fetch N packets */ nb_pkt = lgw_receive(ARRAY_SIZE(rxpkt), rxpkt); if (nb_pkt == 0) { wait_ms(300); } else { /* display received packets */ for(i=0; i < nb_pkt; ++i) { p = &rxpkt[i]; printf("---\nRcv pkt #%d >>", i+1); if (p->status == STAT_CRC_OK) { printf(" if_chain:%2d", p->if_chain); printf(" tstamp:%010u", p->count_us); printf(" size:%3u", p->size); switch (p-> modulation) { case MOD_LORA: printf(" LoRa"); break; case MOD_FSK: printf(" FSK"); break; default: printf(" modulation?"); } switch (p->datarate) { case DR_LORA_SF7: printf(" SF7"); break; case DR_LORA_SF8: printf(" SF8"); break; case DR_LORA_SF9: printf(" SF9"); break; case DR_LORA_SF10: printf(" SF10"); break; case DR_LORA_SF11: printf(" SF11"); break; case DR_LORA_SF12: printf(" SF12"); break; default: printf(" datarate?"); } switch (p->coderate) { case CR_LORA_4_5: printf(" CR1(4/5)"); break; case CR_LORA_4_6: printf(" CR2(2/3)"); break; case CR_LORA_4_7: printf(" CR3(4/7)"); break; case CR_LORA_4_8: printf(" CR4(1/2)"); break; default: printf(" coderate?"); } printf("\n"); printf(" RSSI:%+6.1f SNR:%+5.1f (min:%+5.1f, max:%+5.1f) payload:\n", p->rssi, p->snr, p->snr_min, p->snr_max); for (j = 0; j < p->size; ++j) { printf(" %02X", p->payload[j]); } printf(" #\n"); } else if (p->status == STAT_CRC_BAD) { printf(" if_chain:%2d", p->if_chain); printf(" tstamp:%010u", p->count_us); printf(" size:%3u\n", p->size); printf(" CRC error, damaged packet\n\n"); } else if (p->status == STAT_NO_CRC){ printf(" if_chain:%2d", p->if_chain); printf(" tstamp:%010u", p->count_us); printf(" size:%3u\n", p->size); printf(" no CRC\n\n"); } else { printf(" if_chain:%2d", p->if_chain); printf(" tstamp:%010u", p->count_us); printf(" size:%3u\n", p->size); printf(" invalid status ?!?\n\n"); } } } /* send a packet every X loop */ if (loop_cnt%16 == 0) { /* 32b counter in the payload, big endian */ txpkt.payload[16] = 0xff & (tx_cnt >> 24); txpkt.payload[17] = 0xff & (tx_cnt >> 16); txpkt.payload[18] = 0xff & (tx_cnt >> 8); txpkt.payload[19] = 0xff & tx_cnt; i = lgw_send(txpkt); /* non-blocking scheduling of TX packet */ j = 0; printf("+++\nSending packet #%d, rf path %d, return %d\nstatus -> ", tx_cnt, txpkt.rf_chain, i); do { ++j; wait_ms(100); lgw_status(TX_STATUS, &status_var); /* get TX status */ printf("%d:", status_var); } while ((status_var != TX_FREE) && (j < 100)); ++tx_cnt; printf("\nTX finished\n"); } }
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; }