Пример #1
0
/**
 * @ingroup lte_cfi_coding
 * Main DSP function
 * Encodes the control format indicator (CFI)
 *
 * @return On success, returns a non-negative number indicating the output
 * samples that should be transmitted through all output interface. To specify a different length
 * for certain interface, use the function set_output_samples(int idx, int len)
 * On error returns -1.
 *
 */
int work(void **inp, void **out) {
	int i;
	int rcv_samples, snd_samples;
	input_t *input;
	output_t *output;

	input = inp[0];
	output = out[0];
	rcv_samples = get_input_samples(0);
	snd_samples = NOF_BITS;

	if ((input[0] > 0) && (input[0] < 5)) {
		memcpy(output, &table[input[0]-1], NOF_BITS);
	} else {
		moderror_msg("Wrong cfi %d. Specify 1, 2, 3, or 4 (4 reserved)."
		  "\n", input[0]);
		return -1;
	}

/*	printf("\n\n");
	for (i=0; i<snd_samples; i++) {
		printf("%d",output[i]);
	}
	printf("\n\n %d  %d  %d", table, &table[input[0]-1], &table[input[0]-1][0]);
*/
	return snd_samples;
}
Пример #2
0
/**
 * @ingroup lte_resource_mapper
 *
 *  Main DSP function
 *
 * This function allocates the data symbols of one slot (0.5 ms) in the corresponding place
 * of the LTE frame grid. During initialization phase CRS, PSS and SSS signals has been
 * incorporated and will no be modified during run phase.
 * PBCH (Physical Broadcast Channel), PCFICH (Physical Control Format Indicator Channel) &
 * PDCCH (Physical Downlink Control Channel) will be incorporated.
 *
 */
int work(void **inp, void **out) {

	if (subframe_idx_id) {
		param_get_int(subframe_idx_id, &subframe_idx);
	}
#ifdef CHECK_RCV_SAMPLES
	int n;
	n=check_received_samples_mapper();
	if (n < 1) {
		return n;
	}
#endif

#ifdef _COMPILE_ALOE
	moddebug("subframe_idx=%d tstamp=%d rcv=%d\n",subframe_idx,oesr_tstamp(ctx),get_input_samples(0));
#endif

	if (allocate_all_channels(inp,out[0])) {
		moderror("Error allocating channels\n");
		return 0;
	}

	subframe_idx++;
	if (subframe_idx==NOF_SUBFRAMES_X_FRAME) {
		subframe_idx=0;
	}

	return 0;
}
Пример #3
0
/**@ingroup gen_mux
 *
 */
int work(void **inp, void **out) {
	int i;
	int out_len;
	int nof_active_inputs;

	nof_active_inputs = 0;
	for (i=0;i<nof_inputs;i++) {
		input_lengths[i] = get_input_samples(i);
		nof_active_inputs++;
	}

	if (exclusive && nof_active_inputs>1) {
		moderror_msg("Exclusive mux but %d inputs have data\n",nof_active_inputs);
		return -1;
	}
	if(check_all && (nof_active_inputs<nof_inputs)) {
		moderror_msg("Only %d/%d inputs have data\n",nof_active_inputs,nof_inputs);
		return -1;
	}
	if (!out[0]) {
		moderror("Output not ready\n");
		return -1;
	}
	out_len = sum_i(input_lengths,nof_inputs);
	if (out_len) {
		mux(inp,out[0],input_lengths,input_padding_pre,nof_inputs,input_sample_sz);
	}
	return out_len;
}
Пример #4
0
/**@ingroup gen_demux
 *
 */
int work(void **inp, void **out) {
	int i;
	int rcv_len, out_len;

	rcv_len=get_input_samples(0);
	moddebug("%d samples recevied.\n",rcv_len);
	if (!rcv_len)
		return 0;

	modinfo_msg("received %d bytes\n",rcv_len);
	if ((rcv_len - sum_special_output_lengths) % (nof_outputs-nof_special_outputs)) {
/*		moderror_msg("Received length %d is not multiple of the number of output interfaces %d\n",
				rcv_len,nof_outputs);
*/		return 0;
	}

	out_len = (rcv_len - sum_special_output_lengths) / (nof_outputs-nof_special_outputs);
	for (i=0;i<nof_outputs;i++) {
		if (special_output_length[i]) {
			output_lengths[i] = special_output_length[i];
		} else {
			output_lengths[i] = out_len;
		}
		set_output_samples(i,output_lengths[i]);
		if (!out[i]) {
			moderror_msg("output itf %d not ready\n",out[i]);
			return -1;
		}
	}

	demux(inp[0],out,output_lengths,output_padding_pre,
			output_padding_post,nof_outputs,input_sample_sz);

	return 0;
}
Пример #5
0
/**
 * @ingroup file_sink
 *
 *  Writes the received samples to the dac output buffer
 *
 */
int work(void **inp, void **out) {
	int rcv_samples;
	input_t *buffer = inp[0];

	rcv_samples = get_input_samples(0);

#ifdef _COMPILE_ALOE
	if (rcv_samples != last_rcv_samples) {
		last_rcv_samples = rcv_samples;
		modinfo_msg("Receiving %d samples at tslot %d\n",
				rcv_samples,oesr_tstamp(ctx));
	}
#endif

	if (!rcv_samples) {
		return 0;
	}
	switch(data_type) {
	case 0:
		rtdal_datafile_write_real(fd,(float*) buffer,rcv_samples);
		break;
	case 1:
		rtdal_datafile_write_complex(fd,
				(_Complex float*) buffer,rcv_samples);
		break;
	case 2:
		rtdal_datafile_write_complex_short(fd,
				(_Complex short*) buffer,rcv_samples);
		break;
	case -1:
		rtdal_datafile_write_bin(fd,buffer,rcv_samples);
	}

	return 0;
}
Пример #6
0
/**
 * @ingroup udp_sink
 *
 *  Writes the received samples to the dac output buffer
 *
 */
int work(void **inp, void **out) {
	int rcv_samples;
	int n;
	char tmp[16];
	int nof_pkts,pkt_len,i;
	input_t *input = inp[0];

	rcv_samples = get_input_samples(0);
	if (!rcv_samples) {
		return 0;
	}

	nof_pkts=1;
	param_get_int(blen_id,&nof_pkts);

	if (rcv_samples % nof_pkts) {
		modinfo_msg("Warning received packet len %d not multiple of %d packets\n",
				rcv_samples,nof_pkts);
	}
	pkt_len = rcv_samples/nof_pkts;

	modinfo_msg("Sending %d packets of %d bytes\n",nof_pkts,pkt_len);

	for (i=0;i<nof_pkts;i++) {
		n = sendto(fd,&input[i*pkt_len],pkt_len,0,(struct sockaddr *) &servaddr, sizeof (servaddr));
		if (n == -1) {
			perror("sendto");
			return -1;
		}
	}

	return 0;
}
Пример #7
0
/**
 * @ingroup dac_sink
 *
 *  Writes the received samples to the dac output buffer
 *
 */
