diff --git a/impl/CMakeLists.txt b/impl/CMakeLists.txt index f000aae..aa75737 100644 --- a/impl/CMakeLists.txt +++ b/impl/CMakeLists.txt @@ -53,6 +53,7 @@ target_link_libraries( ${CMAKE_PROJECT_NAME} libliquid.a m + rt fftw3f fec SoapySDR diff --git a/impl/src/config.h b/impl/src/config.h index a753bb0..6a33984 100644 --- a/impl/src/config.h +++ b/impl/src/config.h @@ -3,6 +3,12 @@ #include +/*** TIMING CONFIG ***/ + +#define TX_SWITCH_BACKOFF_PREAMBLE_MS 500 // only relevant if packet cannot be decoded +#define TX_SWITCH_BACKOFF_END_OF_PACKET_MS 1 +#define TX_SWITCH_BACKOFF_AFTER_RX_ON 500 // time the transceiver must stay in RX mode + /*** LAYER 1 CONFIG ***/ #define SYMBOL_RATE 100e3f diff --git a/impl/src/main.c b/impl/src/main.c index 69ca695..101f1c7 100644 --- a/impl/src/main.c +++ b/impl/src/main.c @@ -36,6 +36,14 @@ static int m_tunfd = -1; static bool m_running = true; +static double next_tx_switch_time = 0.0; + + +static void block_tx_for(unsigned offset_ms) +{ + next_tx_switch_time = get_hires_time() + (double)offset_ms * 0.001; +} + void print_complex_array(const char *varname, float complex const *array, size_t len) { fprintf(stderr, "%s=np.array([%f%+fj", varname, crealf(array[0]), cimagf(array[0])); @@ -101,9 +109,12 @@ void cb_rx(rx_evt_t evt, uint8_t *packet_data, size_t packet_len) break; case RX_EVT_PACKET_RECEIVED: - fprintf(stderr, "=== DECODED PAYLOAD (%4zu bytes) ===\n", packet_len); - hexdump(packet_data, packet_len); - fprintf(stderr, "====================================\n"); + fprintf(stderr, "A message of %zu bytes was decoded successfully.\n", packet_len); + //fprintf(stderr, "=== DECODED PAYLOAD (%4zu bytes) ===\n", packet_len); + //hexdump(packet_data, packet_len < 64 ? packet_len : 64); + //fprintf(stderr, "====================================\n"); + + block_tx_for(TX_SWITCH_BACKOFF_END_OF_PACKET_MS); ret = write(m_tunfd, packet_data, packet_len); if(ret < 0) { @@ -113,6 +124,7 @@ void cb_rx(rx_evt_t evt, uint8_t *packet_data, size_t packet_len) case RX_EVT_PREAMBLE_FOUND: fprintf(stderr, "Found preamble!\n"); + block_tx_for(TX_SWITCH_BACKOFF_PREAMBLE_MS); break; } } @@ -207,7 +219,9 @@ int main(void) unsigned rx_retries = 0; while(m_running) { - if(on_air || !layer1_rx_is_busy(&rx)) { + double now = get_hires_time(); + + if((now > next_tx_switch_time) && (on_air || !layer1_rx_is_busy(&rx))) { int ret = poll(&pfd, 1, 0); if(ret < 0) { perror("poll"); @@ -252,6 +266,8 @@ int main(void) RESULT_CHECK(sdr_start_rx(&sdr)); on_air = false; + + block_tx_for(TX_SWITCH_BACKOFF_AFTER_RX_ON); } } diff --git a/impl/src/utils.c b/impl/src/utils.c index cdef365..e5de856 100644 --- a/impl/src/utils.c +++ b/impl/src/utils.c @@ -1,5 +1,8 @@ #include +#include +#include + #include "utils.h" bool dump_array_cf(const float complex *data, size_t n, float T, const char *filename) @@ -64,3 +67,33 @@ err_close: fclose(f); return false; } + +double get_hires_time(void) +{ + struct timespec clk; + clock_gettime(CLOCK_MONOTONIC, &clk); + return clk.tv_sec + 1e-9 * clk.tv_nsec; +} + +void fsleep(double d) +{ + struct timespec ts; + + ts.tv_sec = (time_t)d; + ts.tv_nsec = (long)(1e9 * (d - (long)d)); + + nanosleep(&ts, NULL); +} + +void sleep_until(double hires_time) +{ + struct timespec tv; + int ret; + + tv.tv_sec = hires_time; + tv.tv_nsec = (uint64_t)(1e9 * hires_time) % 1000000000; + do { + ret = clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME, &tv, NULL); + } while(ret == EINTR); +} + diff --git a/impl/src/utils.h b/impl/src/utils.h index 5db5ad9..68d0e26 100644 --- a/impl/src/utils.h +++ b/impl/src/utils.h @@ -24,4 +24,8 @@ bool dump_array_cf(const float complex *data, size_t n, float T, const char *fil */ bool dump_array_f(const float *data, size_t n, float T, const char *filename); +void sleep_until(double hires_time); +void fsleep(double d); +double get_hires_time(void); + #endif // UTILS_H