/* fsk_demod_state.h */

#ifndef FSK_DEMOD_STATE_H

#include "rpack.h"


/*
 * Demodulator state.
 * Different copy is required for each channel & subchannel being processed concurrently.
 */

// TODO1.2:  change prefix from BP_ to DSP_

typedef enum bp_window_e { BP_WINDOW_TRUNCATED, 
				BP_WINDOW_COSINE, 
				BP_WINDOW_HAMMING,
				BP_WINDOW_BLACKMAN,
				BP_WINDOW_FLATTOP } bp_window_t;


struct demodulator_state_s
{
/*
 * These are set once during initialization.
 */

	char profile;			// 'A', 'B', etc.	Upper case.
					// Only needed to see if we are using 'F' to take fast path.

#define TICKS_PER_PLL_CYCLE ( 256.0 * 256.0 * 256.0 * 256.0 )

	int pll_step_per_sample;	// PLL is advanced by this much each audio sample.
					// Data is sampled when it overflows.


	int ms_filter_size;		/* Size of mark & space filters, in audio samples. */
					/* Started off as a guess of one bit length */
					/* but somewhat longer turned out to be better. */
					/* Currently using same size for any prefilter. */

#define MAX_FILTER_SIZE 320		/* 304 is needed for profile C, 300 baud & 44100. */

/*
 * Filter length for Mark & Space in bit times.
 * e.g.  1 means 1/1200 second for 1200 baud.
 */
	float ms_filter_len_bits;

/* 
 * Window type for the various filters.
 */
	
	bp_window_t pre_window;
	bp_window_t ms_window;
	bp_window_t lp_window;


/*
 * Alternate Low pass filters.
 * First is arbitrary number for quick IIR.
 * Second is frequency as ratio to baud rate for FIR.
 */
	int lpf_use_fir;		/* 0 for IIR, 1 for FIR. */

	float lpf_iir;			/* Only if using IIR. */

	float lpf_baud;			/* Cutoff frequency as fraction of baud. */
					/* Intuitively we'd expect this to be somewhere */
					/* in the range of 0.5 to 1. */
					/* In practice, it turned out a little larger */
					/* for profiles B, C, D. */

	float lp_filter_len_bits;  	/* Length in number of bit times. */

	int lp_filter_size;		/* Size of Low Pass filter, in audio samples. */
					/* Previously it was always the same as the M/S */
					/* filters but in version 1.2 it's now independent. */

/*
 * Automatic gain control.  Fast attack and slow decay factors.
 */
	float agc_fast_attack;
	float agc_slow_decay;

/*
 * Use a longer term view for reporting signal levels.
 */
	float quick_attack;
	float sluggish_decay;

/*
 * Hysteresis before final demodulator 0 / 1 decision.		
 */
	float hysteresis;
	int num_slicers;		/* >1 for multiple slicers. */

/* 
 * Phase Locked Loop (PLL) inertia.
 * Larger number means less influence by signal transitions.
 */
	float pll_locked_inertia;
	float pll_searching_inertia;
			

/*
 * Optional band pass pre-filter before mark/space detector.
 */
	int use_prefilter;	/* True to enable it. */

	float prefilter_baud;	/* Cutoff frequencies, as fraction of */
				/* baud rate, beyond tones used.  */
				/* Example, if we used 1600/1800 tones at */
				/* 300 baud, and this was 0.5, the cutoff */
				/* frequencies would be: */
				/* lower = min(1600,1800) - 0.5 * 300 = 1450 */
				/* upper = max(1600,1800) + 0.5 * 300 = 1950 */

	float pre_filter_len_bits;  /* Length in number of bit times. */

	int pre_filter_size;	/* Size of pre filter, in audio samples. */									

	float pre_filter[MAX_FILTER_SIZE] __attribute__((aligned(16)));

/*
 * Kernel for the mark and space detection filters.
 */
					
	float m_sin_table[MAX_FILTER_SIZE] __attribute__((aligned(16)));
	float m_cos_table[MAX_FILTER_SIZE] __attribute__((aligned(16)));

	float s_sin_table[MAX_FILTER_SIZE] __attribute__((aligned(16)));
	float s_cos_table[MAX_FILTER_SIZE] __attribute__((aligned(16)));

/*
 * The rest are continuously updated.
 */

/*
 * Most recent raw audio samples, before/after prefiltering.
 */
	float raw_cb[MAX_FILTER_SIZE] __attribute__((aligned(16)));

/*
 * Use half of the AGC code to get a measure of input audio amplitude.
 * These use "quick" attack and "sluggish" decay while the 
 * AGC uses "fast" attack and "slow" decay.
 */

	float alevel_rec_peak;
	float alevel_rec_valley;
	float alevel_mark_peak;
	float alevel_space_peak;

/*
 * Input to the mark/space detector.
 * Could be prefiltered or raw audio.
 */
	float ms_in_cb[MAX_FILTER_SIZE] __attribute__((aligned(16)));

/*
 * Outputs from the mark and space amplitude detection, 
 * used as inputs to the FIR lowpass filters.
 * Kernel for the lowpass filters.
 */

	float m_amp_cb[MAX_FILTER_SIZE] __attribute__((aligned(16)));
	float s_amp_cb[MAX_FILTER_SIZE] __attribute__((aligned(16)));

	float lp_filter[MAX_FILTER_SIZE] __attribute__((aligned(16)));


	float m_peak, s_peak;
	float m_valley, s_valley;
	float m_amp_prev, s_amp_prev;

/*
 * For the PLL and data bit timing.
 * starting in version 1.2 we can have multiple slicers for one demodulator.
 * Each slicer has its own PLL and HDLC decoder.
 */

#if 1
	struct {

		signed int data_clock_pll;		// PLL for data clock recovery.
							// It is incremented by pll_step_per_sample
							// for each audio sample.

		signed int prev_d_c_pll;		// Previous value of above, before
							// incrementing, to detect overflows.

		int prev_demod_data;			// Previous data bit detected.
							// Used to look for transitions.

		/* This is used only for "9600" baud data. */

		int lfsr;				// Descrambler shift register.

	} slicer [MAX_SUBCHANS];

#else
	signed int data_clock_pll;		// PLL for data clock recovery.
						// It is incremented by pll_step_per_sample
						// for each audio sample.

	signed int prev_d_c_pll;		// Previous value of above, before
						// incrementing, to detect overflows.

	int prev_demod_data;			// Previous data bit detected.
						// Used to look for transitions.
#endif



/* 
 * Special for Rino decoder only.
 * One for each possible signal polarity.
 */

#if 0

	struct gr_state_s {

	  signed int data_clock_pll;		// PLL for data clock recovery.
						// It is incremented by pll_step_per_sample
						// for each audio sample.
  
	  signed int prev_d_c_pll;		// Previous value of above, before
						// incrementing, to detect overflows.

	  float gr_minus_peak;	// For automatic gain control.
	  float gr_plus_peak;

	  int gr_sync;		// Is sync pulse present?
	  int gr_prev_sync;	// Previous state to detect leading edge.

	  int gr_first_sample;	// Index of starting sample index for debugging.

	  int gr_dcd;		// Data carrier detect.  i.e. are we 
				// currently decoding a message.

	  float gr_early_sum;	// For averaging bit values in two regions.
	  int gr_early_count;
	  float gr_late_sum;
	  int gr_late_count;
	  float gr_sync_sum;
	  int gr_sync_count;

	  int gr_bit_count;	// Bit index into message.

	  struct rpack_s rpack;	// Collection of bits.

	} gr_state[2];
#endif

};

#define FSK_DEMOD_STATE_H 1
#endif