2022-02-13 21:29:35 +01:00
|
|
|
#include <stdbool.h>
|
|
|
|
#include <malloc.h>
|
|
|
|
|
2022-02-27 16:02:51 +01:00
|
|
|
#include "results.h"
|
2022-02-13 21:29:35 +01:00
|
|
|
#include "tx.h"
|
|
|
|
|
|
|
|
static inline bool resize_buffer(layer1_tx_t *tx, size_t new_size)
|
|
|
|
{
|
|
|
|
void *tmpptr = realloc(tx->samples, new_size * sizeof(*(tx->samples)));
|
|
|
|
if(tmpptr) {
|
|
|
|
tx->samples = tmpptr;
|
|
|
|
tx->samples_allocated = new_size;
|
|
|
|
return true;
|
|
|
|
} else {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static inline bool can_append_n_samples(layer1_tx_t *tx, size_t samples)
|
|
|
|
{
|
|
|
|
return (tx->samples_used + samples) <= tx->samples_allocated;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static inline size_t get_free_space(layer1_tx_t *tx)
|
|
|
|
{
|
|
|
|
return tx->samples_allocated - tx->samples_used;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static inline float complex* get_write_ptr(layer1_tx_t *tx)
|
|
|
|
{
|
|
|
|
return tx->samples + tx->samples_used;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
result_t layer1_tx_init(layer1_tx_t *tx)
|
|
|
|
{
|
|
|
|
tx->samples = NULL;
|
|
|
|
tx->samples_allocated = 0;
|
|
|
|
tx->samples_used = 0;
|
|
|
|
|
|
|
|
transmission_init(&tx->transmission);
|
|
|
|
packet_mod_init(&tx->pmod);
|
|
|
|
return OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
result_t layer1_tx_shutdown(layer1_tx_t *tx)
|
|
|
|
{
|
|
|
|
if(tx->samples) {
|
|
|
|
free(tx->samples);
|
|
|
|
tx->samples = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
tx->samples_allocated = 0;
|
|
|
|
tx->samples_used = 0;
|
|
|
|
|
|
|
|
transmission_free(&tx->transmission);
|
|
|
|
packet_mod_free(&tx->pmod);
|
|
|
|
|
|
|
|
return OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
result_t layer1_tx_reset(layer1_tx_t *tx)
|
|
|
|
{
|
|
|
|
tx->samples_used = 0;
|
|
|
|
return OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
result_t layer1_tx_add_packet_to_burst(layer1_tx_t *tx, const uint8_t *data, size_t length)
|
|
|
|
{
|
|
|
|
if(tx->samples_used == 0) {
|
|
|
|
if(!resize_buffer(tx, 4096 + transmission_calculate_ramp_up_length(&tx->transmission))) {
|
|
|
|
return ERR_NO_MEM;
|
|
|
|
}
|
|
|
|
|
|
|
|
// nothing is in the buffer yet, so we must first generate a ramp-up.
|
|
|
|
size_t len = get_free_space(tx);
|
|
|
|
result_t res = transmission_ramp_up(&tx->transmission, get_write_ptr(tx), &len);
|
|
|
|
|
|
|
|
if(res != OK) {
|
2022-02-16 21:46:56 +01:00
|
|
|
fprintf(stderr, "Ramp-up requires %zd samples at offset %zd.\n", len, tx->samples_used);
|
2022-02-13 21:29:35 +01:00
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
|
|
|
tx->samples_used += len;
|
|
|
|
}
|
|
|
|
|
|
|
|
// encode and modulate the packet
|
|
|
|
packet_mod_set_data(&tx->pmod, data, length);
|
|
|
|
packet_mod_encode(&tx->pmod);
|
|
|
|
packet_mod_modulate(&tx->pmod);
|
|
|
|
packet_mod_add_header(&tx->pmod);
|
|
|
|
packet_mod_add_preamble(&tx->pmod);
|
|
|
|
|
|
|
|
// determine number of symbols in the packet
|
|
|
|
size_t nsyms;
|
|
|
|
packet_mod_get_result_cf(&tx->pmod, NULL, &nsyms);
|
|
|
|
|
|
|
|
// calculate the number of filtered samples
|
|
|
|
size_t filtered_size = transmission_calculate_packet_length(&tx->transmission, nsyms);
|
|
|
|
|
|
|
|
// resize the buffer if necessary (and add some reserve)
|
|
|
|
if(!can_append_n_samples(tx, filtered_size)) {
|
|
|
|
if(!resize_buffer(tx, tx->samples_allocated + 2*filtered_size)) {
|
|
|
|
return ERR_NO_MEM;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// store the packet symbols into a temporary buffer
|
|
|
|
float complex msg_mod[nsyms];
|
|
|
|
packet_mod_get_result_cf(&tx->pmod, msg_mod, &nsyms);
|
|
|
|
|
|
|
|
// filter the packet and append it to the output buffer
|
|
|
|
size_t len = get_free_space(tx);
|
|
|
|
result_t res = transmission_filter_packet(&tx->transmission, msg_mod, nsyms, get_write_ptr(tx), &len);
|
|
|
|
|
|
|
|
if(res != OK) {
|
2022-02-16 21:46:56 +01:00
|
|
|
fprintf(stderr, "Packet requires %zd samples at offset %zd.\n", len, tx->samples_used);
|
2022-02-13 21:29:35 +01:00
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
|
|
|
tx->samples_used += len;
|
|
|
|
|
|
|
|
return OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
result_t layer1_tx_finalize_burst(layer1_tx_t *tx)
|
|
|
|
{
|
|
|
|
// calculate the number of samples for the ramp down
|
|
|
|
size_t len = transmission_calculate_ramp_down_length(&tx->transmission);
|
|
|
|
|
|
|
|
// resize the buffer if necessary
|
|
|
|
if(!can_append_n_samples(tx, len)) {
|
|
|
|
if(!resize_buffer(tx, tx->samples_allocated + len)) {
|
|
|
|
return ERR_NO_MEM;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// generate the ramp-down
|
|
|
|
len = get_free_space(tx);
|
|
|
|
result_t res = transmission_ramp_down(&tx->transmission, get_write_ptr(tx), &len);
|
|
|
|
|
|
|
|
if(res != OK) {
|
2022-02-16 21:46:56 +01:00
|
|
|
fprintf(stderr, "Ramp-down requires %zd samples at offset %zd.\n", len, tx->samples_used);
|
2022-02-13 21:29:35 +01:00
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
|
|
|
tx->samples_used += len;
|
|
|
|
return OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
size_t layer1_tx_get_sample_count(const layer1_tx_t *tx)
|
|
|
|
{
|
|
|
|
return tx->samples_used;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const float complex* layer1_tx_get_sample_data(const layer1_tx_t *tx)
|
|
|
|
{
|
|
|
|
return tx->samples;
|
|
|
|
}
|