Implement time-based carrier sensing
In the following events, the modem cannot switch to transmit mode for the given time: - after a preamble has been received, for 500 ms - after a packet has been successfully decoded, for 1 ms - after receive mode was initially enabled, for 500 ms Note that the times are that long to work around the RX/TX switching of the hackrf and can be hopefully reduced to <10 milliseconds in a later version.
This commit is contained in:
parent
886a78018f
commit
c8e0516e80
|
@ -53,6 +53,7 @@ target_link_libraries(
|
||||||
${CMAKE_PROJECT_NAME}
|
${CMAKE_PROJECT_NAME}
|
||||||
libliquid.a
|
libliquid.a
|
||||||
m
|
m
|
||||||
|
rt
|
||||||
fftw3f
|
fftw3f
|
||||||
fec
|
fec
|
||||||
SoapySDR
|
SoapySDR
|
||||||
|
|
|
@ -3,6 +3,12 @@
|
||||||
|
|
||||||
#include <liquid/liquid.h>
|
#include <liquid/liquid.h>
|
||||||
|
|
||||||
|
/*** 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 ***/
|
/*** LAYER 1 CONFIG ***/
|
||||||
|
|
||||||
#define SYMBOL_RATE 100e3f
|
#define SYMBOL_RATE 100e3f
|
||||||
|
|
|
@ -36,6 +36,14 @@
|
||||||
static int m_tunfd = -1;
|
static int m_tunfd = -1;
|
||||||
static bool m_running = true;
|
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)
|
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]));
|
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;
|
break;
|
||||||
|
|
||||||
case RX_EVT_PACKET_RECEIVED:
|
case RX_EVT_PACKET_RECEIVED:
|
||||||
fprintf(stderr, "=== DECODED PAYLOAD (%4zu bytes) ===\n", packet_len);
|
fprintf(stderr, "A message of %zu bytes was decoded successfully.\n", packet_len);
|
||||||
hexdump(packet_data, packet_len);
|
//fprintf(stderr, "=== DECODED PAYLOAD (%4zu bytes) ===\n", packet_len);
|
||||||
fprintf(stderr, "====================================\n");
|
//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);
|
ret = write(m_tunfd, packet_data, packet_len);
|
||||||
if(ret < 0) {
|
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:
|
case RX_EVT_PREAMBLE_FOUND:
|
||||||
fprintf(stderr, "Found preamble!\n");
|
fprintf(stderr, "Found preamble!\n");
|
||||||
|
block_tx_for(TX_SWITCH_BACKOFF_PREAMBLE_MS);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -207,7 +219,9 @@ int main(void)
|
||||||
unsigned rx_retries = 0;
|
unsigned rx_retries = 0;
|
||||||
|
|
||||||
while(m_running) {
|
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);
|
int ret = poll(&pfd, 1, 0);
|
||||||
if(ret < 0) {
|
if(ret < 0) {
|
||||||
perror("poll");
|
perror("poll");
|
||||||
|
@ -252,6 +266,8 @@ int main(void)
|
||||||
|
|
||||||
RESULT_CHECK(sdr_start_rx(&sdr));
|
RESULT_CHECK(sdr_start_rx(&sdr));
|
||||||
on_air = false;
|
on_air = false;
|
||||||
|
|
||||||
|
block_tx_for(TX_SWITCH_BACKOFF_AFTER_RX_ON);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,8 @@
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
|
#include <time.h>
|
||||||
|
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
|
|
||||||
bool dump_array_cf(const float complex *data, size_t n, float T, const char *filename)
|
bool dump_array_cf(const float complex *data, size_t n, float T, const char *filename)
|
||||||
|
@ -64,3 +67,33 @@ err_close:
|
||||||
fclose(f);
|
fclose(f);
|
||||||
return false;
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -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);
|
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
|
#endif // UTILS_H
|
||||||
|
|
Loading…
Reference in a new issue