int work(void **inp, void **out) {
	int rcv_samples;
	int n;

	rcv_samples = get_input_samples(0);
	if (!rcv_samples) {
		return 0;
	}
	if (check_blen && check_blen != rcv_samples) {
		moderror_msg("Expected %d samples but got %d\n", check_blen, rcv_samples);
		return -1;
	}
	if (process_params()) {
		return -1;
	}
	vec_mult_c_r((complex_t*) inp[0],out_buffer,amplitude,rcv_samples);
	if (enable_dac) {
		n = rtdal_dac_send(dac,out_buffer,rcv_samples,blocking);
	} else {
		n = rcv_samples;
	}
	modinfo_msg("send %d samples amplitude %g\n",n,amplitude);
	if (n != rcv_samples) {
		moderror_msg("Sent %d/%d samples\n",n,rcv_samples);
		return -1;
	}

	return 0;
}
Пример #8
0
/**
 * @ingroup gen_hard_demod
 *
 * Main DSP function
 *
 * Calls the appropriate function for demodulating all recevied symbols.
 *
 * \param inp Input interface buffers. The value inp[i] points to the buffer received
 * from the i-th interface. The function get_input_samples(i) returns the number of received
 * samples (the sample size is by default sizeof(input_t))
 *
 * \param out Output interface buffers. The value out[i] points to the buffer where the samples
 * to be sent through the i-th interfaces must be stored.
 *
 * @return On success, returns a non-negative number indicating the output
 * samples that should be transmitted through all output interface. To specify a different length
 * for certain interface, use the function set_output_samples(int idx, int len)
 * On error returns -1.
 *
 *
 */
int work(void **inp, void **out) {

	int rcv_samples, snd_samples;
	int modulation;

	int bits_per_symbol;
	input_t *input;
	output_t *output;
	float *inreal;

	if (!get_input_samples(0)) {
		return 0;
	}

	/* Dynamically obtain modulation type */
	if (param_get_int(modulation_id, &modulation) != 1) {
		moderror("Error getting 'modulation' parameter. Assuming BPSK.\n");
		modulation = BPSK;
	}

	/* Verify parameters */
	if ((modulation != BPSK) && (modulation != QPSK) && (modulation != QAM16) && (modulation != QAM64)) {
		moderror_msg("Invalid modulation %d. Specify 1 for BPSK, 2 for QPSK,"
				"4 for 16QAM, or 6 for 64QAM\n", modulation);
		return -1;
	}

	input = inp[0];
	output = out[0];
	rcv_samples = get_input_samples(0); /* number of input samples */
	bits_per_symbol = get_bits_per_symbol(modulation);
	if (in_real) {
		inreal = inp[0];
		hard_demod_real(inreal, output, rcv_samples, modulation);
	} else {
		hard_demod(input, output, rcv_samples, modulation);
	}
	snd_samples = rcv_samples*bits_per_symbol;

	return snd_samples;
}
Пример #9
0
int work(void **inp, void **out) {
	int i, out_len;
	input_t *input;
	output_t *output;

	param_get_int(modulation_id,&modulation);

	for (i=0;i<NOF_INPUT_ITF;i++) {
		input = inp[i];
		output = out[i];

		if (get_input_samples(i)) {
			out_len = modulate(input,output,get_input_samples(i));
			if (out_len == -1) {
				return -1;
			}
			set_output_samples(i,out_len);
		}
	}
	return 0;
}
Пример #10
0
int work(void **inp, void **out) {
	int i, j, nof_fft;
	int dft_size;
	input_t *input;
	output_t *output;
	dft_plan_t *plan;

	if (param_get_int(dft_size_id,&dft_size) != 1) {
		moderror("Getting parameter dft_size\n");
		return -1;
	}

	plan = find_plan(dft_size);
	if (!plan) {
		if ((plan = generate_new_plan(dft_size)) == NULL) {
			moderror("Generating plan.\n");
			return -1;
		}
	}

	for (i=0;i<NOF_INPUT_ITF;i++) {
		input = inp[i];
		output = out[i];

		if (get_input_samples(i) % dft_size) {
			moderror_msg("Number of input samples (%d) must be multiple of dft_size (%d), in "
					"interface %d\n",get_input_samples(i),dft_size,i);
			return -1;
		}

		nof_fft = get_input_samples(i)/dft_size;

		for (j=0;j<nof_fft;j++) {
			dft_run_c2c(plan, &input[j*dft_size], &output[j*dft_size]);
		}

		set_output_samples(i,dft_size*nof_fft);
	}
	return 0;
}
Пример #11
0
/**
 * @ingroup lte_ratematching
 *
 * Main DSP function
 *
 */
int work(void **inp, void **out) {
	int i, in_pkt_len, out_pkt_len, j;
	int rcv_samples;

	char *input, *output;

	param_get_int(pre_padding_id, &pre_padding);
	param_get_int(post_padding_id, &post_padding);
	param_get_int(nof_packets_id, &nof_packets);

	for (i=0;i<NOF_INPUT_ITF;i++) {
		input = inp[i];
		output = out[i];
		rcv_samples = get_input_samples(i);
		moddebug("%d samples received on input interface %d.\n",rcv_samples,i);
		if (rcv_samples == 0) {
			moddebug("%d samples to process. Returning.\n", rcv_samples);
			continue;
		}

		if ((rcv_samples) % nof_packets) {
			moderror_msg("Received samples (%d) should multiple of "
			"nof_packets (%d)\n", rcv_samples, nof_packets);
			return -1;
		}

		in_pkt_len = rcv_samples / nof_packets;
		if (direction) {
			out_pkt_len = in_pkt_len - pre_padding - post_padding;
		} else {
			out_pkt_len = in_pkt_len + pre_padding + post_padding;
		}

		if (in_pkt_len) {
			if (direction) {
				for (j=0;j<nof_packets;j++) {
					memcpy(outaddr(0),inaddr(pre_padding),input_sample_sz*out_pkt_len);
				}
			} else {
				for (j=0;j<nof_packets;j++) {
					memset(outaddr(0),0,input_sample_sz*pre_padding);
					memcpy(outaddr(pre_padding),inaddr(0),input_sample_sz*in_pkt_len);
					memset(outaddr(pre_padding+in_pkt_len),0,input_sample_sz*post_padding);
				}
			}
			moddebug("%d samples sent to output interface %d.\n",out_pkt_len*nof_packets, i);
			set_output_samples(i,out_pkt_len*nof_packets);
		}

	}
	return 0;
}
Пример #12
0
/**
 * @ingroup Lte Rate Matching of convolutionally encoded information
 * Applied for PDCCH
 *
 * Main DSP function
 *
 *
 * \param inp Input interface buffers. The value inp[i] points to the buffer received
 * from the i-th interface. The function get_input_samples(i) returns the number of received
 * samples (the sample size is by default sizeof(input_t))
 *
 * \param out Output interface buffers. The value out[i] points to the buffer where the samples
 * to be sent through the i-th interfaces must be stored.
 *
 * \param E Number of output bits of rate matching in transmitter mode
 * \param S Number of output bits of rate matching in receiver mode
 *
 * @return On success, returns a non-negative number indicating the output
 * samples that should be transmitted through all output interface. To specify a different length
 * for certain interface, use the function set_output_samples(int idx, int len)
 * On error returns -1.
 */
