/*
 * Radio device interface with sample rate conversion
 *
 * Copyright (C) 2011-2014 Free Software Foundation, Inc.
 * Copyright (C) 2015 Ettus Research LLC
 *
 * Author: Tom Tsou <tom@tsou.cc>
 *
 * SPDX-License-Identifier: AGPL-3.0+
 *
 * 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"
}

/* Resampling parameters for 64 MHz clocking */
#define RESAMP_64M_INRATE			65
#define RESAMP_64M_OUTRATE			96

/* Resampling parameters for 100 MHz clocking */
#define RESAMP_100M_INRATE			52
#define RESAMP_100M_OUTRATE			75

/* Universal resampling parameters */
#define NUMCHUNKS				24

/*
 * Resampling filter bandwidth scaling factor
 *   This narrows the filter cutoff relative to the output bandwidth
 *   of the polyphase resampler. At 4 samples-per-symbol using the
 *   2 pulse Laurent GMSK approximation gives us below 0.5 degrees
 *   RMS phase error at the resampler output.
 */
#define RESAMP_TX4_FILTER		0.45

static Resampler *upsampler = NULL;
static Resampler *dnsampler = NULL;
static size_t resamp_inrate = 0;
static size_t resamp_inchunk = 0;
static size_t resamp_outrate = 0;
static size_t resamp_outchunk = 0;

RadioInterfaceResamp::RadioInterfaceResamp(RadioDevice *wDevice,
					   size_t tx_sps, size_t rx_sps)
	: RadioInterface(wDevice, tx_sps, rx_sps, 1),
	  outerSendBuffer(NULL), outerRecvBuffer(NULL)
{
}

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

void RadioInterfaceResamp::close()
{
	delete outerSendBuffer;
	delete outerRecvBuffer;

	delete upsampler;
	delete dnsampler;

	outerSendBuffer = NULL;
	outerRecvBuffer = NULL;

	upsampler = NULL;
	dnsampler = NULL;

	if (sendBuffer.size())
		sendBuffer[0] = NULL;
	if (recvBuffer.size())
		recvBuffer[0] = NULL;

	RadioInterface::close();
}

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

	close();

	switch (type) {
	case RadioDevice::RESAMP_64M:
		resamp_inrate = RESAMP_64M_INRATE;
		resamp_outrate = RESAMP_64M_OUTRATE;
		break;
	case RadioDevice::RESAMP_100M:
		resamp_inrate = RESAMP_100M_INRATE;
		resamp_outrate = RESAMP_100M_OUTRATE;
		break;
	case RadioDevice::NORMAL:
	default:
		LOG(ALERT) << "Invalid device configuration";
		return false;
	}

	resamp_inchunk = resamp_inrate * 4 * mSPSRx;
	resamp_outchunk = resamp_outrate * 4 * mSPSRx;

	if (mSPSTx == 4)
		cutoff = RESAMP_TX4_FILTER;

	dnsampler = new Resampler(resamp_inrate, resamp_outrate);
	if (!dnsampler->init()) {
		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.
	 */
	sendBuffer[0] = new RadioBuffer(NUMCHUNKS, resamp_inchunk,
					  upsampler->len(), true);
	recvBuffer[0] = new RadioBuffer(NUMCHUNKS * 20, resamp_inchunk, 0, false);

	outerSendBuffer =
		new signalVector(NUMCHUNKS * resamp_outchunk);
	outerRecvBuffer =
		new signalVector(resamp_outchunk, dnsampler->len());

	convertSendBuffer[0] = new short[outerSendBuffer->size() * 2];
	convertRecvBuffer[0] = new short[outerRecvBuffer->size() * 2];

	return true;
}

/* Receive a timestamped chunk from the device */
int RadioInterfaceResamp::pullBuffer()
{
	bool local_underrun;
	int rc, num_recv;

	if (recvBuffer[0]->getFreeSegments() <= 0)
		return -1;

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

	convert_short_float((float *) outerRecvBuffer->begin(),
			    convertRecvBuffer[0], 2 * resamp_outchunk);

	osmo_trx_sync_or_and_fetch(&underrun, local_underrun);
	readTimestamp += (TIMESTAMP) resamp_outchunk;

	/* Write to the end of the inner receive buffer */
	rc = dnsampler->rotate((float *) outerRecvBuffer->begin(),
			       resamp_outchunk,
			       recvBuffer[0]->getWriteSegment(),
			       resamp_inchunk);
	if (rc < 0) {
		LOG(ALERT) << "Sample rate upsampling error";
	}

	/* Set history for the next chunk */
	outerRecvBuffer->updateHistory();
	return 0;
}

/* Send a timestamped chunk to the device */
bool RadioInterfaceResamp::pushBuffer()
{
	bool local_underrun;
	int rc;
	size_t numSent;

	if (sendBuffer[0]->getAvailSegments() <= 0)
		return false;

	/* Always send from the beginning of the buffer */
	rc = upsampler->rotate(sendBuffer[0]->getReadSegment(),
			       resamp_inchunk,
			       (float *) outerSendBuffer->begin(),
			       resamp_outchunk);
	if (rc < 0) {
		LOG(ALERT) << "Sample rate downsampling error";
	}

	convert_float_short(convertSendBuffer[0],
			    (float *) outerSendBuffer->begin(),
			    powerScaling[0], 2 * resamp_outchunk);

	numSent = mDevice->writeSamples(convertSendBuffer,
				       resamp_outchunk,
				       &local_underrun,
				       writeTimestamp);
	if (numSent != resamp_outchunk) {
		LOG(ALERT) << "Transmit error " << numSent;
	}

	osmo_trx_sync_or_and_fetch(&underrun, local_underrun);
	writeTimestamp += resamp_outchunk;

	return true;
}
