#include <stdlib.h>
#include <stdio.h>

#include "trx.h"
#include "rtty.h"
#include "baudot.h"
#include "filter.h"
#include "fftfilt.h"
#include "prefs.h"

static void rtty_txinit(struct trx *trx)
{
        struct rtty *r = (struct rtty *) trx->modem;

	r->rxmode = BAUDOT_LETS;
	r->txmode = BAUDOT_LETS;

	/* start each transmission with 440ms of MARK tone */
	r->preamble = 20;
}

static void rtty_free(struct rtty *s)
{
	if (s) {
		clear_filter(s->hilbert);
		free(s);
	}
}

static void rtty_rxinit(struct trx *trx)
{
        struct rtty *r = (struct rtty *) trx->modem;

	r->rxmode = BAUDOT_LETS;
	r->txmode = BAUDOT_LETS;
}

static void rtty_destructor(struct trx *trx)
{
	struct rtty *s = (struct rtty *) trx->modem;

	rtty_free(s);

        trx->modem = NULL;
        trx->txinit = NULL;
        trx->rxinit = NULL;
        trx->txprocess = NULL;
        trx->rxprocess = NULL;
        trx->destructor = NULL;
}

void rtty_init(struct trx *trx)
{
	struct rtty *s;
	double flo, fhi, bw;

	if ((s = calloc(1, sizeof(struct rtty))) == NULL)
		return;

	s->shift = prefs.rttyshift;
	s->symbollen = (int) (SampleRate / prefs.rttybaud + 0.5);
	switch (prefs.rttybits) {
	case 0:
		s->nbits = 5;
		break;
	case 1:
		s->nbits = 7;
		break;
	case 2:
		s->nbits = 8;
		break;
	}
	switch (prefs.rttyparity) {
	case 0:
		s->parity = PARITY_NONE;
		break;
	case 1:
		s->parity = PARITY_EVEN;
		break;
	case 2:
		s->parity = PARITY_ODD;
		break;
	case 3:
		s->parity = PARITY_ZERO;
		break;
	case 4:
		s->parity = PARITY_ONE;
		break;
	}
	switch (prefs.rttystop) {
	case 0:
		s->stoplen = (int) (1.0 * SampleRate / prefs.rttybaud + 0.5);
		break;
	case 1:
		s->stoplen = (int) (1.5 * SampleRate / prefs.rttybaud + 0.5);
		break;
	case 2:
		s->stoplen = (int) (2.0 * SampleRate / prefs.rttybaud + 0.5);
		break;
	}
	s->reverse = (prefs.rttyreverse == TRUE) ? 1 : 0;
	s->msb = (prefs.rttymsb == TRUE) ? 1 : 0;

	if (s->symbollen > MaxSymLen || s->stoplen > MaxSymLen) {
		fprintf(stderr, "RTTY: symbol length too big\n");
		rtty_free(s);
		return;
	}

	bw = prefs.rttybaud * 1.1;
	flo = (s->shift / 2 - bw) / SampleRate;
	fhi = (s->shift / 2 + bw) / SampleRate;
	flo = 0;
//	fhi = 0.25;
//	fprintf(stderr, "flo=%f fhi=%f\n", flo * SampleRate, fhi * SampleRate);

	if ((s->hilbert = init_filter(0.05, 0.45)) == NULL) {
		rtty_free(s);
		return;
	}

	if ((s->fftfilt = init_fftfilt(flo, fhi, 2048)) == NULL) {
		rtty_free(s);
		return;
	}

        trx->modem = s;

	trx->txinit = rtty_txinit;
	trx->rxinit = rtty_rxinit;

	trx->txprocess = rtty_txprocess;
	trx->rxprocess = rtty_rxprocess;

	trx->destructor = rtty_destructor;

	trx->samplerate = SampleRate;
	trx->fragmentsize = 256;
	trx->bandwidth = s->shift;
}