int work(void **inp, void **out) {
	int S, E;
	int rcv_samples, snd_samples;
	char *input_b;
	char *output_b;
	float *input_f;
	float *output_f;

	rcv_samples = get_input_samples(0);
	if (!rcv_samples || !out[0] || rcv_samples > 3*6114) {
		return 0;
	}

	input_f = inp[0];
	input_b = inp[0];
	output_f = out[0];
	output_b = out[0];

	if (!direction) {
		/* @Transmitter */
		if (param_get_int(E_id, &E) != 1) {
			moderror("Error getting parameter 'E', indiciating the "
			  "number of rate matching output samples in Tx mode.\n");
			return -1;
		}
		if (E > OUTPUT_MAX_SAMPLES) {
			moderror("Too may output samples (E).\n");
			return -1;
		}
		rate_matching(input_b, output_b, rcv_samples, E);
		snd_samples = E;

	} else {
		/* @Receiver */
		if (param_get_int(S_id, &S) != 1) {
			moderror("Error getting parameter 'S', indiciating the "
			  "number of rate matching output samples in Rx mode\n");
			return -1;
		}
		if (S > OUTPUT_MAX_SAMPLES) {
			moderror("Too may output samples (S).\n");
			return -1;
		}
		if (S%3 > 0) {
			moderror("Number of output samples S not integer divisible by 3.\n");
			return -1;
		}
		snd_samples = rate_unmatching(input_f, output_f, rcv_samples, S);
	}

	return snd_samples;
}
Пример #13
0
/**@ingroup gen_mux
 *
 */
int work(void **inp, void **out) {
	int i;
	int out_len;

	for (i=0;i<nof_inputs;i++) {
		input_lengths[i] = get_input_samples(i);
	}
	out_len = sum_i(input_lengths,nof_inputs);
	if (out_len) {
		mux(inp,out[0],input_lengths,input_padding_pre,nof_inputs,input_sample_sz);
	}
	return out_len;
}
Пример #14
0
int work(void **inp, void **out) {
	int i, out_len, j;
	input_t *input;
	output_t *output;
	int rcv_samples;

	for (i=0;i<NOF_INPUT_ITF;i++) {
		input = inp[i];
		output = out[i];
		moddebug("rcv_len=%d\n",get_input_samples(i));
		rcv_samples = get_input_samples(i);
		if (rcv_samples) {
			conv_encode(input,rcv_samples,constraint_length,rate,g,tail_bit,
								output,&out_len);

			for (j=0;j<padding;j++) {
				output[out_len+j] = 0;
			}

			set_output_samples(i,out_len+padding);
		}
	}
	return 0;
}
Пример #15
0
int work(void **inp, void **out) {
	int len;

	if (!direction) {
		if (!out[0]) {
			return 0;
		}
		len = send_dci(out[0]);
		if (len == -1) {
			return -1;
		}
		return len;
	} else {
		len = get_input_samples(0);
		recv_dci(inp[0],out[0],len);
	}

	return 0;
}
Пример #16
0
/**@ingroup gen_crc
 * Adds a CRC to every received packet from each interface
 */
int work(void **inp, void **out) {
	int i;
	unsigned int n;
	input_t *input;

	if (poly_id) param_get_int(poly_id,&poly);
	if (long_crc_id) param_get_int(long_crc_id, &long_crc);

	for (i=0;i<NOF_INPUT_ITF;i++) {
		if (get_input_samples(i)) {
			moddebug("rcv_len=%d\n",get_input_samples(i));
			memcpy(out[i],inp[i],sizeof(input_t)*get_input_samples(i));
			input = out[i];
			n = icrc(0, input, get_input_samples(i), long_crc, poly, mode == MODE_ADD);

			if (mode==MODE_CHECK) {
				if (n) {
					total_errors++;
				}
				total_pkts++;
				set_output_samples(i,get_input_samples(i)-long_crc);

				if (!print_nof_pkts) {
					tscnt++;
					if (tscnt==interval_ts) {
						tscnt=0;
						#ifdef PRINT_BLER
						printf("Total blocks: %d\tTotal errors: %d\tBLER=%g\n",
								total_pkts,total_errors,(float)total_errors/total_pkts);
						#endif
					}
				} else {
					print_nof_pkts_cnt++;
					if (print_nof_pkts_cnt == print_nof_pkts) {
						print_nof_pkts_cnt=0;
						printf("Total blocks: %d\tTotal errors: %d\tBLER=%g\n",
								total_pkts,total_errors,(float)total_errors/total_pkts);
						total_pkts=0;
						total_errors=0;
					}
				}

			} else {
				set_output_samples(i,get_input_samples(i)+long_crc);
			}
		}
	}
	return 0;
}
Пример #17
0
int work(void **inp, void **out) {
	int i,n;
#if NOF_INPUTS>1
	for (i=0;i<NOF_INPUT_ITF;i++) {
		binsource.input[i] = inp[i];
		binsource.in_len[i] = get_input_samples(i)
	}
#elif NOF_INPUTS == 1
	binsource.input = inp[0];
	binsource.in_len = get_input_samples(0);
#endif

#if NOF_OUTPUTS>1
	for (i=0;i<NOF_OUTPUT_ITF;i++) {
		binsource.output[i] = out[i];
		binsource.out_len = &out_len[i];
	}
#elif NOF_OUTPUTS == 1
	binsourceoutput = out[0];
	binsource.out_len = &out_len[0];
#endif

	/* Get input parameters */
	if (param_get_int(nbits_id, &binsource.ctrl_in.nbits) != 1) {
		moderror("Error getting parameter nbits\n");
		return -1;
	}

	/* call work */
	n = binsource_work(&binsource);

	/* Set output nof_samples */
	for (i=0;i<NOF_OUTPUT_ITF;i++) {
		set_output_samples(i,out_len[i]);
		binsource.out_len = &out_len[i];
	}

	/* Set output parameters */

	return n;
}
Пример #18
0
/**
 * @ingroup lte_resource_mapper
 *
 *  Main DSP function
 *
 * This function allocates the data symbols of one slot (0.5 ms) in the corresponding place
 * of the LTE frame grid. During initialization phase CRS, PSS and SSS signals has been
 * incorporated and will no be modified during run phase.
 * PBCH (Physical Broadcast Channel), PCFICH (Physical Control Format Indicator Channel) &
 * PDCCH (Physical Downlink Control Channel) will be incorporated.
 *
 */
