// ------------------------------------------------------------------------------------------------ // Transmission test with polling of registers int radio_transmit_test(spi_parms_t *spi_parms, arguments_t *arguments) // ------------------------------------------------------------------------------------------------ { uint8_t test_length, tx_length, byte; uint8_t tx_buf[PI_CCxxx0_FIFO_SIZE]; int i, j, ret; uint32_t payload_fec = 4 + arguments->packet_length; // Number of bytes that can be protected by FEC uint64_t tx_delay; // Delay in microseconds for message transmission. Take 8 bytes guard interval. if (arguments->modulation == MOD_FSK4) { payload_fec /= 2; } if (arguments->fec) // twice the payload delay if FEC is engaged { tx_delay = (8000000ULL * (nb_preamble_bytes[arguments->preamble] + 4 + 2*payload_fec + 8)) / rate_values[arguments->rate]; } else { tx_delay = (8000000ULL * (nb_preamble_bytes[arguments->preamble] + 4 + payload_fec + 8)) / rate_values[arguments->rate]; } if (tx_delay < 100000ULL) // set a minimum wait time of 100ms { tx_delay = 100000ULL; } verbprintf(1, "Estimated Tx delay is %lld us\n", tx_delay); if (strlen(arguments->test_phrase) < PI_CCxxx0_FIFO_SIZE) { test_length = strlen(arguments->test_phrase); } else { verbprintf(0, "Test phrase too long. Truncated to CC1101 FIFO size\n"); test_length = PI_CCxxx0_FIFO_SIZE; } memset(tx_buf, ' ', PI_CCxxx0_FIFO_SIZE); memcpy(tx_buf, arguments->test_phrase, test_length); if (arguments->packet_length == 0) { tx_length = test_length; } else if (arguments->packet_length < PI_CCxxx0_FIFO_SIZE) { tx_length = arguments->packet_length; } else { tx_length = PI_CCxxx0_FIFO_SIZE; } radio_set_packet_length(spi_parms, tx_length); PI_CC_SPIWriteReg(spi_parms, PI_CCxxx0_IOCFG2, 0x02); // GDO2 output pin config TX mode PI_CC_SPIStrobe(spi_parms, PI_CCxxx0_SFTX); verbprintf(0, "Sending test packet of size %d %d times\n", tx_length, arguments->repetition); for (i=0; i<arguments->repetition; i++) { verbprintf(0, "Packet #%d\n", i); for (j=0; j<tx_length; j++) { PI_CC_SPIWriteReg(spi_parms, PI_CCxxx0_TXFIFO, tx_buf[j]); verbprintf(2, "%02X ", spi_parms->rx[0]); } verbprintf(2, "\n"); ret = PI_CC_SPIStrobe(spi_parms, PI_CCxxx0_STX); usleep(tx_delay); print_radio_status(spi_parms); } }
// ------------------------------------------------------------------------------------------------ // Reception test with polling of registers int radio_receive_test(spi_parms_t *spi_parms, arguments_t *arguments) // ------------------------------------------------------------------------------------------------ { uint8_t iterations, rx_bytes, fsm_state, rssi_dec, crc_lqi, x_byte, pkt_on; uint8_t rx_buf[PI_CCxxx0_FIFO_SIZE+1]; uint8_t rx_count; int i; uint32_t poll_us = 4*8000000 / rate_values[arguments->rate]; // 4 2-FSK symbols delay PI_CC_SPIWriteReg(spi_parms, PI_CCxxx0_IOCFG2, 0x00); // GDO2 output pin config RX mode PI_CC_SPIStrobe(spi_parms, PI_CCxxx0_SFRX); PI_CC_SPIStrobe(spi_parms, PI_CCxxx0_SRX); while(1) { PI_CC_SPIReadStatus(spi_parms, PI_CCxxx0_MARCSTATE, &fsm_state); fsm_state &= 0x1F; if (fsm_state == CCxxx0_STATE_RX) { break; } usleep(1000); } print_radio_status(spi_parms); for (iterations=0; iterations<arguments->repetition; iterations++) { verbprintf(0, "Packet #%d\n", iterations+1); pkt_on = 0; // wait for packet start memset(rx_buf, '\0', PI_CCxxx0_FIFO_SIZE+1); while(1) { PI_CC_SPIReadStatus(spi_parms, PI_CCxxx0_PKTSTATUS, &x_byte); // sense GDO0 (& 0x01) if (x_byte & 0x01) { pkt_on = 1; // started receiving a packet } if (!(x_byte & 0x01) && pkt_on) // packet received { PI_CC_SPIReadStatus(spi_parms, PI_CCxxx0_RXBYTES, &rx_count); rx_count &= PI_CCxxx0_NUM_RXBYTES; verbprintf(1, "Received %d bytes\n", rx_count); for (i=0; i<rx_count; i++) { PI_CC_SPIReadReg(spi_parms, PI_CCxxx0_RXFIFO, &(rx_buf[i])); } print_block(0, rx_buf, rx_count); break; } usleep(poll_us); } } verbprintf(0, "Done\n"); }
// ------------------------------------------------------------------------------------------------ int main (int argc, char **argv) // ------------------------------------------------------------------------------------------------ { int i, nbytes; // unsolicited termination handling struct sigaction sa; // Catch all signals possible on process exit! for (i = 1; i < 64; i++) { // skip SIGUSR2 for Wiring Pi if (i == 17) continue; // These are uncatchable or harmless or we want a core dump (SEGV) if (i != SIGKILL && i != SIGSEGV && i != SIGSTOP && i != SIGVTALRM && i != SIGWINCH && i != SIGPROF) { memset(&sa, 0, sizeof(sa)); sa.sa_handler = terminate; sigaction(i, &sa, NULL); } } // Set argument defaults init_args(&arguments); // Parse arguments argp_parse (&argp, argc, argv, 0, 0, &arguments); if (arguments.print_long_help) { print_long_help(); return 0; } if (!arguments.usbacm_device) { arguments.usbacm_device = strdup("/dev/ttyACM2"); } if (!arguments.serial_device) { arguments.serial_device = strdup("/var/ax25/axp2"); } if (!arguments.bulk_filename) { arguments.bulk_filename = strdup("-"); } set_serial_parameters(&serial_parms_ax25, arguments.serial_device, get_serial_speed(arguments.serial_speed, &arguments.serial_speed_n)); set_serial_parameters(&serial_parms_usb, arguments.usbacm_device, get_serial_speed(115200, &arguments.usb_speed_n)); init_radio_parms(&radio_parms, &arguments); if (arguments.verbose_level > 0) { print_args(&arguments); print_radio_parms(&radio_parms); fprintf(stderr, "\n"); } if (arguments.tnc_mode == TNC_KISS) { kiss_init(&arguments); kiss_run(&serial_parms_ax25, &serial_parms_usb, &radio_parms, &arguments); } else if (arguments.tnc_mode == TNC_SLIP) { arguments.slip = 1; kiss_init(&arguments); kiss_run(&serial_parms_ax25, &serial_parms_usb, &radio_parms, &arguments); } else if (arguments.tnc_mode == TNC_TEST_USB_ECHO) // This one does not need any access to the radio { usb_test_echo(&serial_parms_usb, &arguments); } else if (arguments.tnc_mode == TNC_RADIO_STATUS) { print_radio_status(&serial_parms_usb, &arguments); } else if (arguments.tnc_mode == TNC_RADIO_INIT) { init_radio(&serial_parms_usb, &radio_parms, &arguments); if (nbytes < 0) { fprintf(stderr, "Error\n"); } } else if (arguments.tnc_mode == TNC_TEST_TX) { radio_transmit_test(&serial_parms_usb, &radio_parms, &arguments); } else if (arguments.tnc_mode == TNC_TEST_RX) { radio_receive_test(&serial_parms_usb, &radio_parms, &arguments); } else if (arguments.tnc_mode == TNC_TEST_ECHO_TX) { radio_echo_test(&serial_parms_usb, &radio_parms, &arguments, 1); } else if (arguments.tnc_mode == TNC_TEST_ECHO_RX) { radio_echo_test(&serial_parms_usb, &radio_parms, &arguments, 0); } else if (arguments.tnc_mode == TNC_TEST_TX_PACKET) { radio_packet_transmit_test(&serial_parms_usb, &radio_parms, &arguments); } else if (arguments.tnc_mode == TNC_TEST_RX_PACKET) { radio_packet_receive_test(&serial_parms_usb, &radio_parms, &arguments); } else if (arguments.tnc_mode == TNC_TEST_RX_PACKET_NON_BLOCKING) { radio_packet_receive_nb_test(&serial_parms_usb, &radio_parms, &arguments); } else if (arguments.tnc_mode == TNC_BULK_TX) { file_bulk_transmit(&serial_parms_usb, &radio_parms, &arguments); } else if (arguments.tnc_mode == TNC_BULK_RX) { file_bulk_receive(&serial_parms_usb, &radio_parms, &arguments); } close_serial(&serial_parms_usb); close_serial(&serial_parms_ax25); delete_args(&arguments); return 0; }