#include #include #include "results.h" #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) { fprintf(stderr, "Ramp-up requires %zd samples at offset %zd.\n", len, tx->samples_used); 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) { fprintf(stderr, "Packet requires %zd samples at offset %zd.\n", len, tx->samples_used); 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) { fprintf(stderr, "Ramp-down requires %zd samples at offset %zd.\n", len, tx->samples_used); 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; }