int work(void **inp, void **out) {
	int n;

	subframe_idx=-1;
	if (subframe_idx_id) {
		param_get_int(subframe_idx_id, &subframe_idx);
	}

#ifdef _COMPILE_ALOE
	moddebug("subframe_idx=%d tstamp=%d rcv_len=%d cfi=%d\n",subframe_idx,oesr_tstamp(ctx),
		get_input_samples(0),grid.cfi);
#endif

	if (subframe_idx==-1) {
		return 0;
	}

	n=check_received_samples_demapper();
	if (n < 1) {
		return n;
	}

	if (channels_init_grid(channel_ids, nof_channels)) {
		moderror("Initiating resource grid\n");
		return 0;
	}

	if (deallocate_all_channels(channel_ids, nof_channels, inp[0],out)) {
		return -1;
	}
	if (extract_refsig(inp[0],out)) {
		return -1;
	}

	if (copy_signal(inp[0],out)) {
		return -1;
	}

	return 0;
}
Пример #19
0
/**
 * @ingroup gen_hard_demod
 *
 * Main DSP function
 *
 * Calls the appropriate function for demodulating all recevied symbols.
 *
 * \param inp Input interface buffers. The value inp[i] points to the buffer received
 * from the i-th interface. The function get_input_samples(i) returns the number of received
 * samples (the sample size is by default sizeof(input_t))
 *
 * \param out Output interface buffers. The value out[i] points to the buffer where the samples
 * to be sent through the i-th interfaces must be stored.
 *
 * @return On success, returns a non-negative number indicating the output
 * samples that should be transmitted through all output interface. To specify a different length
 * for certain interface, use the function set_output_samples(int idx, int len)
 * On error returns -1.
 *
 *
 */
int work(void **inp, void **out) {
	int i;
	int rcv_samples, snd_samples;
	int modulation;
	float sigma2;
	int bits_per_symbol;
	input_t *input;
	output_t *output;

	/* Dynamically obtain modulation type */
	if (param_get_int(modulation_id, &modulation) != 1) {
		moderror("Error getting 'modulation' parameter. Assuming QPSK.\n");
		modulation = QPSK;
	}

	/* Verify parameters */
	if (modulation > 3 || modulation < 0) {
		moderror_msg("Invalid modulation %d. Specify 0 for BPSK, 1 for QPSK,"
				"2 for 16QAM, or 3 for 64QAM\n", modulation);
		return -1;
	} else {
		modinfo_msg("Modulation type is %d (0:BPSK; 1:QPSK; 2:16QAM;"
				"3:64QAM)\n",modulation);
	}

	input = inp[0];
	output = out[0];
	rcv_samples = get_input_samples(0); /* number of input samples */
	bits_per_symbol = get_bits_per_symbol(modulation);
	hard_demod(input, output, rcv_samples, modulation);
	snd_samples = rcv_samples*bits_per_symbol;

/*	printf("\n\n");
	for (i=0; i<snd_samples; i++) {
		printf("%d",output[i]);
	}
*/
	return snd_samples;
}
Пример #20
0
/**
 * @TODO:
 * - re-compute c from N_id_2
 */
int work(void **inp, void **out) {
	int rcv_samples=get_input_samples(0);
	int m0,m1;
	int subframe_idx,N_id_1;
	input_t *input=inp[0];

	if (!rcv_samples) {
		return 0;
	}

	dft_run_c2c(&plan, &input[sss_pos_in_frame], input_fft);

	if (!get_m0m1(&input_fft[sss_pos_in_symbol],&m0,&m1,correlation_threshold)) {
		return 0;
	}

	subframe_idx=decide_subframe(m0,m1);

	N_id_1=decide_N_id_1(m0,m1);

	modinfo_msg("m0=%d, m1=%d subframe=%d\n", m0,m1,subframe_idx,N_id_1);

#ifdef _COMPILE_ALOE

	if (sf_pm_idx >= 0 && !(subframe_idx && first)) {
		first=0;
		if (param_remote_set(out, 0, sf_pm_idx, &subframe_idx,
				sizeof(int))) {
			moderror("Setting parameter\n");
			return -1;
		}
	}
#endif

	return 0;
}
Пример #21
0
/**
 * @ingroup template
 *
 *  Main DSP function
 *
 * Document here your module, which parameters it requires and how it behaves as a function of them.
 *
 * \param inp Input interface buffers. The value inp[i] points to the buffer received
 * from the i-th interface. The function get_input_samples(i) returns the number of received
 * samples (the sample size is by default sizeof(input_t))
 *
 * \param out Output interface buffers. The value out[i] points to the buffer where the samples
 * to be sent through the i-th interfaces must be stored.
 *
 * @return On success, returns a non-negative number indicating the output
 * samples that should be transmitted through all output interface. To specify a different length
 * for certain interface, use the function set_output_samples(int idx, int len)
 * On error returns -1.
 *
 *
 */
int work(void **inp, void **out) {
	int rcv_samples, snd_samples;
	int j;
	input_t *input;
	output_t *output;
	float gain;

	if (param_get_float(gain_id, &gain) != 1) {
		moderror("Error getting parameter gain\n");
		return -1;
	}

	/* inp[n] and out[m] are pointer to the n-th and m-th input and output interfaces */
	/* let us assume we only have one input and output interface */
	input = inp[0];
	output = out[0];
	rcv_samples = get_input_samples(0); /* this function returns the samples received from an input */
	for (j = 0; j < rcv_samples; j++) {
		/* do here your DSP work */
		output[j] = gain*input[j];
	}
	snd_samples = rcv_samples;
	return snd_samples;
}
Пример #22
0
int work(void **inp, void **out) {
	int rcv_samples;
	int n;
	input_t *input;
	output_t *output;
	float gain_re,gain_im,variance,scale;
	_Complex float gain_c;

	if (!get_input_samples(0)) {
		return 0;
	}

	if (param_get_float(gain_re_id, &gain_re) != 1) {
		moderror("Error getting parameter gain_re\n");
		return -1;
	}
	if (param_get_float(gain_im_id, &gain_im) != 1) {
		moderror("Error getting parameter gain_im\n");
		return -1;
	}
	if (param_get_float(scale_id, &scale) != 1) {
		moderror("Error getting parameter scale\n");
		return -1;
	}
	if (!auto_mode) {
		if (param_get_float(variance_id, &variance) != 1) {
			moderror("Error getting parameter variance\n");
			return -1;
		}
	} else if (auto_mode == 1) {
		variance = get_variance(snr_current,scale);
		cnt_realizations++;
		if (cnt_realizations >= num_realizations) {
			snr_current += snr_step;
			cnt_realizations=0;
		}
		if (snr_current >= snr_max) {
			auto_mode=2;
			variance=0;
		}
	}

	__real__ gain_c = gain_re;
	__imag__ gain_c = gain_im;

	for (n=0;n<NOF_INPUT_ITF;n++) {
		input = inp[n];
		output = out[n];
		rcv_samples = get_input_samples(0);
		if (variance != 0) {
			gen_noise_c(noise_vec,variance,rcv_samples);
			vec_sum_c(output,input,noise_vec,rcv_samples);
		} else {
			memcpy(output,input,rcv_samples*sizeof(input_t));
		}
		if (gain_re != 1.0 && gain_im != 0.0) {
			vec_mult_c(output,output,gain_c,rcv_samples);
		}

	}
	return rcv_samples;
}
Пример #23
0
/**
 * Testsuite:
 * Generates random symbols and calls the module ....
 * @param ...
 * @param ...
 * @param ... */
