/*
 * Radio device interface with sample rate conversion
 * Written by Thomas Tsou <tom@tsou.cc>
 *
 * Copyright 2011, 2012, 2013 Free Software Foundation, Inc.
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 * See the COPYING file in the main directory for details.
 */

#include <radioInterface.h>
#include <Logger.h>

#include "Resampler.h"

extern "C" {
#include "convert.h"
}

/* New chunk sizes for resampled rate */
#ifdef INCHUNK
  #undef INCHUNK
#endif
#ifdef OUTCHUNK
  #undef OUTCHUNK
#endif

/* Resampling parameters for 100 MHz clocking */
#define RESAMP_INRATE			52
#define RESAMP_OUTRATE			75
#define RESAMP_FILT_LEN			16

#define INCHUNK				(RESAMP_INRATE * 4)
#define OUTCHUNK			(RESAMP_OUTRATE * 4)

static Resampler *upsampler = NULL;
static Resampler *dnsampler = NULL;
short *convertRecvBuffer = NULL;
short *convertSendBuffer = NULL;

RadioInterfaceResamp::RadioInterfaceResamp(RadioDevice *wRadio,
					   int wReceiveOffset,
					   int wSPS,
					   GSM::Time wStartTime)
	: RadioInterface(wRadio, wReceiveOffset, wSPS, wStartTime),
	  innerSendBuffer(NULL), outerSendBuffer(NULL),
	  innerRecvBuffer(NULL), outerRecvBuffer(NULL)
{
}

RadioInterfaceResamp::~RadioInterfaceResamp()
{
	close();
}

void RadioInterfaceResamp::close()
{
	RadioInterface::close();

	delete innerSendBuffer;
	delete outerSendBuffer;
	delete innerRecvBuffer;
	delete outerRecvBuffer;

	delete upsampler;
	delete dnsampler;

	innerSendBuffer = NULL;
	outerSendBuffer = NULL;
	innerRecvBuffer = NULL;
	outerRecvBuffer = NULL;

	upsampler = NULL;
	dnsampler = NULL;
}

/* Initialize I/O specific objects */
bool RadioInterfaceResamp::init()
{
	float cutoff = 1.0f;

	close();

	/*
	 * With oversampling, restrict bandwidth to 150% of base rate. This also
	 * provides last ditch bandwith limiting if the pulse shaping filter is
	 * insufficient.
	 */
	if (sps > 1)
		cutoff = 1.5 / sps;

	dnsampler = new Resampler(RESAMP_INRATE, RESAMP_OUTRATE);
	if (!dnsampler->init(cutoff)) {
		LOG(ALERT) << "Rx resampler failed to initialize";
		return false;
	}

	upsampler = new Resampler(RESAMP_OUTRATE, RESAMP_INRATE);
	if (!upsampler->init(cutoff)) {
		LOG(ALERT) << "Tx resampler failed to initialize";
		return false;
	}

	/*
	 * Allocate high and low rate buffers. The high rate receive
	 * buffer and low rate transmit vectors feed into the resampler
	 * and requires headroom equivalent to the filter length. Low
	 * rate buffers are allocated in the main radio interface code.
	 */
	innerSendBuffer = new signalVector(INCHUNK * 20, RESAMP_FILT_LEN);
	outerSendBuffer = new signalVector(OUTCHUNK * 20);

	outerRecvBuffer = new signalVector(OUTCHUNK * 2, RESAMP_FILT_LEN);
	innerRecvBuffer = new signalVector(INCHUNK * 20);

	convertSendBuffer = new short[OUTCHUNK * 2 * 20];
	convertRecvBuffer = new short[OUTCHUNK * 2 * 2];

	sendBuffer = innerSendBuffer;
	recvBuffer = innerRecvBuffer;

	return true;
}

/* Receive a timestamped chunk from the device */
void RadioInterfaceResamp::pullBuffer()
{
	bool local_underrun;
	int rc, num_recv;
	int inner_len = INCHUNK;
	int outer_len = OUTCHUNK;

	/* Outer buffer access size is fixed */
	num_recv = mRadio->readSamples(convertRecvBuffer,
				       outer_len,
				       &overrun,
				       readTimestamp,
				       &local_underrun);
	if (num_recv != outer_len) {
		LOG(ALERT) << "Receive error " << num_recv;
		return;
	}

	convert_short_float((float *) outerRecvBuffer->begin(),
			    convertRecvBuffer, 2 * outer_len);

	underrun |= local_underrun;
	readTimestamp += (TIMESTAMP) num_recv;

	/* Write to the end of the inner receive buffer */
	rc = dnsampler->rotate((float *) outerRecvBuffer->begin(), outer_len,
			       (float *) (innerRecvBuffer->begin() + recvCursor),
			       inner_len);
	if (rc < 0) {
		LOG(ALERT) << "Sample rate upsampling error";
	}

	recvCursor += inner_len;
}

/* Send a timestamped chunk to the device */
void RadioInterfaceResamp::pushBuffer()
{
	int rc, chunks, num_sent;
	int inner_len, outer_len;

	if (sendCursor < INCHUNK)
		return;

	chunks = sendCursor / INCHUNK;
	if (chunks > 8)
		chunks = 8;

	inner_len = chunks * INCHUNK;
	outer_len = chunks * OUTCHUNK;

	/* Always send from the beginning of the buffer */
	rc = upsampler->rotate((float *) innerSendBuffer->begin(), inner_len,
			       (float *) outerSendBuffer->begin(), outer_len);
	if (rc < 0) {
		LOG(ALERT) << "Sample rate downsampling error";
	}

	convert_float_short(convertSendBuffer,
			    (float *) outerSendBuffer->begin(),
			    powerScaling, 2 * outer_len);

	num_sent = mRadio->writeSamples(convertSendBuffer,
					outer_len,
					&underrun,
					writeTimestamp);
	if (num_sent != outer_len) {
		LOG(ALERT) << "Transmit error " << num_sent;
	}

	/* Shift remaining samples to beginning of buffer */
	memmove(innerSendBuffer->begin(),
		innerSendBuffer->begin() + inner_len,
		(sendCursor - inner_len) * 2 * sizeof(float));

	writeTimestamp += outer_len;
	sendCursor -= inner_len;
	assert(sendCursor >= 0);
}
