120 lines
2.7 KiB
C
120 lines
2.7 KiB
C
#include <math.h>
|
|
|
|
#include "transmission.h"
|
|
|
|
#include "config.h"
|
|
|
|
result_t transmission_init(transmission_ctx_t *ctx)
|
|
{
|
|
ctx->rrc_interp = firinterp_crcf_create_prototype(LIQUID_FIRFILT_RRC, RRC_SPS, RRC_DELAY, RRC_BETA, 0);
|
|
return OK;
|
|
}
|
|
|
|
|
|
result_t transmission_free(transmission_ctx_t *ctx)
|
|
{
|
|
firinterp_crcf_destroy(ctx->rrc_interp);
|
|
|
|
return OK;
|
|
}
|
|
|
|
|
|
result_t transmission_ramp_up(transmission_ctx_t *ctx, float complex *output, size_t *output_size)
|
|
{
|
|
if(*output_size < RRC_SPS*TRANSMISSION_RAMP_UP_LEN) {
|
|
*output_size = RRC_SPS*TRANSMISSION_RAMP_UP_LEN;
|
|
return ERR_SIZE;
|
|
}
|
|
|
|
// ramp up alternating ±1 symbols following a sin(t)^2 curve
|
|
for(size_t i = 0; i < TRANSMISSION_RAMP_UP_LEN; i++) {
|
|
float s = sinf((float)M_PI / 2.0f * i / TRANSMISSION_RAMP_UP_LEN);
|
|
float symbol = s*s;
|
|
|
|
if((i % 2) != 0) {
|
|
symbol = -symbol;
|
|
}
|
|
|
|
firinterp_crcf_execute(ctx->rrc_interp, symbol, output + (RRC_SPS*i));
|
|
}
|
|
|
|
*output_size = RRC_SPS*TRANSMISSION_RAMP_UP_LEN;
|
|
|
|
return OK;
|
|
}
|
|
|
|
|
|
result_t transmission_ramp_down(transmission_ctx_t *ctx, float complex *output, size_t *output_size)
|
|
{
|
|
const size_t total_symbols = TRANSMISSION_RAMP_DOWN_LEN + 2*RRC_DELAY;
|
|
if(*output_size < RRC_SPS*total_symbols) {
|
|
*output_size = RRC_SPS*total_symbols;
|
|
return ERR_SIZE;
|
|
}
|
|
|
|
// ramp down alternating ±1 symbols following a cos(t)^2 curve
|
|
for(size_t i = 0; i < TRANSMISSION_RAMP_DOWN_LEN; i++) {
|
|
float s = cosf((float)M_PI / 2.0f * i / TRANSMISSION_RAMP_DOWN_LEN);
|
|
float symbol = s*s;
|
|
|
|
if((i % 2) != 0) {
|
|
symbol = -symbol;
|
|
}
|
|
|
|
firinterp_crcf_execute(ctx->rrc_interp, symbol, output + (RRC_SPS*i));
|
|
}
|
|
|
|
// add 2*RRC_DELAY zeros to flush the filter history
|
|
for(size_t i = 0; i < 2*RRC_DELAY; i++) {
|
|
firinterp_crcf_execute(ctx->rrc_interp, 0.0f, output + (RRC_SPS*(TRANSMISSION_RAMP_DOWN_LEN+i)));
|
|
}
|
|
|
|
*output_size = RRC_SPS*total_symbols;
|
|
|
|
return OK;
|
|
}
|
|
|
|
|
|
result_t transmission_filter_packet(
|
|
transmission_ctx_t *ctx,
|
|
const float complex *packet,
|
|
size_t packet_size,
|
|
float complex *output,
|
|
size_t *output_size)
|
|
{
|
|
if(*output_size < RRC_SPS*packet_size) {
|
|
*output_size = RRC_SPS*packet_size;
|
|
return ERR_SIZE;
|
|
}
|
|
|
|
// ramp down alternating ±1 symbols following a cos(t)^2 curve
|
|
for(size_t i = 0; i < packet_size; i++) {
|
|
firinterp_crcf_execute(ctx->rrc_interp, packet[i], output + (RRC_SPS*i));
|
|
}
|
|
|
|
*output_size = RRC_SPS*packet_size;
|
|
|
|
return OK;
|
|
}
|
|
|
|
|
|
size_t transmission_calculate_ramp_up_length(transmission_ctx_t *ctx)
|
|
{
|
|
(void)ctx;
|
|
return RRC_SPS * TRANSMISSION_RAMP_UP_LEN;
|
|
}
|
|
|
|
|
|
size_t transmission_calculate_ramp_down_length(transmission_ctx_t *ctx)
|
|
{
|
|
(void)ctx;
|
|
return RRC_SPS * (TRANSMISSION_RAMP_DOWN_LEN + 2 * RRC_DELAY);
|
|
}
|
|
|
|
|
|
size_t transmission_calculate_packet_length(transmission_ctx_t *ctx, size_t symbol_count)
|
|
{
|
|
(void)ctx;
|
|
return RRC_SPS * symbol_count;
|
|
}
|