int main(int argc, char **argv)
{
	struct timespec tdata[3];
	gnuplot_ctrl *plot;
	char tmp[64];
	int ret, i, j;
	float *tmp_f;
	_Complex float *tmp_c;
	double *plot_buff_r;
	double *plot_buff_c;

	allocate_memory();

	parameters = NULL;

	parse_paramters(argc, argv);

	if (generate_input_signal(input_data, input_lengths)) {
		printf("Error generating input signal\n");
		exit(1);
	}

	for (i=0;i<nof_input_itf;i++) {
		if (!input_lengths[i]) {
			printf("Warning, input interface %d has zero length\n",i);
		}
	}

	if (initialize()) {
		printf("Error initializing\n");
		exit(1); /* the reason for exiting should be printed out beforehand */
	}

#ifndef _ALOE_OLD_SKELETON
	for (i=0;i<nof_input_itf;i++) {
		input_ptr[i] = &input_data[i*input_max_samples*input_sample_sz];
	}
	for (i=0;i<nof_output_itf;i++) {
		output_ptr[i] = &output_data[i*output_max_samples*output_sample_sz];
	}
	clock_gettime(CLOCK_MONOTONIC,&tdata[1]);
	ret = work(input_ptr, output_ptr);
	clock_gettime(CLOCK_MONOTONIC,&tdata[2]);

#else

	clock_gettime(CLOCK_MONOTONIC,&tdata[1]);
	ret = work(input_data, output_data);
	clock_gettime(CLOCK_MONOTONIC,&tdata[2]);
#endif

	stop();
	if (ret == -1) {
		printf("Error running\n");
		exit(-1);
	}
	get_time_interval(tdata);

	for (i=0;i<nof_output_itf;i++) {
		if (!output_lengths[i]) {
			output_lengths[i] = ret;
		}
		if (!output_lengths[i]) {
			printf("Warning output interface %d has zero length\n",i);
		}
	}


	printf("\nExecution time: %d ns.\n", (int) tdata[0].tv_nsec);
	printf("FINISHED\n");

	if (use_gnuplot) {
		for (i=0;i<nof_input_itf;i++) {
			plot_buff_r = malloc(sizeof(double)*input_lengths[i]);
			plot_buff_c = malloc(sizeof(double)*input_lengths[i]);
			if (input_sample_sz == sizeof(float)) {
				tmp_f = (float*) &input_data[i*input_max_samples];
				for (j=0;j<input_lengths[i];j++) {
					plot_buff_r[j] = (double) tmp_f[j];
				}
				plot = gnuplot_init() ;
			    gnuplot_setstyle(plot,"lines");
			    snprintf(tmp,64,"input_%d",i);
		        gnuplot_plot_x(plot, plot_buff_r,
		        		get_input_samples(i), tmp);
		        free(plot_buff_r);
			} else if (input_sample_sz == sizeof(_Complex float)) {
				tmp_c = (_Complex float*) &input_data[i*input_max_samples];
				for (j=0;j<input_lengths[i];j++) {
					plot_buff_r[j] = (double) __real__ tmp_c[j];
					plot_buff_c[j] = (double) __imag__ tmp_c[j];
				}
				plot = gnuplot_init() ;
			    gnuplot_setstyle(plot,"lines");
			    snprintf(tmp,64,"input_real_%d",i);
		        gnuplot_plot_x(plot, plot_buff_r,
		        		get_input_samples(i), tmp);
		        plot = gnuplot_init() ;
			    gnuplot_setstyle(plot,"lines");
			    snprintf(tmp,64,"input_imag_%d",i);
		        gnuplot_plot_x(plot, plot_buff_c,
		        		get_input_samples(i), tmp);
		        free(plot_buff_r);
		        free(plot_buff_c);
			}
		}
		for (i=0;i<nof_output_itf;i++) {
			plot_buff_r = malloc(sizeof(double)*output_lengths[i]);
			plot_buff_c = malloc(sizeof(double)*output_lengths[i]);
			if (output_sample_sz == sizeof(float)) {
				tmp_f = (float*) &output_data[i*output_max_samples];
				for (j=0;j<output_lengths[i];j++) {
					plot_buff_r[j] = (double) __real__ tmp_f[j];
				}
				plot = gnuplot_init() ;
				gnuplot_setstyle(plot,"lines");
				snprintf(tmp,64,"output_%d",i);
				gnuplot_plot_x(plot, plot_buff_r,
						output_lengths[i], tmp);
				free(plot_buff_r);
			} else if (output_sample_sz == sizeof(_Complex float)) {
				tmp_c = (_Complex float*) &output_data[i*output_max_samples];
				for (j=0;j<output_lengths[i];j++) {
					plot_buff_r[j] = (double) __real__ tmp_c[j];
					plot_buff_c[j] = (double) __imag__ tmp_c[j];
				}
				plot = gnuplot_init() ;
				gnuplot_setstyle(plot,"lines");
				snprintf(tmp,64,"output_real_%d",i);
				gnuplot_plot_x(plot, plot_buff_r,
						output_lengths[i], tmp);
				plot = gnuplot_init() ;
				gnuplot_setstyle(plot,"lines");
				snprintf(tmp,64,"output_imag_%d",i);
				gnuplot_plot_x(plot, plot_buff_c,
						output_lengths[i], tmp);
				free(plot_buff_r);
				free(plot_buff_c);
	        }
		}

		printf("Type ctrl+c to exit\n");fflush(stdout);
		free_memory();
		pause();
		/* make sure we exit here */
		exit(1);
	}

	free_memory();

	return 0;
}
Пример #24
0
int work(void **inp, void **out) {
	int i, j, k;
	int rcv_samples, nof_ffts;
	int df, fs;
	int e;
	int dft_size;
	input_t *input;
	output_t *output;
	dft_plan_t *plan;
	
 
	if (param_get_int(dft_size_id,&dft_size) != 1) {
		dft_size = get_input_samples(0);
		moddebug("Parameter dft_size not defined. Assuming %d"
		" (number of input samples on interface 0).\n", dft_size);
		/*moderror("Getting parameter dft_size\n");
		return -1;*/
	}

	if (dft_size == 0) {
		modinfo("dft_size = 0. Returning.\n");
		return 0;
	} else {
		moddebug("dft_size = %d.\n", dft_size);
	}
	
/*	if (param_get_int(param_id("dft_size"),&dft_size) != 1) {
		
		moddebug("Parameter dft_size not defined. Assuming %d"
			" (number of input samples on interface 0).\n", dft_size);
	}
*/
	plan = find_plan(dft_size);
	if (!plan) {
		if ((plan = generate_new_plan(dft_size)) == NULL) {
			moderror("Generating plan.\n");
			return -1;
		}
	}
	
	if (param_get_int(df_id, &df) != 1) {
		df = 0;
	}
	if (df != 0) {
		if (param_get_int(fs_id, &fs) != 1) {
			moderror("Parameter fs not defined.\n");
			return -1;
		}
		if (fs <= 0) {
			moderror("Sampling rate fs must be larger than 0.\n");
			return -1;
		}
		if ((df != previous_df) || (fs != previous_fs) || (dft_size != previous_dft_size)) {
			e = process_shift_params(df, fs, dft_size);
			if (e < 0) {
				return -1;
			}
			previous_df = df;
			previous_fs = fs;
			previous_dft_size = dft_size;
		}
	}

	for (i=0;i<NOF_INPUT_ITF;i++) {
		input = inp[i];
		output = out[i];
		rcv_samples = get_input_samples(i);
		moddebug("%d samples received on interface %d.\n",rcv_samples, i);
		if (rcv_samples == 0) {
			moddebug("%d samples to process. Returning.\n", rcv_samples);
			continue;
		}
		moddebug("Processing %d samples...\n",rcv_samples);

		if (rcv_samples % dft_size) {
			moderror_msg("Number of input samples (%d) not integer multiple"
			" of dft_size (%d) on interface %d\n",rcv_samples,dft_size,i);
			return -1;
		}
		if (get_input_samples(0)>0) {
			modinfo_msg("received %d samples\n",get_input_samples(0));
		}

		nof_ffts = rcv_samples/dft_size;

		for (j=0;j<nof_ffts;j++) {
			if ((df != 0) && (direction == FORWARD)) { /* Rx: shift before FFT */
				for (k=0;k<dft_size;k++) {
					input[j*dft_size+k] *= shift[k*shift_increment];
				}
			}

			dft_run_c2c(plan, &input[j*dft_size], &output[j*dft_size]);

			if ((df !=0) && (direction == BACKWARD)) { /* Tx: shift after IFFT */
				for (k=0;k<dft_size;k++) {
					output[j*dft_size+k] *= shift[k*shift_increment];
				}
			}
		}

		set_output_samples(i,dft_size*nof_ffts);
		moddebug("%d samples sent to output interface %d.\n",dft_size*nof_ffts,i);
	}

	return 0;
}
Пример #25
0
/**@ingroup gen_remcyclic
 *
 * For each interface, the number of received samples must be multiple of the OFDM symbol size,
 * otherwise the module produces and error and stops the waveform.
 *
 * It removes a cyclic prefix to each OFDM symbol received from each interface.
 */
int work(void **inp, void **out) {
	int i, j;
	int dft_size, cyclic_prefix_sz, first_cyclic_prefix_sz;
	int k, nof_ofdm_symbols_per_slot, rcv_samples;
	int cpy;
	int cnt;
	input_t *input;
	output_t *output;

	if (param_get_int(cyclic_prefix_sz_id, &cyclic_prefix_sz) != 1) {
		moderror("getting parameter cyclic_prefix_sz\n");
		return -1;
	}
	if (first_cyclic_prefix_sz_id) {
		if (param_get_int(first_cyclic_prefix_sz_id, &first_cyclic_prefix_sz) != 1) {
			moderror("getting parameter first_cyclic_prefix_sz\n");
			return -1;
		}
	} else {
		first_cyclic_prefix_sz = cyclic_prefix_sz;
	}

	if (param_get_int(dft_size_id, &dft_size) != 1) {
		/*moderror("getting parameter dft_size\n");
		return -1;*/
		dft_size = get_input_samples(0)-cyclic_prefix_sz;
		moddebug("Parameter dft_size not defined. Assuming %d"
		" (number of input samples on interface 0 - cyclic_prefix_sz)."
		"\n", dft_size);
	}

	if (dft_size <= 0) {
		modinfo("dft_size <= 0. Returning.\n");
		return 0;
	} else {
		moddebug("dft_size = %d.\n", dft_size);
	}

	if (first_cyclic_prefix_sz > dft_size || cyclic_prefix_sz > dft_size) {
		moderror_msg("Error with parameters dft_size=%d, cyclic_prefix_sz=%d, "
				"first_cyclic_prefix_sz=%d\n",dft_size,cyclic_prefix_sz,first_cyclic_prefix_sz);
		return -1;
	}

	if (first_cyclic_prefix_sz == cyclic_prefix_sz) {
		nof_ofdm_symbols_per_slot = 6;
	} else {
		nof_ofdm_symbols_per_slot = 7;
	}

	for (i=0;i<NOF_INPUT_ITF;i++) {
		cnt=0;
		input = inp[i];
		output = out[i];
		rcv_samples = get_input_samples(i);
		moddebug("rcv_len=%d samples \n",rcv_samples);

		if (rcv_samples > 0) {
			j = 0;
			k = 0;
			while (cnt < rcv_samples) {
				if (j == k*nof_ofdm_symbols_per_slot) {
					cpy = first_cyclic_prefix_sz;
					k++;
				} else {
					cpy = cyclic_prefix_sz;
				}
				memcpy(output,&input[cpy],sizeof(input_t)*dft_size);
				input += dft_size+cpy;
				output += dft_size;
				cnt += dft_size+cpy;
				j++;
			}
			if (rcv_samples != cnt) {
				moderror_msg("Number of input samples (%d) should be "
				"equal to %d on interface %d\n",rcv_samples,cnt,i);
				return -1;
			}
			set_output_samples(i, j*dft_size);
		}
	}
	return 0;
}
Пример #26
0
/**@ingroup plp_sink
 * Prints or displays the signal according to the selected mode.
 */
int work(void **inp, void **out) {
	int n,i,j;
	int mode;
	float *r_input;
	_Complex float *c_input;
	dft_plan_t *plan;

	strdef(xlabel);

	if (mode_id != NULL) {
		if (param_get_int(mode_id,&mode) != 1) {
			mode = 0;
		}
	} else {
		mode = 0;
	}
	memset(signal_lengths,0,sizeof(int)*2*NOF_INPUT_ITF);
	for (n=0;n<NOF_INPUT_ITF;n++) {
		if (is_complex && mode != MODE_PSD) {
			signal_lengths[2*n] = get_input_samples(n)/2;
			signal_lengths[2*n+1] = signal_lengths[2*n];
		} else {
			signal_lengths[n] = get_input_samples(n);
		}
		if (get_input_samples(n) != last_rcv_samples) {
			last_rcv_samples = get_input_samples(n);
#ifdef _COMPILE_ALOE
			modinfo_msg("Receiving %d samples at tslot %d\n",last_rcv_samples,
					oesr_tstamp(ctx));
#endif
		}
	}

#ifdef _COMPILE_ALOE
	if (print_not_received) {
		for (n=0;n<NOF_INPUT_ITF;n++) {
			if (MOD_DEBUG) {
				ainfo_msg("ts=%d, rcv_len=%d\n",oesr_tstamp(ctx),get_input_samples(n));
			}
			if (!get_input_samples(n)) {
				printf("ts=%d. Data not received from interface %d\n",oesr_tstamp(ctx),n);
			}

		}
	}
#endif


#ifdef _COMPILE_ALOE
	if (oesr_tstamp(ctx)-last_tstamp < interval_ts) {
		return 0;
	}
	last_tstamp = interval_ts;
#endif


	switch(mode) {
	case MODE_SILENT:
		break;
	case MODE_PRINT:
		for (n=0;n<NOF_INPUT_ITF;n++) {
			if (inp[n]) {
				print_signal(inp[n],get_input_samples(n));
			}
		}
	break;
	case MODE_SCOPE:
#ifdef _COMPILE_ALOE
		snprintf(xlabel,STR_LEN,"# sample (ts=%d)",oesr_tstamp(ctx));
#else
		snprintf(xlabel,STR_LEN,"# sample");
#endif
		if (is_complex) {
			set_legend(c_legends,2*NOF_INPUT_ITF);
		} else {
			set_legend(r_legends,NOF_INPUT_ITF);
		}
		set_labels(xlabel,"amp");

		for (n=0;n<NOF_INPUT_ITF;n++) {
			if (inp[n]) {
				if (is_complex) {
					c_input = inp[n];
					for (i=0;i<signal_lengths[2*n];i++) {
						pl_signals[2*n*INPUT_MAX_SAMPLES+i] = (double) __real__ c_input[i];
						pl_signals[(2*n+1)*INPUT_MAX_SAMPLES+i] = (double) __imag__ c_input[i];
					}
				} else {
					r_input = inp[n];
					for (i=0;i<signal_lengths[n];i++) {
						pl_signals[n*INPUT_MAX_SAMPLES+i] = (double) r_input[i];
					}
				}
			}

		}

		plp_draw(pl_signals,signal_lengths,0);
	break;
	case MODE_PSD:
#ifdef _COMPILE_ALOE
		snprintf(xlabel,STR_LEN,"freq. idx (ts=%d)",oesr_tstamp(ctx));
#else
		snprintf(xlabel,STR_LEN,"freq. idx");
#endif

		set_labels(xlabel,"PSD (dB/Hz)");

		set_legend(fft_legends,NOF_INPUT_ITF);

		for (i=0;i<NOF_INPUT_ITF;i++) {
			if (signal_lengths[i]) {
				if (fft_size) {
					signal_lengths[i] = signal_lengths[i]>fft_size?fft_size:signal_lengths[i];
				}
				plan = find_plan(signal_lengths[i]);
				c_input = inp[i];
				r_input = inp[i];
				if (!plan) {
					if ((plan = generate_new_plan(signal_lengths[i])) == NULL) {
						moderror("Generating plan.\n");
						return -1;
					}
				}
				if (is_complex) {
					dft_run_c2r(plan, c_input, &f_pl_signals[i*INPUT_MAX_SAMPLES]);
				} else {
					dft_run_r2r(plan, r_input, &f_pl_signals[i*INPUT_MAX_SAMPLES]);
				}
				/*if (!is_complex) {
					signal_lengths[i] = signal_lengths[i]/2;
				}*/
				for (j=0;j<signal_lengths[i];j++) {
					pl_signals[i*INPUT_MAX_SAMPLES+j] = (double) f_pl_signals[i*INPUT_MAX_SAMPLES+j];
				}
			}
		}
		for (i=NOF_INPUT_ITF;i<2*NOF_INPUT_ITF;i++) {
			signal_lengths[i] = 0;
		}
		plp_draw(pl_signals,signal_lengths,0);

	break;
	default:
		moderror_msg("Unknown mode %d\n",mode);
		return -1;

	}
	return 0;
}
Пример #27
0
/**
 * @ingroup dac_sink
 *
 *  Writes the received samples to the dac output buffer
 *
 */
int work(void **inp, void **out) {
	int rcv_samples;
	float *input_rf;
	_Complex float *input_f;
	_Complex short *input_s;
	int i,j;
	float freq;
	float gain;
	float x=0;
	float *buffer_rf = buffer;
	_Complex float *buffer_f = buffer;
	_Complex short *buffer_s = buffer;

	if (param_get_float(freq_id,&freq) != 1) {
		moderror("Getting parameter freq_samp\n");
		return -1;
	}

	if (gain_id) {
		if (param_get_float(gain_id,&gain) != 1) {
			moderror("Getting parameter gain\n");
			return -1;
		}
	} else {
		gain = 1.0;
	}

#ifdef _COMPILE_ALOE
	if (freq != last_freq) {
		modinfo_msg("Set sampling frequency to %.2f MHz at tslot %d\n", freq/1000000,oesr_tstamp(ctx));
		last_freq = freq;
	}
#endif

	rtdal_uhd_set_freq(freq);

	for (i=0;i<NOF_INPUT_ITF;i++) {
		input_s = inp[i];
		input_f = inp[i];
		input_rf = inp[i];

		rcv_samples = get_input_samples(i);

#ifdef _COMPILE_ALOE
		if (rcv_samples != last_rcv_samples) {
			last_rcv_samples = rcv_samples;
			modinfo_msg("Receiving %d samples at tslot %d\n",rcv_samples,oesr_tstamp(ctx));
		}
#endif

		rtdal_uhd_set_block_len(rcv_samples);
		x=0;
		for (j=0;j<rcv_samples;j++) {
			switch(data_type) {
			case 0:
				buffer_rf[j] = gain*input_rf[j];
				break;
			case 1:
				buffer_f[j] = gain*input_f[j];
				break;
			case 2:
				buffer_s[j] = gain*input_s[j];
				break;
			}
		}
	}

	return 0;
}
Пример #28
0
/**@ingroup gen_cyclic
 *
 * For each interface, the number of received samples must be multiple of the OFDM symbol size,
 * otherwise the module produces and error and stops the waveform.
 *
 * It adds a cyclic prefix to each OFDM symbol received from each interface.
 */
int work(void **inp, void **out) {
	int i, j;
	int nof_ofdm_symb;
	int dft_size, cyclic_prefix_sz, first_cyclic_prefix_sz;
	int k, nof_ofdm_symbols_per_slot,rcv_samples;
	int cnt;
	int cpy;
	div_t symbols;
	input_t *input;
	output_t *output;

	if (param_get_int(dft_size_id, &dft_size) != 1) {
		/*moderror("getting parameter dft_size\n");
		return -1;*/
		dft_size = get_input_samples(0);
		moddebug("Parameter dft_size not defined. Assuming %d"
		" (number of input samples on interface 0).\n", dft_size);
	}

	if (dft_size == 0) {
		modinfo("dft_size = 0. Returning.\n");
		return 0;
	} else {
		moddebug("dft_size = %d.\n", dft_size);
	}

	if (param_get_int(cyclic_prefix_sz_id, &cyclic_prefix_sz) != 1) {
		moderror("getting parameter cyclic_prefix_sz\n");
		return -1;
	}
	if (first_cyclic_prefix_sz_id) {
		if (param_get_int(first_cyclic_prefix_sz_id, &first_cyclic_prefix_sz) != 1) {
			moderror("getting parameter first_cyclic_prefix_sz\n");
			return -1;
		}
	} else {
		first_cyclic_prefix_sz = cyclic_prefix_sz;
	}
	if (first_cyclic_prefix_sz > dft_size || cyclic_prefix_sz > dft_size) {
		moderror_msg("Error with parameters dft_size=%d, cyclic_prefix_sz=%d, "
				"first_cyclic_prefix_sz=%d\n",dft_size,cyclic_prefix_sz,first_cyclic_prefix_sz);
		return -1;
	}

	if (first_cyclic_prefix_sz == cyclic_prefix_sz) {
		nof_ofdm_symbols_per_slot = 6;
	} else {
		nof_ofdm_symbols_per_slot = 7;
	}

	for (i=0;i<NOF_INPUT_ITF;i++) {
		input = inp[i];
		output = out[i];
		rcv_samples = get_input_samples(i);
		moddebug("rcv_len=%d samples \n",rcv_samples);

		symbols = div(rcv_samples,dft_size);

		if (symbols.rem) {
			moderror_msg("Number of input samples (%d) must be "
			"integer multiple of dft_size (%d) on interface "
			"%d\n",rcv_samples,dft_size,i);
			return -1;
		}

		nof_ofdm_symb = symbols.quot;

		if (nof_ofdm_symb) {
			k = 0;
			cnt = 0;
			for (j=0;j<nof_ofdm_symb;j++) {
				if (j == k*nof_ofdm_symbols_per_slot) {
					cpy = first_cyclic_prefix_sz;
					k++;
				} else {
					cpy = cyclic_prefix_sz;
				}
				memcpy(output, &input[dft_size-cpy], sizeof(input_t)*cpy);
				memcpy(&output[cpy], input, sizeof(input_t)*dft_size);
				input += dft_size;
				output += dft_size+cpy;
				cnt += dft_size+cpy;
			}

			set_output_samples(i, cnt);
		}
	}
	return 0;
}
Пример #29
0
/**
 * @ingroup lte_ratematching
 *
 * Main DSP function
 *
 */
int work(void **inp, void **out) {
	int in_len,nof_active_itf,out_len,out_len_block,rvidx;
	int i,j;
	int fft_size, mcs,cp_is_long,nrb;
	char *input_b;
	char *output_b;
	float *input_f;
	float *output_f;

	if (!get_input_samples(0)) {
		return 0;
	}

	if (out_len_id) {
		if (param_get_int(out_len_id, &out_len) != 1) {
			moderror("Error getting parameter out_len\n");
			return -1;
		}
	} else {
		if (tslot_idx_id) {
			if (param_get_int(tslot_idx_id, &tslot_idx) != 1) {
				moderror("Error getting parameter tslot_idx\n");
				return -1;
			}
		}
		if (param_get_int(fft_size_id, &fft_size) != 1) {
			moderror("Error getting parameter fft_size\n");
			return -1;
		}
		if (param_get_int(mcs_id, &mcs) != 1) {
			moderror("Error getting parameter mcs\n");
			return -1;
		}
		if (param_get_int(nrb_id, &nrb) != 1) {
			moderror("Error getting parameter nrb\n");
			return -1;
		}
		if (param_get_int(cp_long_id, &cp_is_long) != 1) {
			moderror("Error getting parameter cp_is_long\n");
			return -1;
		}
		if (!direction) {
			out_len = lte_get_psdch_bits_x_slot(lteslots_x_timeslot*tslot_idx, fft_size, cp_is_long, lteslots_x_timeslot)*
					lte_get_modulation_format(mcs);
		} else {
			out_len = lte_get_cbits(mcs,nrb);
		}
		if (out_len == -1) {
			moderror("Error computing bits per slot\n");
			return -1;
		}
	}


	if (rvidx_id) {
		if (param_get_int(rvidx_id, &rvidx) != 1) {
			moderror("Error getting parameter rvidx\n");
			return -1;
		}
	} else {
		rvidx = 0;
	}

	nof_active_itf = 0;
	for (i=0;i<NOF_INPUT_ITF;i++) {
		if (get_input_samples(i))
			nof_active_itf++;
	}
	
	if (!nof_active_itf) {
		return 0;
	}
	
	out_len_block = out_len/nof_active_itf;
	output_f = out[0];
	output_b = out[0];

	for (i=0;i<NOF_INPUT_ITF;i++) {
		input_f = inp[i];
		input_b = inp[i];
		in_len = get_input_samples(i);

		if (in_len && inp[i]) {
			if(!direction) {
				if (char_RM_block(input_b,&output_b[i*out_len_block],in_len,
						out_len_block,rvidx)) {
					return -1;
				}
			} else {
				if (float_UNRM_block(input_f,&output_f[i*out_len_block],in_len,
						out_len_block,rvidx)) {
					return -1;
				}	
			}

		}
	}
	tslot_idx++;
	if (tslot_idx == LTE_NOF_SLOTS_X_FRAME/lteslots_x_timeslot) {
		tslot_idx = 0;
	}
	return out_len_block*nof_active_itf;
}