//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//+
//+   Copyright (c) CML Microsystems Plc 2015
//+
//+   This firmware was designed by CML Microcircuits (UK) Ltd, based on
//+   UK originated technology and is only intended for use on CML’s  Evaluation kits.
//+
//+   The supply and use of this Firmware is subject to CML's
//+   Licence Agreement, a copy of which can be obtained from CML on request.
//+
//+   Contact details:
//+   Technical:  techsupport@cmlmicro.com
//+   Sales:  sales@cmlmicro.com
//+
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++



#include "chip.h"
#include "pe0003.h"
#include "pe0003_config.h"
#include "ftdi.h"
#include "cbus.h"
#include "gpio.h"
#include "timer.h"
#include "lpc_types.h"

#include "mon_file.h"
#include "mon_general.h"


#include "ProgTools.h"
#include "Settings.h"
#include "Registers.h"

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


//Global variables
//Use static buffers
//	-	as global to get more control in the memory allocation
//		(KEY TO HELP IN THE MEMORY ALLOCATION AND MAXIMIZE MEMORY USE OF LPC4330)
//	-	all the buffers share the same static buffers
///Static Buffers allocated in RAM2
__BSS(RAM2) uint16_t sBufferOut[OUTSTATICBUFFER_SIZE];
__BSS(RAM2) uint16_t sBufferIn[INSTATICBUFFER_SIZE];




//-------------------------------------------------------------------
//
//		MENUES
//
//-------------------------------------------------------------------



uint8_t Menu_DefaultSelection(uint8_t defOpt)
{
	while(defOpt == 0)
	{
		mprintf("\n");
		mprintf("Select configuration:\n");
		mprintf("	1): Custom Encoder Operation\n");
		mprintf("	2): Custom Decoder Operation\n");
		mprintf("	3): Custom Decoder Infinite Loop Operation\n");
		mprintf("	4): Custom Transcoder Operation\n");
		mprintf("	5): Custom Encoder/Decoder Operation\n");
		mprintf("	6): G279A Encoder Operation\n");
		mprintf("	7): G279A Decoder Operation\n");
		mprintf("	8): G279A Decoder Infinite Loop Operation\n");
		mprintf("	9): G279A Decoder Infinite Loop2 Operation\n");
		mprintf("	10): Unpacked CVSD Encoder Operation\n");
		mprintf("	11): Unpacked CVSD Decoder Operation\n");
		mprintf("	12): Unpacked CVSD Decoder Infinite Loop Operation\n");
		mprintf("	13): Unpacked CVSD Decoder Infinite Loop2 Operation\n");
		mprintf("	14): G279A CVSD Transcoder Operation\n");
		mprintf("	15): PCM PCM Transcoder Operation\n");
		mscanf("%u", defOpt);
	}

	return defOpt;
}


//-------------------------------------------------------------------
//
//		PRECONFIGURE OPERATIONS - HELP FUNCTIONS
//
//-------------------------------------------------------------------

/**
 * @brief Open a file for reading according to the configuration set at Settings.h. (FOR PR7261)
 * @param file_id	- File identifier
 * @param filename	- Filename (not used)
 * @param fileOperation - FILE_WRITE or FILE_READ to open for writing or reading respectively
 * @param fileType - Type of file - CFG_WAV_FILE, CFG_TEXT_FILE, CFG_BIN_FILE(Default)
 * @return GUI_FILE_OK if there is not errors
 */
uint8_t PR7261_FileDialogOpen(uint8_t *file_id,  const char* filename, uint8_t fileOperation, uint8_t fileType)
{
	uint8_t res = 0;

	//WAV FILE
	if (fileType == CFG_WAV_FILE)
	{
		uint8_t isStereo = 0;

		if (fileOperation == FILE_WRITE)
			mprintf("Select WAV File to store the data...\n");
		else
			mprintf("Select WAV File to load data from...\n");

		if (WAV_CHANNELS == 1)
			isStereo = FILEWAV_MONO;
		else
			isStereo = FILEWAV_STEREO;

		res = Gui_FileWavDialogOpen(file_id, filename, fileOperation, isStereo, FILEWAV_BITSPERSAMPLE_16B, WAV_SAMPLERATE);
	}
	else
	{
		//TEXT FILE
		if (fileType == CFG_TEXT_FILE)
		{
			if (fileOperation == FILE_WRITE)
				mprintf("Select file to store data...\n");
			else
				mprintf("Select file to load data from...\n");
			res = Gui_FileTxtDialogOpen(file_id, filename, fileOperation, "%d");
		}
		else
		{
			//DEFAULT BIN FILE
			if (fileOperation == FILE_WRITE)
				mprintf("Select binary file to store data...\n");
			else
				mprintf("Select binary file to load data from...\n");
			res = Gui_FileBinDialogOpen(file_id, filename, fileOperation);
		}
	}

	return res;
}

/**
 * @brief Read samples from a file. (FOR PR7261)
 * @param file_id - file identifier
 * @param data - Data array to hold the samples (word size)
 * @param length - Number of samples
 * @param nDataRead - Number of samples read back
 * @param fileType - Type of file - CFG_WAV_FILE, CFG_TEXT_FILE, CFG_BIN_FILE(Default)
 * @return GUI_FILE_OK if there is not errors
 */
uint8_t PR7261_FileReadSamples(uint8_t file_id, uint16_t *data, uint32_t length, uint32_t *nDataRead, uint8_t fileType )
{
	uint8_t res;

	//Read some data first
	if (fileType == CFG_WAV_FILE)
		res = Gui_FileWavReadWordSamples(file_id, (uint16_t *)data, OUTBUFFER_SIZE , nDataRead);
	else
	{
		if (fileType == CFG_TEXT_FILE)
			res = Gui_FileTxtRead(file_id, (uint8_t *)data, OUTBUFFER_SIZE , nDataRead, FILE_TYPE_WORD);
		else
			res = Gui_FileReadWord(file_id, data, OUTBUFFER_SIZE , nDataRead);
	}

	return res;
}

/**
 * @brief Write samples into a file. (FOR PR7261)
 * @param file_id - file identifier
 * @param data - Data array with the samples (word size)
 * @param length - Number of samples
 * @param nDataWritten - Number of samples to write
 * @param fileType - Type of file - CFG_WAV_FILE, CFG_TEXT_FILE, CFG_BIN_FILE(Default)
 * @return GUI_FILE_OK if there is not errors
 */
uint8_t PR7261_FileWriteSamples(uint8_t file_id, uint16_t *data, uint32_t length, uint32_t *nDataWritten, uint8_t fileType)
{
	uint8_t res;

	if (fileType == CFG_WAV_FILE)
		res = Gui_FileWavWriteWordSamples(file_id, data, INBUFFER_SIZE, nDataWritten);
	else
	{
		if (fileType == CFG_TEXT_FILE)
			res = Gui_FileTxtWrite(file_id, (uint8_t *) data, INBUFFER_SIZE, nDataWritten, FILE_TYPE_WORD);
		else
			res = Gui_FileWriteWord(file_id, data, INBUFFER_SIZE, nDataWritten);	//BIN FILE DEFAULT
	}
	return res;
}


/**
 * @brief Close file. (FOR PR7261)
 * @param file_id - file identifier
 * @param fileType - Type of file - CFG_WAV_FILE, CFG_TEXT_FILE, CFG_BIN_FILE(Default)
 * @return GUI_FILE_OK if there is not errors
 */
uint8_t PR7261_FileClose(uint8_t file_id, uint8_t fileType)
{
	uint8_t res;

	if (fileType == CFG_WAV_FILE)
		res = Gui_FileWavClose(file_id);
	else
	{
		if (fileType == CFG_TEXT_FILE)
			res = Gui_FileClose(file_id);
		else
			res = Gui_FileClose(file_id);
	}

	return res;
}




//-------------------------------------------------------------------
//
//		PRECONFIGURE OPERATIONS
//
//-------------------------------------------------------------------



uint8_t G279A_Encoder_Op(uint32_t nSamples)
{
	uint8_t res;
	uint32_t i = 0;
	uint8_t level = 0;
	uint16_t val = 0;
	uint8_t file_id = 0;
	uint32_t nDataWritten;
	uint16_t nstatus = 0;

	uint16_t bufferIn[INBUFFER_SIZE];
	uint32_t j = 0;

	//Open file for writting
	char filename[] = "dummy.dat";
	res = PR7261_FileDialogOpen(&file_id, filename, FILE_WRITE, CFG_OUT_FILE);
	if (res != GUI_FILE_RESULT_OK)
	{
		mprintf("ERROR - Opening file for writing\n");
	}


	Pe0003_CbusWriteWord(CBUSPORT, MODE_REG, 0);						//Idle mode to configure
	Pe0003_CbusWriteWord(CBUSPORT, ANAIN_CONF, ANAIN_CONF_VAL);	//Power up AnlogIn
	mprintf("ANAIN_CONF_REG 0x%x\n", ANAIN_CONF_VAL);
	Pe0003_CbusWriteWord(CBUSPORT, ANAIN_COARSE_GAIN, ANAIN_COARSE_GAIN_VAL);				//0dB gain
	mprintf("ANAIN_COARSE_GAIN 0x%x\n", ANAIN_COARSE_GAIN_VAL);


	Pe0003_CbusWriteWord(CBUSPORT, FIFO_CONTROL, 0x8080);				//Flush FIFO

	Pe0003_TimerDelayUs(10000);

	Pe0003_CbusWriteWord(CBUSPORT, INPUT_TYPE, INPUT_TYPE_16BIT_SIGNED_PCM);	//16 Bit linear PCM
	mprintf("INPUT_REG 0x%x\n", INPUT_TYPE_16BIT_SIGNED_PCM);
	Pe0003_CbusWriteWord(CBUSPORT, OUTPUT_TYPE, OUTPUT_TYPE_PACKED_G279A);		//G279 samples
	mprintf("OUTPUT_REG 0x%x\n", OUTPUT_TYPE_PACKED_G279A);

	mprintf("MODE_REG 0x%x\n", 0x211);
	Pe0003_CbusWriteWord(CBUSPORT, MODE_REG, 0x211);//(MODE_AUDIO_SRC_CBUS << 8) | (MODE_AUDIO_DST_CBUS << 4) | MODE_HALF_TRANSC);			//Analogue input, CBus output


	Pe0003_TimerDelayUs(10000);

	while(i < nSamples)
	{
		//Read level of the FIFO
		level = Pe0003_CbusReadByte(CBUSPORT, FIFO_OUT_LEVEL);

		if (level > 0)
		{
			//Recover sample
			val = Pe0003_CbusReadWord(CBUSPORT, FIFO_OUT_WORD);

			bufferIn[j++] = val;
			i++;

			//Store data in blocks of 10
			if (j == INBUFFER_SIZE)
			{
				j = 0;
				res = PR7261_FileWriteSamples(file_id, (uint16_t *) &bufferIn[0], INBUFFER_SIZE, &nDataWritten, CFG_OUT_FILE);
				if (res != GUI_FILE_RESULT_OK)
				{
					mprintf("ERROR - Writing data into a file\n");
					return FALSE;
				}

			}

			if (DEBUG_DISP)
			{
				if ((i % 255) == 0)
					mprintf("s%d \n", i);
			}
		}

		/*
		if (level == WARNING_FIFO_LEVEL)
		{
			mprintf("ERROR - Buffer overflow\n");
		}
		*/
		//Check status for underflows
		nstatus = Pe0003_CbusReadWord(CBUSPORT, STATUS);

		if (nstatus & IRQ_OFLOW)			//Check for overflows
		{
			mprintf("ERROR - Buffer overflow\n");
		}
	}


	//Store data left
	if (j > 0)
	{
		//Save data into a file
		res = PR7261_FileWriteSamples(file_id, (uint16_t *) &bufferIn[0], j, &nDataWritten, CFG_OUT_FILE);
		if (res != GUI_FILE_RESULT_OK)
		{
			mprintf("ERROR - Writing data into a file\n");
		}
	}

	//Close file
	res = PR7261_FileClose(file_id, CFG_OUT_FILE);

	mprintf("G279 samples captured\n");

	return TRUE;
}



uint8_t G279A_Decoder_Op(uint32_t nSamples)
{
	uint8_t res;
	uint8_t level = 0;
	uint8_t file_id = 0;
	uint32_t nDataRead;
	uint16_t nstatus = 0;
	uint32_t count = 0;
	uint32_t dispCount = 0;

	uint16_t bufferOut[OUTBUFFER_SIZE];
	uint32_t j = 0;

	//Open file for reading
	char filename[] = "dummy.dat";
	res = PR7261_FileDialogOpen(&file_id, filename, FILE_READ, CFG_IN_FILE);
	if (res != GUI_FILE_RESULT_OK)
	{
		mprintf("ERROR - Opening file for writing\n");
		return FALSE;
	}

	//Configuration
	Pe0003_CbusWriteWord(CBUSPORT, MODE_REG, 0);				//Idle mode to configure
	Pe0003_CbusWriteWord(CBUSPORT, FIFO_CONTROL, 0x8080);		//Flush FIFO

	Pe0003_TimerDelayUs(10000);

	Pe0003_CbusWriteWord(CBUSPORT, INPUT_TYPE, INPUT_TYPE_PACKED_G279A);			//G279 samples
	mprintf("INPUT_REG 0x%x\n", INPUT_TYPE_PACKED_G279A);
	Pe0003_CbusWriteWord(CBUSPORT, OUTPUT_TYPE, OUTPUT_TYPE_16BIT_SIGNED_PCM);		//PCM 16 bit signed linear
	mprintf("OUTPUT_REG 0x%x\n", OUTPUT_TYPE_16BIT_SIGNED_PCM);

	Pe0003_CbusWriteWord(CBUSPORT, ANAOUT_CONF, ANAOUT_CONF_VAL);	//0x802 power up ANAOUT driver
	mprintf("ANAOUT_CONF_REG 0x%x\n", ANAOUT_CONF_VAL);
	Pe0003_CbusWriteWord(CBUSPORT, ANAOUT_COARSE_GAIN, ANAOUT_COARSE_GAIN_VAL);							//0dB attenuation
	mprintf("ANAOUT_COARSE_GAIN_REG 0x%x\n", ANAOUT_COARSE_GAIN_VAL);

	Pe0003_CbusWriteWord(CBUSPORT, REG_DONE_SELECT, REG_DONE_MODE);					//Set interrupt on Mode Reg Done
	Pe0003_CbusWriteWord(CBUSPORT, MODE_REG, 0);									//Idle mode to configure
	//FIXME DANIEL SET INTERRUPT

	mprintf("MODE_REG 0x%x\n", 0x121);
	Pe0003_CbusWriteWord(CBUSPORT, MODE_REG, 0x121);//(MODE_AUDIO_SRC_CBUS << 8) | (MODE_AUDIO_DST_ANA << 4) | MODE_HALF_TRANSC);



	//Read some data first
	res = PR7261_FileReadSamples(file_id, (uint16_t *)bufferOut, OUTBUFFER_SIZE , &nDataRead, CFG_IN_FILE);

	//Normal process
	while(nDataRead != 0)
	{
		while(nDataRead != 0)
		{
			//Check fifo level
			level = Pe0003_CbusReadByte(CBUSPORT, FIFO_IN_LEVEL);

			if (level < MAX_FIFO_SIZE)
			{
				if ((MAX_FIFO_SIZE - level) > nDataRead)
				{
					//Stream some data in
					Pe0003_CbusWriteWstream(CBUSPORT,  FIFO_IN_WORD, &bufferOut[j], nDataRead);		//Stream data into the buffer
					count += nDataRead;
					j = 0;
					nDataRead = 0;
				}
				/*
				else
				{
					uint8_t spaceLeft = MAX_FIFO_SIZE - level;
					Pe0003_CbusWriteWstream(CBUSPORT,  FIFO_IN_WORD, &bufferOut[j], spaceLeft);		//Stream part of the data into the buffer
					j = spaceLeft;
					count += spaceLeft;
					nDataRead -= spaceLeft;
				}
				*/
			}

			//Check status for underflows
			nstatus = Pe0003_CbusReadWord(CBUSPORT, STATUS);

			if (nstatus & IRQ_UFLOW)			//Check for underflow
			{
				mprintf("ERROR - Data underflow\n");
			}

			if (DEBUG_DISP)
			{
				if (count > dispCount)
				{
					dispCount += 255;
					mprintf("s%d \n", count);
				}
			}

			if (count >= nSamples)
				break;
		}

		if (count >= nSamples)
			break;

		//Get more data
		res = PR7261_FileReadSamples(file_id, (uint16_t *)bufferOut, OUTBUFFER_SIZE , &nDataRead, CFG_IN_FILE);
		if (res != GUI_FILE_RESULT_OK)
		{
			mprintf("ERROR - Reading data from file\n");
			return FALSE;
		}
	}

	//Close file
	res = PR7261_FileClose(file_id, CFG_IN_FILE);

	mprintf("G279 samples sent\n");

	return TRUE;
}



uint8_t G279A_Decoder_Op_Loop(uint32_t nSamples)
{
	uint8_t res;
	uint8_t level = 0;
	uint8_t file_id = 0;
	uint32_t nDataRead;
	uint16_t nstatus = 0;
	uint32_t count = 0;
	uint32_t dispCount = 0;
	uint32_t i = 0;
	uint32_t maxSamples = nSamples;
	uint32_t dataLeft;
	uint16_t tmpBufferOut[OUTBUFFER_SIZE];			//Small buffer to deal with small chunks of data
	//uint16_t sBufferOut[OUTSTATICBUFFER_SIZE];

	if (maxSamples > OUTSTATICBUFFER_SIZE)
		maxSamples = OUTSTATICBUFFER_SIZE;

	//Open file for reading
	char filename[] = "dummy.dat";
	res = PR7261_FileDialogOpen(&file_id, filename, FILE_READ, CFG_IN_FILE);
	if (res != GUI_FILE_RESULT_OK)
	{
		mprintf("ERROR - Opening file for writing\n");
		return FALSE;
	}

	//Set configuration
	Pe0003_CbusWriteWord(CBUSPORT, MODE_REG, 0);				//Idle mode to configure
	Pe0003_CbusWriteWord(CBUSPORT, FIFO_CONTROL, 0x8080);		//Flush FIFO

	Pe0003_TimerDelayUs(10000);

	Pe0003_CbusWriteWord(CBUSPORT, INPUT_TYPE, INPUT_TYPE_PACKED_G279A);			//G279 samples
	mprintf("INPUT_REG 0x%x\n", INPUT_TYPE_PACKED_G279A);
	Pe0003_CbusWriteWord(CBUSPORT, OUTPUT_TYPE, OUTPUT_TYPE_16BIT_SIGNED_PCM);		//PCM 16 bit signed linear
	mprintf("OUTPUT_REG 0x%x\n", OUTPUT_TYPE_16BIT_SIGNED_PCM);

	Pe0003_CbusWriteWord(CBUSPORT, ANAOUT_CONF, ANAOUT_CONF_VAL);						//0x802 power up ANAOUT driver
	mprintf("ANAOUT_CONF_REG 0x%x\n", ANAOUT_CONF_VAL);
	Pe0003_CbusWriteWord(CBUSPORT, ANAOUT_COARSE_GAIN, ANAOUT_COARSE_GAIN_VAL);							//0dB gain
	mprintf("ANAOUT_COARSE_GAIN_REG 0x%x\n", ANAOUT_COARSE_GAIN_VAL);

	Pe0003_CbusWriteWord(CBUSPORT, REG_DONE_SELECT, REG_DONE_MODE);					//Set interrupt on Mode Reg Done
	Pe0003_CbusWriteWord(CBUSPORT, MODE_REG, 0);									//Idle mode to configure
	//FIXME DANIEL SET INTERRUPT

	mprintf("MODE_REG 0x%x\n", 0x121);
	Pe0003_CbusWriteWord(CBUSPORT, MODE_REG, 0x121);//(MODE_AUDIO_SRC_CBUS << 8) | (MODE_AUDIO_DST_ANA << 4) | MODE_HALF_TRANSC);



	//First get some data from file
	res = PR7261_FileReadSamples(file_id, (uint16_t *)tmpBufferOut, OUTBUFFER_SIZE , &nDataRead, CFG_IN_FILE);

	i = 0;
	while(nDataRead != 0)
	{
		//Copy data from a temporal buffer into final staticBuffer
		memcpy(&sBufferOut[i], tmpBufferOut, nDataRead * sizeof(uint16_t));
		i += nDataRead;

		//Read more samples
		res = PR7261_FileReadSamples(file_id, (uint16_t *)tmpBufferOut, OUTBUFFER_SIZE , &nDataRead, CFG_IN_FILE);
		if(i + nDataRead > maxSamples)
			break;
	}

	//Add data left
	if (nDataRead != 0)
	{
		if (i != maxSamples)
		{
			dataLeft = maxSamples - i;
			memcpy(&sBufferOut[i], tmpBufferOut, dataLeft * sizeof(uint16_t));

		}
	}

	//Close file
	res = PR7261_FileClose(file_id, CFG_IN_FILE);



	//Normal process. Infinite loop
	i = 0;
	while(1)
	{
		//Check fifo level
		level = Pe0003_CbusReadByte(CBUSPORT, FIFO_IN_LEVEL);

		if (level < MAX_FIFO_SIZE)
		{
			if ((MAX_FIFO_SIZE - level) > OUTBUFFER_SIZE)
			{
				memcpy(tmpBufferOut, &sBufferOut[i], OUTBUFFER_SIZE * sizeof(uint16_t));

				//Stream samples into CBus
				Pe0003_CbusWriteWstream(CBUSPORT,  FIFO_IN_WORD, tmpBufferOut, OUTBUFFER_SIZE);		//Streaming data
				i += OUTBUFFER_SIZE;
				count += OUTBUFFER_SIZE;


				if ((i + OUTBUFFER_SIZE) > maxSamples)
					i = 0;

			}

			//Check status for underflows
			nstatus = Pe0003_CbusReadWord(CBUSPORT, STATUS);

			if (nstatus & IRQ_UFLOW)			//Check for underflow
			{
				mprintf("ERROR - Data underflow\n");
			}

			if (DEBUG_DISP)
			{
				if (count > dispCount)
				{
					dispCount += 255;
					mprintf("s%d \n", count);
				}
			}
		}
	}

	return TRUE;
}



uint8_t G279A_Decoder_Op_Loop2(uint32_t nSamples)
{
	uint8_t res;
	uint8_t level = 0;
	uint8_t file_id = 0;
	uint32_t nDataRead;
	uint16_t nstatus = 0;
	uint32_t count = 0;
	uint32_t dispCount = 0;
	uint32_t i = 0;
	uint32_t maxSamples = nSamples;
	uint16_t tmpBufferOut[OUTBUFFER_SIZE];
	uint32_t dataLeft;


	if (maxSamples > OUTSTATICBUFFER_SIZE)
		maxSamples = OUTSTATICBUFFER_SIZE;


	//Open file for reading
	char filename[] = "dummy.dat";
	res = PR7261_FileDialogOpen(&file_id, filename, FILE_READ, CFG_IN_FILE);
	if (res != GUI_FILE_RESULT_OK)
	{
		mprintf("ERROR - Opening file for writing\n");
		return FALSE;
	}


	//Set configuration
	Pe0003_CbusWriteWord(CBUSPORT, MODE_REG, 0);				//Idle mode to configure
	Pe0003_CbusWriteWord(CBUSPORT, FIFO_CONTROL, 0x8080);		//Flush FIFO

	Pe0003_TimerDelayUs(10000);

	Pe0003_CbusWriteWord(CBUSPORT, INPUT_TYPE, INPUT_TYPE_PACKED_G279A);			//G279 samples
	mprintf("INPUT_REG 0x%x\n", INPUT_TYPE_PACKED_G279A);
	Pe0003_CbusWriteWord(CBUSPORT, OUTPUT_TYPE, OUTPUT_TYPE_16BIT_SIGNED_PCM);		//PCM 16 bit signed linear
	mprintf("OUTPUT_REG 0x%x\n", OUTPUT_TYPE_16BIT_SIGNED_PCM);

	Pe0003_CbusWriteWord(CBUSPORT, ANAOUT_CONF, ANAOUT_CONF_VAL);	//0x802 power up ANAOUT driver
	mprintf("ANAOUT_CONF_REG 0x%x\n", ANAOUT_CONF_VAL);
	Pe0003_CbusWriteWord(CBUSPORT, ANAOUT_COARSE_GAIN, ANAOUT_COARSE_GAIN_VAL);							//0dB gain
	mprintf("ANAOUT_COARSE_GAIN_REG 0x%x\n", ANAOUT_COARSE_GAIN_VAL);

	Pe0003_CbusWriteWord(CBUSPORT, REG_DONE_SELECT, REG_DONE_MODE);					//Set interrupt on Mode Reg Done
	Pe0003_CbusWriteWord(CBUSPORT, MODE_REG, 0);									//Idle mode to configure
	//FIXME DANIEL SET INTERRUPT

	mprintf("MODE_REG 0x%x\n", 0x121);
	Pe0003_CbusWriteWord(CBUSPORT, MODE_REG, 0x121);//(MODE_AUDIO_SRC_CBUS << 8) | (MODE_AUDIO_DST_ANA << 4) | MODE_HALF_TRANSC);



	//Get data into the static buffer
	res = PR7261_FileReadSamples(file_id, (uint16_t *)tmpBufferOut, OUTBUFFER_SIZE , &nDataRead, CFG_IN_FILE);
	i = 0;
	while(nDataRead != 0)
	{
		memcpy(&sBufferOut[i], tmpBufferOut, nDataRead * sizeof(uint16_t));
		i += nDataRead;

		res = PR7261_FileReadSamples(file_id, (uint16_t *)tmpBufferOut, OUTBUFFER_SIZE , &nDataRead, CFG_IN_FILE);

		if(i + nDataRead > maxSamples)
			break;
	}

	//DataLeft to reach nSamples
	if (nDataRead != 0)
	{
		if (i != maxSamples)
		{
			dataLeft = maxSamples - i;
			memcpy(&sBufferOut[i], tmpBufferOut, dataLeft * sizeof(uint16_t));
			i += dataLeft;
		}
	}

	//Close file
	res = PR7261_FileClose(file_id, CFG_IN_FILE);


	//Normal process
	i = 0;
	while(1)
	{

		//Check fifo level
		level = Pe0003_CbusReadByte(CBUSPORT, FIFO_IN_LEVEL);

		if (level < MAX_FIFO_SIZE)
		{
			//Write data into CBus one by one
			Pe0003_CbusWriteWord(CBUSPORT,  FIFO_IN_WORD, sBufferOut[i++]);
			count++;

			if (i == maxSamples)
					i = 0;
		}

		//Check status for underflows
		nstatus = Pe0003_CbusReadWord(CBUSPORT, STATUS);

		if (nstatus & IRQ_UFLOW)			//Check for underflow
		{
			mprintf("ERROR - Data underflow\n");
		}

		if (DEBUG_DISP)
		{
			if (count >= dispCount)
			{
				dispCount += 255;
				mprintf("s%d \n", count);
			}
		}
	}


	return TRUE;
}



uint8_t Unpacked_CVSD_Encoder_Op(uint32_t nSamples)
{
	uint8_t res;
	uint32_t i = 0;
	uint8_t level = 0;
	uint16_t val = 0;
	uint8_t file_id = 0;
	uint32_t nDataWritten;
	uint16_t nstatus = 0;
	uint16_t valReg = 0;

	uint16_t bufferIn[INBUFFER_SIZE];
	uint32_t j = 0;

	//Open file
	char filename[] = "dummy.dat";
	res = PR7261_FileDialogOpen(&file_id, filename, FILE_WRITE, CFG_OUT_FILE);
	if (res != GUI_FILE_RESULT_OK)
	{
		mprintf("ERROR - Opening file for writing\n");
		return FALSE;
	}

	//Main Configuration
	Pe0003_CbusWriteWord(CBUSPORT, MODE_REG, 0);								//Idle mode to configure
	Pe0003_CbusWriteWord(CBUSPORT, ANAIN_CONF, ADC_PWR | ANAIN_PWR);			//Power up AnlogIn
	valReg = ANAIN_CONF, ADC_PWR | ANAIN_PWR;
	mprintf("OUTPUT_REG 0x%x\n", valReg);
	Pe0003_CbusWriteWord(CBUSPORT, ANAIN_COARSE_GAIN, 0);						//0dB gain
	mprintf("ANAIN_COARSE_GAIN_REG 0x%x\n", 0);


	Pe0003_CbusWriteWord(CBUSPORT, FIFO_CONTROL, 0x8080);		//Flush FIFO

	Pe0003_TimerDelayUs(10000);

	Pe0003_CbusWriteWord(CBUSPORT, INPUT_TYPE, INPUT_TYPE_16BIT_SIGNED_PCM | RATE_32KHZ);			//16 Bit linear PCM
	valReg = INPUT_TYPE_16BIT_SIGNED_PCM | RATE_32KHZ;
	mprintf("INPUT_REG 0x%x\n", valReg);
	Pe0003_CbusWriteWord(CBUSPORT, OUTPUT_TYPE, OUTPUT_TYPE_UNPACKED_CVSD | RATE_32KHZ);		//Unpacked CVSD 32Kbps
	valReg = OUTPUT_TYPE_UNPACKED_CVSD | RATE_32KHZ;
	mprintf("OUTPUT_REG 0x%x\n", valReg);

	mprintf("MODE_REG 0x%x\n", 0x211);
	Pe0003_CbusWriteWord(CBUSPORT, MODE_REG, 0x211);//(MODE_AUDIO_SRC_ANA << 8) | (MODE_AUDIO_DST_CBUS << 4) | MODE_HALF_TRANSC);			//Analogue input, CBus output


	Pe0003_TimerDelayUs(10000);

	while(i < nSamples)
	{
		//Chekc fifo level
		level = Pe0003_CbusReadByte(CBUSPORT, FIFO_OUT_LEVEL);

		if (level > 0)
		{
			//GEt sample from fifo
			val = Pe0003_CbusReadWord(CBUSPORT, FIFO_OUT_WORD);

			bufferIn[j++] = val;
			i++;

			//Store data in blocks of 10
			if (j == INBUFFER_SIZE)
			{
				j = 0;
				res = PR7261_FileWriteSamples(file_id, (uint16_t *) &bufferIn[0], INBUFFER_SIZE, &nDataWritten, CFG_OUT_FILE);
				if (res != GUI_FILE_RESULT_OK)
				{
					mprintf("ERROR - Writing data into a file\n");
					return FALSE;
				}

			}

			if (DEBUG_DISP)
			{
				if ((i % 255) == 0)
					mprintf("s%d \n", i);
			}
		}

		/*
		if (level == WARNING_FIFO_LEVEL)
		{
			mprintf("ERROR - Buffer overflow\n");
		}
		*/

		//Check status for underflows
		nstatus = Pe0003_CbusReadWord(CBUSPORT, STATUS);
		if (nstatus & IRQ_OFLOW)			//Check for overflows
		{
			mprintf("ERROR - Buffer overflow\n");
		}
	}


	//Store samples left in the buffer
	if (j > 0)
	{
		res = PR7261_FileWriteSamples(file_id, (uint16_t *) &bufferIn[0], j, &nDataWritten, CFG_OUT_FILE);
		if (res != GUI_FILE_RESULT_OK)
		{
			mprintf("ERROR - Writing data into a file\n");
			return FALSE;
		}
	}

	//Close file
	res = PR7261_FileClose(file_id, CFG_OUT_FILE);


	mprintf("CVSD samples captured\n");

	return TRUE;
}




uint8_t Unpacked_CVSD_Decoder_Op(uint32_t nSamples)
{
	uint8_t res;
	uint8_t level = 0;
	uint8_t file_id = 0;
	uint32_t nDataRead;
	uint16_t nstatus = 0;
	uint32_t count = 0;
	uint32_t dispCount = 0;
	uint16_t valReg = 0;

	uint16_t bufferOut[OUTBUFFER_SIZE];
	uint32_t j = 0;

	//Open file to get the samples
	char filename[] = "dummy.dat";
	res = PR7261_FileDialogOpen(&file_id, filename, FILE_READ, CFG_IN_FILE);
	if (res != GUI_FILE_RESULT_OK)
	{
		mprintf("ERROR - Opening file for reading\n");
		return FALSE;
	}

	//Main configuration
	Pe0003_CbusWriteWord(CBUSPORT, MODE_REG, 0);				//Idle mode to configure
	Pe0003_CbusWriteWord(CBUSPORT, FIFO_CONTROL, 0x8080);		//Flush FIFO

	Pe0003_TimerDelayUs(10000);

	Pe0003_CbusWriteWord(CBUSPORT, INPUT_TYPE, INPUT_TYPE_UNPACKED_CVSD | RATE_32KHZ);		//Unpacked CVSD 32Kbps
	valReg = INPUT_TYPE_UNPACKED_CVSD | RATE_32KHZ;
	mprintf("INPUT_REG 0x%x\n", valReg);
	Pe0003_CbusWriteWord(CBUSPORT, OUTPUT_TYPE, OUTPUT_TYPE_16BIT_SIGNED_PCM | RATE_32KHZ);	//PCM 16 bit signed linear
	valReg = OUTPUT_TYPE_16BIT_SIGNED_PCM | RATE_32KHZ;
	mprintf("OUTPUT_REG 0x%x\n", valReg);

	Pe0003_CbusWriteWord(CBUSPORT, ANAOUT_CONF, ANAOUT_CONF_VAL);	//0x802 power up ANAOUT driver
	mprintf("ANAOUT_CONF_REG 0x%x\n", ANAOUT_CONF_VAL);
	Pe0003_CbusWriteWord(CBUSPORT, ANAOUT_COARSE_GAIN, ANAOUT_COARSE_GAIN_VAL);							//0dB gain
	mprintf("ANAOUT_COARSE_GAIN_REG 0x%x\n", ANAOUT_COARSE_GAIN_VAL);

	Pe0003_CbusWriteWord(CBUSPORT, REG_DONE_SELECT, REG_DONE_MODE);					//Set interrupt on Mode Reg Done
	Pe0003_CbusWriteWord(CBUSPORT, MODE_REG, 0);									//Idle mode to configure
	//FIXME DANIEL SET INTERRUPT

	mprintf("MODE_REG 0x%x\n", 0x121);
	Pe0003_CbusWriteWord(CBUSPORT, MODE_REG, 0x121);//(MODE_AUDIO_SRC_CBUS << 8) | (MODE_AUDIO_DST_ANA << 4) | MODE_HALF_TRANSC);



	//Get some data into a temporal buffer
	res = PR7261_FileReadSamples(file_id, (uint16_t *)bufferOut, OUTBUFFER_SIZE , &nDataRead, CFG_IN_FILE);

	//Normal process
	while(nDataRead != 0)
	{

		while(nDataRead != 0)
		{
			//Check fifo level
			level = Pe0003_CbusReadByte(CBUSPORT, FIFO_IN_LEVEL);

			if (level < MAX_FIFO_SIZE)
			{
				if ((MAX_FIFO_SIZE - level) > nDataRead)
				{
					//Stream all the data from the temporal buffer into the CBus
					Pe0003_CbusWriteWstream(CBUSPORT,  FIFO_IN_WORD, &bufferOut[j], nDataRead);//&bufferOut[j], nDataRead);		//Stream data into the buffer
					count += nDataRead;
					j = 0;
					nDataRead = 0;
				}
				/*
				else
				{
					uint8_t spaceLeft = MAX_FIFO_SIZE - level;
					Pe0003_CbusWriteWstream(CBUSPORT,  FIFO_IN_WORD, &bufferOut[j], spaceLeft);		//Stream part of the data into the buffer
					j = spaceLeft;
					count += spaceLeft;
					nDataRead -= spaceLeft;
				}
				*/
			}

			//Check status register for underflows
			nstatus = Pe0003_CbusReadWord(CBUSPORT, STATUS);

			if (nstatus & IRQ_UFLOW)			//Check for underflow
			{
				mprintf("ERROR - Data underflow\n");
			}

			if (DEBUG_DISP)
			{
				if (count > dispCount)
				{
					dispCount += 255;
					mprintf("s%d \n", count);
				}
			}
		}

		//Read more data
		res = PR7261_FileReadSamples(file_id, (uint16_t *)bufferOut, OUTBUFFER_SIZE , &nDataRead, CFG_IN_FILE);
		if (res != GUI_FILE_RESULT_OK)
		{
			mprintf("ERROR - Reading data from file\n");
		}
	}

	//Close file
	res = PR7261_FileClose(file_id, CFG_IN_FILE);

	mprintf("Unpacked CVSD decoding finished\n");

	return TRUE;
}



uint8_t Unpacked_CVSD_Decoder_Op_Loop(uint32_t nSamples)
{
	uint8_t res;
	uint8_t level = 0;
	uint8_t file_id = 0;
	uint32_t nDataRead;
	uint16_t nstatus = 0;
	uint32_t count = 0;
	uint32_t dispCount = 0;
	uint32_t i = 0;
	uint16_t tmpBufferOut[OUTBUFFER_SIZE];
	uint32_t maxSamples = nSamples;
	uint16_t valReg = 0;


	if (maxSamples > OUTSTATICBUFFER_SIZE)
		maxSamples = OUTSTATICBUFFER_SIZE;


	//Open file
	char filename[] = "dummy.dat";
	res = PR7261_FileDialogOpen(&file_id, filename, FILE_READ, CFG_IN_FILE);
	if (res != GUI_FILE_RESULT_OK)
	{
		mprintf("ERROR - Opening file for writing\n");
	}


	//Main Configuration
	Pe0003_CbusWriteWord(CBUSPORT, MODE_REG, 0);				//Idle mode to configure
	Pe0003_CbusWriteWord(CBUSPORT, FIFO_CONTROL, 0x8080);		//Flush FIFO

	Pe0003_TimerDelayUs(10000);

	Pe0003_CbusWriteWord(CBUSPORT, INPUT_TYPE, INPUT_TYPE_UNPACKED_CVSD | RATE_32KHZ);			//Unpacked CVSD 32Kbps
	valReg = INPUT_TYPE_UNPACKED_CVSD | RATE_32KHZ;
	mprintf("INPUT_REG 0x%x\n", valReg);
	Pe0003_CbusWriteWord(CBUSPORT, OUTPUT_TYPE, OUTPUT_TYPE_16BIT_SIGNED_PCM | RATE_32KHZ);	//PCM 16 bit signed linear
	valReg = OUTPUT_TYPE_16BIT_SIGNED_PCM | RATE_32KHZ;
	mprintf("OUTPUT_REG 0x%x\n", valReg);

	Pe0003_CbusWriteWord(CBUSPORT, ANAOUT_CONF, ANAOUT_DAC_PWR | ANAOUT_DRVPWR);	//0x802 power up ANAOUT driver
	valReg = ANAOUT_DAC_PWR | ANAOUT_DRVPWR;
	mprintf("ANAOUT_CONF_REG 0x%x\n", valReg);
	Pe0003_CbusWriteWord(CBUSPORT, ANAOUT_COARSE_GAIN, 0);							//0dB gain
	mprintf("ANAOUT_COARSE_GAIN_REG 0x%x\n", 0);

	Pe0003_CbusWriteWord(CBUSPORT, REG_DONE_SELECT, REG_DONE_MODE);					//Set interrupt on Mode Reg Done
	Pe0003_CbusWriteWord(CBUSPORT, MODE_REG, 0);				//Idle mode to configure
	//FIXME DANIEL SET INTERRUPT

	mprintf("MODE_REG 0x%x\n", 0x121);
	Pe0003_CbusWriteWord(CBUSPORT, MODE_REG, 0x121);//(MODE_AUDIO_SRC_CBUS << 8) | (MODE_AUDIO_DST_ANA << 4) | MODE_HALF_TRANSC);



	//Store data into the static buffer
	//Get some data
	res = PR7261_FileReadSamples(file_id, (uint16_t *)tmpBufferOut, OUTBUFFER_SIZE , &nDataRead, CFG_IN_FILE);

	i = 0;
	while(nDataRead != 0)
	{
		//Copy data into the static buffer from atemporal buffer
		memcpy(&sBufferOut[i], tmpBufferOut, nDataRead * sizeof(uint16_t));
		i += nDataRead;

		res = PR7261_FileReadSamples(file_id, (uint16_t *)tmpBufferOut, OUTBUFFER_SIZE , &nDataRead, CFG_IN_FILE);

		if(i + nDataRead > maxSamples)
			break;
	}

	//Close file
	res = PR7261_FileClose(file_id, CFG_IN_FILE);


	//Normal process. Infinite loop
	i = 0;
	while(1)
	{
		//Check fifo level
		level = Pe0003_CbusReadByte(CBUSPORT, FIFO_IN_LEVEL);

		if (level < MAX_FIFO_SIZE)
		{
			if ((MAX_FIFO_SIZE - level) > OUTBUFFER_SIZE)
			{
				//Copy data from static buffer into temporal buffer.
				memcpy(tmpBufferOut, &sBufferOut[i], OUTBUFFER_SIZE * sizeof(uint16_t));
				Pe0003_CbusWriteWstream(CBUSPORT,  FIFO_IN_WORD, tmpBufferOut, OUTBUFFER_SIZE);		//Stream data into the buffer
				i += OUTBUFFER_SIZE;
				count += OUTBUFFER_SIZE;

				//Reached the maximu number of samples?
				if ((i + OUTBUFFER_SIZE) > maxSamples)
					i = 0;
			}

			//Check status for underflows
			nstatus = Pe0003_CbusReadWord(CBUSPORT, STATUS);

			if (nstatus & IRQ_UFLOW)			//Check for underflow
			{
				mprintf("ERROR - Data underflow\n");
			}

			if (DEBUG_DISP)
			{
				if (count > dispCount)
				{
					dispCount += 255;
					mprintf("s%d \n", count);
				}
			}
		}
	}

	return TRUE;
}



uint8_t Unpacked_CVSD_Decoder_Op_Loop2(uint32_t nSamples)
{
	uint8_t res;
	uint8_t level = 0;
	uint8_t file_id = 0;
	uint32_t nDataRead;
	uint16_t nstatus = 0;
	uint32_t count = 0;
	uint32_t dispCount = 0;
	uint32_t i = 0;
	uint32_t maxSamples = nSamples;
	uint16_t tmpBufferOut[OUTBUFFER_SIZE];
	uint32_t dataLeft = 0;
	uint16_t valReg = 0;

	//Set maximum number of samples possible
	if (maxSamples > OUTSTATICBUFFER_SIZE)
		maxSamples = OUTSTATICBUFFER_SIZE;


	//Open the file for reading
	char filename[] = "dummy.dat";
	res = PR7261_FileDialogOpen(&file_id, filename, FILE_READ, CFG_IN_FILE);
	if (res != GUI_FILE_RESULT_OK)
	{
		mprintf("ERROR - Opening file for writing\n");
		return FALSE;
	}


	//Main Configuration
	Pe0003_CbusWriteWord(CBUSPORT, MODE_REG, 0);				//Idle mode to configure
	Pe0003_CbusWriteWord(CBUSPORT, FIFO_CONTROL, 0x8080);		//Flush FIFO

	Pe0003_TimerDelayUs(10000);

	Pe0003_CbusWriteWord(CBUSPORT, INPUT_TYPE, INPUT_TYPE_UNPACKED_CVSD | RATE_32KHZ);			//Unpacked CVSD 32Kbps
	valReg = INPUT_TYPE_UNPACKED_CVSD | RATE_32KHZ;
	mprintf("INPUT_REG 0x%x\n", 0x121);
	Pe0003_CbusWriteWord(CBUSPORT, OUTPUT_TYPE, OUTPUT_TYPE_16BIT_SIGNED_PCM | RATE_32KHZ);		//PCM 16 bit signed linear
	valReg = OUTPUT_TYPE_16BIT_SIGNED_PCM | RATE_32KHZ;
	mprintf("OUTPUT_REG 0x%x\n", valReg);

	Pe0003_CbusWriteWord(CBUSPORT, ANAOUT_CONF, ANAOUT_DAC_PWR | ANAOUT_DRVPWR);	//0x802 power up ANAOUT driver
	valReg = ANAOUT_DAC_PWR | ANAOUT_DRVPWR;
	mprintf("ANAOUT_CONF_REG 0x%x\n", valReg);
	Pe0003_CbusWriteWord(CBUSPORT, ANAOUT_COARSE_GAIN, 0);							//0dB gain
	mprintf("ANAOUT_COARSE_GAIN_REG 0x%x\n", 0);

	Pe0003_CbusWriteWord(CBUSPORT, REG_DONE_SELECT, REG_DONE_MODE);					//Set interrupt on Mode Reg Done
	Pe0003_CbusWriteWord(CBUSPORT, MODE_REG, 0);				//Idle mode to configure
	//FIXME DANIEL SET INTERRUPT

	mprintf("MODE_REG 0x%x\n", 0x121);
	Pe0003_CbusWriteWord(CBUSPORT, MODE_REG, 0x121);//(MODE_AUDIO_SRC_CBUS << 8) | (MODE_AUDIO_DST_ANA << 4) | MODE_HALF_TRANSC);



	//Store data into the static buffer
	//Get some data
	res = PR7261_FileReadSamples(file_id, (uint16_t *)tmpBufferOut, OUTBUFFER_SIZE , &nDataRead, CFG_IN_FILE);

	i = 0;
	while(nDataRead != 0)
	{
		memcpy(&sBufferOut[i], tmpBufferOut, nDataRead * sizeof(uint16_t));
		i += nDataRead;

		res = PR7261_FileReadSamples(file_id, (uint16_t *)tmpBufferOut, OUTBUFFER_SIZE , &nDataRead, CFG_IN_FILE);

		if(i + nDataRead > maxSamples)
			break;
	}

	//Data Left to reach nSamples
	if (nDataRead != 0)
	{
		if (i != maxSamples)
		{
			dataLeft = maxSamples - i;
			memcpy(&sBufferOut[i], tmpBufferOut, dataLeft * sizeof(uint16_t));
			i += dataLeft;
		}
	}

	//Close file
	res = PR7261_FileClose(file_id, CFG_IN_FILE);


	//Normal process. Infinite loop
	i = 0;
	while(1)
	{
		//Check fifo level
		level = Pe0003_CbusReadByte(CBUSPORT, FIFO_IN_LEVEL);

		if (level < MAX_FIFO_SIZE)
		{
			//Write one sample into the fifo
			Pe0003_CbusWriteWord(CBUSPORT,  FIFO_IN_WORD, sBufferOut[i++]);
			count++;

			if (i == maxSamples)
					i = 0;
		}

		//Check status register for underflows
		nstatus = Pe0003_CbusReadWord(CBUSPORT, STATUS);

		if (nstatus & IRQ_UFLOW)			//Check for underflow
		{
			mprintf("ERROR - Data underflow\n");
		}

		if (DEBUG_DISP)
		{
			if (count > dispCount)
			{
				dispCount += 255;
				mprintf("s%d \n", count);
			}
		}
	}


	return TRUE;
}




//FIXME DANIEL CHANGE TO AFIX SIZE OF THE STATIC BUFFER
//FIXME REMEMBER NOTE In case the number of samples is bigger than staticbuffer sizes,
//the samples are limited to these sizes
uint8_t G279A_CVSD_Transcoder(uint32_t nSamples)
{
	uint8_t res;
	uint32_t i = 0;
	uint8_t level = 0;
	uint16_t val = 0;
	uint8_t file_id = 0;
	uint32_t nDataWritten = 0;
	uint32_t nDataRead = 0;
	uint32_t dispCount = 0;
	uint16_t valReg = 0;

	uint32_t dataLeft = 0;
	uint16_t nstatus = 0;

	uint16_t tmpBufferIn[INBUFFER_SIZE];
	uint16_t tmpBufferOut[OUTBUFFER_SIZE];
	uint32_t j = 0;

	uint32_t countIn, countOut;

	uint8_t enableEncoder = TRUE, enableDecoder = TRUE;

	uint32_t maxInSamples = 0;
	uint32_t maxOutSamples = 0;

	//Set the maximum number of samples possible to process. Depends on the size of the static buffers
	if (nSamples > INSTATICBUFFER_SIZE)
		maxInSamples = INSTATICBUFFER_SIZE;
	else
		maxInSamples = nSamples;

	if (nSamples > OUTSTATICBUFFER_SIZE)
		maxOutSamples = OUTSTATICBUFFER_SIZE;
	else
		maxOutSamples = nSamples;
//--------------File------------------------------
	//Load samples into a static buffer
	char filename[] = "dummy.dat";

	res = PR7261_FileDialogOpen(&file_id, filename, FILE_READ, CFG_IN_FILE);
	if (res != GUI_FILE_RESULT_OK)
	{
		mprintf("ERROR - Opening file for writing\n");
	}
//---------------------------------loading file into buffer ----------------------------sBufferOut
	res = PR7261_FileReadSamples(file_id, (uint16_t *)tmpBufferOut, OUTBUFFER_SIZE , &nDataRead, CFG_IN_FILE);

	i = 0;
	while(nDataRead != 0)
	{
		memcpy(&sBufferOut[i], tmpBufferOut, nDataRead * sizeof(uint16_t));
		i += nDataRead;

		res = PR7261_FileReadSamples(file_id, (uint16_t *)tmpBufferOut, OUTBUFFER_SIZE , &nDataRead, CFG_IN_FILE);

		if(i + nDataRead > maxOutSamples)
			break;
	}

	if (nDataRead != 0)
	{
		if (i <= maxOutSamples)
		{
			dataLeft = maxOutSamples - i;
			memcpy(&sBufferOut[i], tmpBufferOut, dataLeft * sizeof(uint16_t));
			i += dataLeft;
		}
	}

	res = PR7261_FileClose(file_id, CFG_IN_FILE);
//----------------------------------------------------------Configuration------------------------------------------------
	//Main Configuration
	Pe0003_CbusWriteWord(CBUSPORT, MODE_REG, 0);						//Idle mode to configure
	Pe0003_CbusWriteWord(CBUSPORT, ANAIN_CONF, ANAIN_CONF_VAL);	//Power up AnlogIn
	mprintf("ANAIN_CONF_REG 0x%x\n", ANAIN_CONF_VAL);
	Pe0003_CbusWriteWord(CBUSPORT, ANAIN_COARSE_GAIN, ANAIN_COARSE_GAIN_VAL);				//0dB gain
	mprintf("ANAIN_COARSE_GAIN_REG 0x%x\n", ANAIN_COARSE_GAIN_VAL);

	Pe0003_CbusWriteWord(CBUSPORT, FIFO_CONTROL, 0x8080);		//Flush FIFO

	Pe0003_TimerDelayUs(10000);

	Pe0003_CbusWriteWord(CBUSPORT, INPUT_TYPE, INPUT_TYPE_UNPACKED_G279A);					//G279A
	mprintf("INPUT_REG 0x%x\n", INPUT_TYPE_UNPACKED_G279A);
	Pe0003_CbusWriteWord(CBUSPORT, OUTPUT_TYPE, OUTPUT_TYPE_UNPACKED_CVSD | RATE_32KHZ);		//Unpacked CVSD 32Kbps
	valReg = OUTPUT_TYPE_UNPACKED_CVSD | RATE_32KHZ;
	mprintf("OUTPUT_REG 0x%x\n", valReg);

	Pe0003_CbusWriteWord(CBUSPORT, ANAOUT_CONF, ANAOUT_CONF_VAL);	//0x802 power up ANAOUT driver
	mprintf("ANAOUT_CONF_REG 0x%x\n", ANAOUT_CONF_VAL);
	Pe0003_CbusWriteWord(CBUSPORT, ANAOUT_COARSE_GAIN, ANAOUT_COARSE_GAIN_VAL);							//0dB gain
	mprintf("ANAOUT_COARSE_GAIN_REG 0x%x\n", ANAOUT_COARSE_GAIN_VAL);

	mprintf("MODE_REG 0x%x\n", 0x111);
	Pe0003_CbusWriteWord(CBUSPORT, MODE_REG, 0x111);//(MODE_AUDIO_SRC_CBUS << 8) | (MODE_AUDIO_DST_CBUS << 4) | MODE_HALF_TRANSC);


	Pe0003_TimerDelayUs(10000);

//---------------------------------------------------------------Main Process----------------------------------------------
	//Main process
	countIn = 0;
	countOut = 0;
	while(enableEncoder || enableDecoder)
	{
		//Encoder part
		if (enableEncoder)
		{
			level = Pe0003_CbusReadByte(CBUSPORT, FIFO_OUT_LEVEL);

			if (level > 0)
			{
				val = Pe0003_CbusReadWord(CBUSPORT, FIFO_OUT_WORD);

				sBufferIn[j++] = val;
				countIn++;

				if (DEBUG_DISP)
				{
					if ((countIn % 255) == 0)
						mprintf("s%d In\n", countIn);
				}

				if (countIn == maxInSamples)
					enableEncoder = FALSE;
			}

			/*
			if (level == WARNING_FIFO_LEVEL)
			{
				mprintf("ERROR - Buffer overflow\n");
			}
			*/

			//Check status for underflows
			nstatus = Pe0003_CbusReadWord(CBUSPORT, STATUS);
			if (nstatus & IRQ_OFLOW)			//Check for overflows
			{
				mprintf("ERROR - Buffer overflow\n");
			}

			//Case there is not more samples to process by the decoder
			//Samples must be provided to the encoder While the decoder is still running
			if (!enableDecoder)
			{
				level = Pe0003_CbusReadByte(CBUSPORT, FIFO_IN_LEVEL);

				if (level < MAX_FIFO_SIZE)
					Pe0003_CbusWriteWord(CBUSPORT,  FIFO_IN_WORD, 0);
			}
		}

		//Decoder part
		if (enableDecoder)
		{


			level = Pe0003_CbusReadByte(CBUSPORT, FIFO_IN_LEVEL);



			if (level < MAX_FIFO_SIZE)
			{

				Pe0003_CbusWriteWord(CBUSPORT,  FIFO_IN_WORD, sBufferOut[i++]);
				countOut++;

				if (i == maxOutSamples)
					break;
			}



			nstatus = Pe0003_CbusReadWord(CBUSPORT, STATUS);

			if (nstatus & IRQ_UFLOW)			//Check for underflow
			{
				mprintf("ERROR - Data underflow\n");
			}

			if (countOut == maxOutSamples)
				enableDecoder = FALSE;

			if (DEBUG_DISP)
			{
				if (countOut > dispCount)
				{
					dispCount += 255;
					mprintf("s%d Out\n", countOut);
				}
			}

			//This is in case there is not more samples to process by the encoder and still there are smples from the decoder
			//Must continue getting samples while the Decoder is still running
			if (!enableEncoder)
			{
				level = Pe0003_CbusReadByte(CBUSPORT, FIFO_OUT_LEVEL);
				if (level > 0)
					val = Pe0003_CbusReadWord(CBUSPORT, FIFO_OUT_WORD);
			}
		}
	}

//----------------------------------------------------------------Storing samples into a file from ------------------------ sBuffeRIn
	//Store samples from the static buffer
	char filename2[] = "dummy.dat";
	res = PR7261_FileDialogOpen(&file_id, filename2, FILE_WRITE, CFG_OUT_FILE);
	if (res != GUI_FILE_RESULT_OK)
	{
		mprintf("ERROR - Opening file for writing\n");
	}

	j = 0;
	while(j < maxInSamples)
	{
		memcpy(tmpBufferIn, &sBufferIn[j], INBUFFER_SIZE * sizeof(uint16_t));
		j += INBUFFER_SIZE;

		res = PR7261_FileWriteSamples(file_id, (uint16_t *) &tmpBufferIn[0], INBUFFER_SIZE, &nDataWritten, CFG_OUT_FILE);
		if (res != GUI_FILE_RESULT_OK)
		{
			mprintf("ERROR - Writing data into a file\n");
			return FALSE;
		}

		if ((j + INBUFFER_SIZE) > maxInSamples)
			break;
	}

	//Store last samples
	if (j != maxInSamples)
	{
		uint32_t samplesLeft = maxInSamples - j;
		memcpy(tmpBufferIn, &sBufferIn[j], samplesLeft * sizeof(uint16_t));
		j += samplesLeft;

		res = PR7261_FileWriteSamples(file_id, (uint16_t *) &tmpBufferIn[0], samplesLeft, &nDataWritten, CFG_OUT_FILE);
		if (res != GUI_FILE_RESULT_OK)
		{
			mprintf("ERROR - Writing data into a file\n");
			return FALSE;
		}
	}

	//Close File
	res = PR7261_FileClose(file_id, CFG_OUT_FILE);

	mprintf("Transcoder operation finished\n");

	return TRUE;
}



uint8_t PCM_PCM_Transcoder(uint32_t nSamples)
{
	uint8_t res;
	uint32_t i = 0;
	uint8_t level = 0;
	uint16_t val = 0;
	uint8_t file_id = 0;
	uint32_t nDataWritten = 0;
	uint32_t nDataRead = 0;
	uint32_t dispCount = 0;
	uint16_t valReg = 0;

	uint32_t dataLeft = 0;
	uint16_t nstatus = 0;

	uint16_t sBufferOut[OUTSTATICBUFFER_SIZE];
	uint16_t sBufferIn[INSTATICBUFFER_SIZE];
	uint16_t tmpBufferIn[INBUFFER_SIZE];
	uint16_t tmpBufferOut[OUTBUFFER_SIZE];
	uint32_t j = 0;

	uint32_t countIn, countOut;

	uint8_t enableEncoder = TRUE, enableDecoder = TRUE;

	uint32_t maxInSamples = 0;
	uint32_t maxOutSamples = 0;

	//Set the maximum number of samples posibble to process. Despends on the size of the static buffers
	if (nSamples > INSTATICBUFFER_SIZE)
		maxInSamples = INSTATICBUFFER_SIZE;
	else
		maxInSamples = nSamples;

	if (nSamples > OUTSTATICBUFFER_SIZE)
		maxOutSamples = OUTSTATICBUFFER_SIZE;
	else
		maxOutSamples = nSamples;

	//Store samples in output static buffer
	char filename[] = "dummy.dat";
	res = PR7261_FileDialogOpen(&file_id, filename, FILE_READ, CFG_IN_FILE);
	if (res != GUI_FILE_RESULT_OK)
	{
		mprintf("ERROR - Opening file for writing\n");
	}

	res = PR7261_FileReadSamples(file_id, (uint16_t *)tmpBufferOut, OUTBUFFER_SIZE , &nDataRead, CFG_IN_FILE);

	i = 0;
	while(nDataRead != 0)
	{
		memcpy(&sBufferOut[i], tmpBufferOut, nDataRead * sizeof(uint16_t));
		i += nDataRead;

		res = PR7261_FileReadSamples(file_id, (uint16_t *)tmpBufferOut, OUTBUFFER_SIZE , &nDataRead, CFG_IN_FILE);

		if(i + nDataRead > maxOutSamples)
			break;
	}

	if (nDataRead != 0)
	{
		if (i <= maxOutSamples)
		{
			dataLeft = maxOutSamples - i;
			memcpy(&sBufferOut[i], tmpBufferOut, dataLeft * sizeof(uint16_t));
			i += dataLeft;
		}
	}

	res = PR7261_FileClose(file_id, CFG_IN_FILE);

	//Main Configuration
	Pe0003_CbusWriteWord(CBUSPORT, MODE_REG, 0);						//Idle mode to configure
	Pe0003_CbusWriteWord(CBUSPORT, ANAIN_CONF, ADC_PWR | ANAIN_PWR);	//Power up AnlogIn
	valReg = ADC_PWR | ANAIN_PWR;
	mprintf("ANAIN_CONF_REG 0x%x\n", valReg);
	Pe0003_CbusWriteWord(CBUSPORT, ANAIN_COARSE_GAIN, 0);				//0dB gain
	mprintf("ANAIN_COARSE_GAIN_REG 0x%x\n", 0);

	Pe0003_CbusWriteWord(CBUSPORT, FIFO_CONTROL, 0x8080);		//Flush FIFO

	Pe0003_TimerDelayUs(10000);

	Pe0003_CbusWriteWord(CBUSPORT, INPUT_TYPE, INPUT_TYPE_PACKED_G279A);					//G279A
	mprintf("INPUT_REG 0x%x\n", INPUT_TYPE_PACKED_G279A);
	Pe0003_CbusWriteWord(CBUSPORT, OUTPUT_TYPE, OUTPUT_TYPE_PACKED_CVSD | RATE_32KHZ);		//Unpacked CVSD 32Kbps
	valReg = OUTPUT_TYPE_PACKED_CVSD | RATE_32KHZ;
	mprintf("OUTPUT_REG 0x%x\n", valReg);

	Pe0003_CbusWriteWord(CBUSPORT, ANAOUT_CONF, ANAOUT_DAC_PWR | ANAOUT_DRVPWR);	//0x802 power up ANAOUT driver
	valReg = ANAOUT_DAC_PWR | ANAOUT_DRVPWR;
	mprintf("ANAOUT_CONF_REG 0x%x\n", valReg);
	Pe0003_CbusWriteWord(CBUSPORT, ANAOUT_COARSE_GAIN, 0);							//0dB gain
	mprintf("ANAOUT_COARSE_GAIN_REG 0x%x\n", 0);

	mprintf("MODE_REG 0x%x\n", 0x111);
	Pe0003_CbusWriteWord(CBUSPORT, MODE_REG, 0x111);//(MODE_AUDIO_SRC_CBUS << 8) | (MODE_AUDIO_DST_CBUS << 4) | MODE_HALF_TRANSC);


	Pe0003_TimerDelayUs(10000);


	//Main process
	countIn = 0;
	countOut = 0;
	while(enableEncoder || enableDecoder)
	{
		//Encoder part
		if (enableEncoder)
		{
			level = Pe0003_CbusReadByte(CBUSPORT, FIFO_OUT_LEVEL);

			if (level > 0)
			{
				val = Pe0003_CbusReadWord(CBUSPORT, FIFO_OUT_WORD);

				sBufferIn[j++] = val;
				countIn++;

				if (DEBUG_DISP)
				{
					if ((countIn % 255) == 0)
						mprintf("s%d In\n", countIn);
				}

				if (countIn == maxInSamples)
					enableEncoder = FALSE;
			}

			/*
			if (level == WARNING_FIFO_LEVEL)
			{
				mprintf("ERROR - Buffer overflow\n");
			}
			*/

			//Check status for underflows
			nstatus = Pe0003_CbusReadWord(CBUSPORT, STATUS);

			if (nstatus & IRQ_OFLOW)			//Check for overflows
			{
				mprintf("ERROR - Buffer overflow\n");
			}

			//Case there is not more samples to process by the decoder
			//Samples must be provided to the encoder While the decoder is still running
			if (!enableDecoder)
			{
				level = Pe0003_CbusReadByte(CBUSPORT, FIFO_IN_LEVEL);

				if (level < MAX_FIFO_SIZE)
					Pe0003_CbusWriteWord(CBUSPORT,  FIFO_IN_WORD, 0);
			}
		}

		//Decoder part
		if (enableDecoder)
		{
			level = Pe0003_CbusReadByte(CBUSPORT, FIFO_IN_LEVEL);


			if (level < MAX_FIFO_SIZE)
			{
				Pe0003_CbusWriteWord(CBUSPORT,  FIFO_IN_WORD, sBufferOut[i++]);
				countOut++;

				if (i == maxOutSamples)
					break;
			}


			nstatus = Pe0003_CbusReadWord(CBUSPORT, STATUS);

			if (nstatus & IRQ_UFLOW)			//Check for underflow
			{
				mprintf("ERROR - Data underflow\n");
			}

			if (countOut == maxOutSamples)
				enableDecoder = FALSE;

			if (DEBUG_DISP)
			{
				if (countOut > dispCount)
				{
					dispCount += 255;
					mprintf("s%d \n", countOut);
				}
			}

			//This is in case there is not more samples to process by the encoder and still there are smples from the decoder
			//Must continue getting samples while the Decoder is still running
			if (!enableEncoder)
			{
				level = Pe0003_CbusReadByte(CBUSPORT, FIFO_OUT_LEVEL);
				if (level > 0)
					val = Pe0003_CbusReadWord(CBUSPORT, FIFO_OUT_WORD);
			}
		}
	}


	//Store samples from the static buffer
	char filename2[] = "dummy.dat";
	res = PR7261_FileDialogOpen(&file_id, filename2, FILE_WRITE, CFG_OUT_FILE);
	if (res != GUI_FILE_RESULT_OK)
	{
		mprintf("ERROR - Opening file for writing\n");
	}

	j = 0;
	while(j < maxInSamples)
	{
		memcpy(tmpBufferIn, &sBufferIn[j], INBUFFER_SIZE * sizeof(uint16_t));
		j += INBUFFER_SIZE;

		res = PR7261_FileWriteSamples(file_id, (uint16_t *) &tmpBufferIn[0], INBUFFER_SIZE, &nDataWritten, CFG_OUT_FILE);
		if (res != GUI_FILE_RESULT_OK)
		{
			mprintf("ERROR - Writing data into a file\n");
			return FALSE;
		}

		if ((j + INBUFFER_SIZE) > maxInSamples)
			break;
	}

	//Store last samples
	if (j != maxInSamples)
	{
		uint32_t samplesLeft = maxInSamples - j;
		memcpy(tmpBufferIn, &sBufferIn[j], samplesLeft * sizeof(uint16_t));
		j += samplesLeft;

		res = PR7261_FileWriteSamples(file_id, (uint16_t *) &tmpBufferIn[0], samplesLeft, &nDataWritten, CFG_OUT_FILE);
		if (res != GUI_FILE_RESULT_OK)
		{
			mprintf("ERROR - Writing data into a file\n");
			return FALSE;
		}
	}

	//Close File
	res = PR7261_FileClose(file_id, CFG_OUT_FILE);

	mprintf("Transcoder operation finished\n");

	return TRUE;
}



//-------------------------------------------------------------------
//
//							CUSTOM OPERATIONS
//
//-------------------------------------------------------------------



/**
 * @brief Open a file for writting, using a save dialog box
 * @param file_id - Id of the file
 * @return	TRUE if success, FALSE if failed
 */
uint8_t RunFileOuputRequired(uint8_t *file_id)
{
	uint8_t res = TRUE;

	char filename[] = "dummy.dat";

	res = PR7261_FileDialogOpen(file_id, filename, FILE_WRITE, CFG_OUT_FILE);
	if (res != GUI_FILE_RESULT_OK)
	{
		mprintf("ERROR - Opening file for writing\n");
		return FALSE;
	}


	return TRUE;
}


/**
 * @brief Open a file for reading and stores all the data into a static buffer
 * @param sBufferOut - Static buffer
 * @param samples - Number of samples to store
 * @return TRUE if success and FALSE if fails
 */
uint8_t RunFileInputRequired_Loop(uint16_t *sBufferOut, uint32_t samples)
{
	uint8_t res = TRUE;
	uint32_t i = 0;
	uint16_t tmpBufferOut[OUTBUFFER_SIZE];
	uint32_t maxSamples = samples;
	uint8_t file_id = 0;
	uint32_t nDataRead = 0;

	char filename[] = "dummy.dat";
	res = PR7261_FileDialogOpen(&file_id, filename, FILE_READ, CFG_IN_FILE);
	if (res != GUI_FILE_RESULT_OK)
	{
		mprintf("ERROR - Opening file for reading\n");
		return FALSE;
	}

	//First get some data from file
	res = PR7261_FileReadSamples(file_id, (uint16_t *)tmpBufferOut, OUTBUFFER_SIZE , &nDataRead, CFG_IN_FILE);
	if (res != GUI_FILE_RESULT_OK)
	{
		mprintf("ERROR - Reading file\n");
		return FALSE;
	}

	i = 0;
	while(nDataRead != 0)
	{
		//Copy data from a temporal buffer into final staticBuffer
		memcpy(&sBufferOut[i], tmpBufferOut, nDataRead * sizeof(uint16_t));
		i += nDataRead;

		//Read more samples
		res = PR7261_FileReadSamples(file_id, (uint16_t *)tmpBufferOut, OUTBUFFER_SIZE , &nDataRead, CFG_IN_FILE);
		if (res != GUI_FILE_RESULT_OK)
		{
			mprintf("ERROR - Reading file\n");
			return FALSE;
		}


		if(i + nDataRead > maxSamples)
			break;
	}

	//Store data left
	if (nDataRead != 0)
	{
		if (i <maxSamples)
		{
			uint32_t dataLeft = maxSamples - i;
			memcpy(&sBufferOut[i], tmpBufferOut, dataLeft * sizeof(uint16_t));
		}
	}

	//Close file
	res = PR7261_FileClose(file_id, CFG_IN_FILE);

	return TRUE;
}


/**
 * @brief Open a file for reading, using a save dialog box
 * @param file_id - Id of the file
 * @return	TRUE if success, FALSE if failed
 */
uint8_t RunFileInputRequired(uint8_t *file_id)
{
	uint8_t res = TRUE;
	char filename[] = "dummy.dat";

	res = PR7261_FileDialogOpen(file_id, filename, FILE_READ, CFG_IN_FILE);
	if (res != GUI_FILE_RESULT_OK)
	{
		mprintf("ERROR - Opening file for writing\n");
		return FALSE;
	}


	return TRUE;
}


/**
 * @brief Run the main loop operation to get samples from some Analog input into
 * 			a  file. Part of the Encoding process
 * @param file_id - Id of the file used
 * @param nSamples - Number of samples to encode
 * @return TRUE if success, FALSE if failed
 */
uint8_t RunCBusInAnaOutOp(uint8_t *file_id, uint32_t nSamples)
{
	uint8_t res = FALSE;
	uint32_t nDataWritten;
	uint32_t i = 0;
	uint8_t level = 0;
	uint16_t val = 0;
	uint16_t bufferIn[INBUFFER_SIZE];
	uint32_t j = 0;
	uint16_t nstatus = 0;

	while(i < nSamples)
	{
		//Read fifo level
		level = Pe0003_CbusReadByte(CBUSPORT, FIFO_OUT_LEVEL);

		if (level > 0)
		{
			//Read sample from fifo out
			val = Pe0003_CbusReadWord(CBUSPORT, FIFO_OUT_WORD);

			bufferIn[j++] = val;
			i++;

			//Store data in blocks of INBUFFER_SIZE
			if (j == INBUFFER_SIZE)
			{
				j = 0;
				res = PR7261_FileWriteSamples(*file_id, (uint16_t *) &bufferIn[0], INBUFFER_SIZE, &nDataWritten, CFG_OUT_FILE);
				if (res != GUI_FILE_RESULT_OK)
				{
					mprintf("ERROR - Writing data into a file\n");
					return FALSE;
				}

			}

			if (DEBUG_DISP)
			{
				if ((i % 1000) == 0)
					mprintf("s%d \n", i);
			}
		}

		/*
		if (level == WARNING_FIFO_LEVEL)
		{
			mprintf("ERROR - Buffer overflow\n");
		}
		*/

		//Check status for underflows
		nstatus = Pe0003_CbusReadWord(CBUSPORT, STATUS);

		if (nstatus & IRQ_OFLOW)			//Check for overflows
		{
			mprintf("ERROR - Buffer overflow\n");
		}
	}


	//Store the left data
	if (j > 0)
	{
		res = PR7261_FileWriteSamples(*file_id, (uint16_t *) &bufferIn[0], j, &nDataWritten, CFG_OUT_FILE);
		if (res != GUI_FILE_RESULT_OK)
		{
			mprintf("ERROR - Writing data into a file\n");
			return FALSE;
		}
	}

	return TRUE;
}


/**
 * @brief Run the main loop operation to get samples from a file into sime Analog output
 * 		 	Part of the Decoding process
 * @param file_id - Id of the file used
 * @param nSamples - Number of samples to decode
 * @return TRUE if success, FALSE if failed
 */
uint8_t RunCBusOutAnaInOp(uint8_t *file_id, uint32_t nSamples)
{
	uint8_t res;
	uint8_t level = 0;

	uint32_t nDataRead;
	uint16_t nstatus = 0;
	uint32_t count = 0;
	uint32_t dispCount = 0;

	uint16_t bufferOut[OUTBUFFER_SIZE];
	uint32_t j = 0;


	//Firstly read some data
	res = PR7261_FileReadSamples(*file_id, (uint16_t *) bufferOut, OUTBUFFER_SIZE , &nDataRead, CFG_IN_FILE);

	//Normal process
	while(nDataRead != 0)
	{

		while(nDataRead != 0)
		{
			//Get level fifo in
			level = Pe0003_CbusReadByte(CBUSPORT, FIFO_IN_LEVEL);

			if (level < MAX_FIFO_SIZE)
			{
				//Stream data into Cbus
				if ((MAX_FIFO_SIZE - level) > nDataRead)
				{
					Pe0003_CbusWriteWstream(CBUSPORT,  FIFO_IN_WORD, &bufferOut[j], nDataRead);//&bufferOut[j], nDataRead);		//Stream data into the buffer
					count += nDataRead;
					j = 0;
					nDataRead = 0;
				}
				/*
				else
				{
					uint8_t spaceLeft = MAX_FIFO_SIZE - level;
					Pe0003_CbusWriteWstream(CBUSPORT,  FIFO_IN_WORD, &bufferOut[j], spaceLeft);		//Stream part of the data into the buffer
					j = spaceLeft;
					count += spaceLeft;
					nDataRead -= spaceLeft;
				}
				*/
			}

			nstatus = Pe0003_CbusReadWord(CBUSPORT, STATUS);

			if (nstatus & IRQ_UFLOW)			//Check for underflow
			{
				mprintf("ERROR - Data underflow\n");
			}

			if (DEBUG_DISP)
			{
				if (count > dispCount)
				{
					dispCount += 255;
					mprintf("s%d \n", count);
				}
			}


			if (count >= nSamples)
				break;

		}

		if (count >= nSamples)
			break;

		res = PR7261_FileReadSamples(*file_id, (uint16_t *) bufferOut, OUTBUFFER_SIZE , &nDataRead, CFG_IN_FILE);
		if (res != GUI_FILE_RESULT_OK)
		{
			mprintf("ERROR - Reading data from file\n");
		}
	}
		return TRUE;
}



uint8_t RunCBusOutAnaInOp_Loop(uint16_t *sBufferOut, uint32_t nSamples)
{
	uint32_t i = 0;
	uint32_t count = 0;
	uint32_t dispCount = 0;
	uint32_t maxSamples = nSamples;
	uint16_t nstatus;
	uint16_t level;


	while(1)
	{
		//Get level fifo in
		level = Pe0003_CbusReadByte(CBUSPORT, FIFO_IN_LEVEL);

		if (level < MAX_FIFO_SIZE)
		{
			Pe0003_CbusWriteWord(CBUSPORT,  FIFO_IN_WORD, sBufferOut[i++]);
			count++;

		}

		nstatus = Pe0003_CbusReadWord(CBUSPORT, STATUS);

		if (nstatus & IRQ_UFLOW)			//Check for underflow
		{
			mprintf("ERROR - Data underflow\n");
		}

		if (DEBUG_DISP)
		{
			if (count > dispCount)
			{
				dispCount += 255;
				mprintf("s%d \n", count);
			}
		}

		if (i >= maxSamples)
			i  = 0;
	}


	return TRUE;
}




/**
 * @brief Close the file
 * @param file_id - Id of the file
 * @param fileType - Type of file
 * @return TRUE
 */
uint8_t EndCBusInOp(uint8_t *file_id, uint8_t fileType)
{
	uint8_t res;

	res = PR7261_FileClose(*file_id, fileType);

	mprintf("End capture\n");

	return TRUE;
}


uint8_t Custom_Encoder_Op(uint32_t nSamples)
{
	uint8_t res;
	uint8_t file_id = 0;
	uint16_t val = 0;

	res = RunFileOuputRequired(&file_id);
	if (res == FALSE)
		return FALSE;

	//General Configuration
	Pe0003_CbusWriteWord(CBUSPORT, MODE_REG, 0);				//Idle mode to configure

	//If analog configuration
	Pe0003_CbusWriteWord(CBUSPORT, ANAIN_CONF, ANAIN_CONF_VAL);			//Power up AnlogIn
	mprintf("ANAIN_CONF_REG 0x%x\n", ANAIN_CONF_VAL);
	Pe0003_CbusWriteWord(CBUSPORT, ANAIN_COARSE_GAIN, ANAIN_COARSE_GAIN_VAL);		//0dB gain
	mprintf("ANAIN_COARSE_GAIN 0x%x\n", ANAIN_COARSE_GAIN_VAL);

	Pe0003_CbusWriteWord(CBUSPORT, FIFO_CONTROL, 0x8080);		//Flush FIFO

	Pe0003_TimerDelayUs(10000);

	//If analogue configuration does not need this
	val = INPUT_TYPE_VAL | INPUT_RATE_VAL;
	mprintf("INPUT_REG 0x%x\n", val);
	Pe0003_CbusWriteWord(CBUSPORT, INPUT_TYPE, val);			//Set input register


	val = OUTPUT_TYPE_VAL | OUTPUT_RATE_VAL;
	mprintf("OUTPUT_REG 0x%x\n", val);
	Pe0003_CbusWriteWord(CBUSPORT, OUTPUT_TYPE, val);		//Set output register

	val = (MODE_AUDIO_SRC_VAL << 8) | (MODE_AUDIO_DST_CBUS << 4) | MODE_HALF_TRANSC;
	mprintf("MODE_REG 0x%x\n", val);
	Pe0003_CbusWriteWord(CBUSPORT, MODE_REG, (MODE_AUDIO_SRC_VAL << 8) | (MODE_AUDIO_DST_CBUS << 4) | MODE_HALF_TRANSC);			//Mode register


	//Run main loop
	res = RunCBusInAnaOutOp(&file_id, nSamples);
	if (res == FALSE)
		return FALSE;

	EndCBusInOp(&file_id, CFG_OUT_FILE);

	return TRUE;
}



uint8_t Custom_Decoder_Op(uint32_t nSamples)
{
	uint8_t res;
	uint8_t file_id = 0;
	uint16_t val;

	res = RunFileInputRequired(&file_id);
	if (res == FALSE)
		return FALSE;


	//MainConfiguration
	Pe0003_CbusWriteWord(CBUSPORT, MODE_REG, 0);				//Idle mode to configure
	Pe0003_CbusWriteWord(CBUSPORT, FIFO_CONTROL, 0x8080);		//Flush FIFO

	Pe0003_TimerDelayUs(10000);

	Pe0003_CbusWriteWord(CBUSPORT, INPUT_TYPE, INPUT_TYPE_VAL | INPUT_RATE_VAL);		//Input register
	val = INPUT_TYPE, INPUT_TYPE_VAL | INPUT_RATE_VAL;
	mprintf("INPUT_REG 0x%x\n", val);
	Pe0003_CbusWriteWord(CBUSPORT, OUTPUT_TYPE, OUTPUT_TYPE_VAL | OUTPUT_RATE_VAL);		//Output register
	val = OUTPUT_TYPE, OUTPUT_TYPE_VAL | OUTPUT_RATE_VAL;
	mprintf("OUTPUT_REG 0x%x\n", val);

	Pe0003_CbusWriteWord(CBUSPORT, ANAOUT_CONF, ANAOUT_CONF_VAL);						//ANAOUT configuration
	val = ANAOUT_CONF_VAL;
	mprintf("ANAOUT_CONF_REG 0x%x\n", val);
	Pe0003_CbusWriteWord(CBUSPORT, ANAOUT_COARSE_GAIN, ANAOUT_COARSE_GAIN_VAL);			//Set gain
	val = ANAOUT_COARSE_GAIN_VAL;
	mprintf("ANAOUT_COARSE_GAIN_REG 0x%x\n", val);

	Pe0003_CbusWriteWord(CBUSPORT, REG_DONE_SELECT, REG_DONE_MODE);					//Set interrupt on Mode Reg Done
	Pe0003_CbusWriteWord(CBUSPORT, MODE_REG, 0);									//Idle mode to configure
	//FIXME DANIEL SET INTERRUPT

	val = (MODE_AUDIO_SRC_CBUS << 8) | (MODE_AUDIO_DST_VAL << 4) | MODE_HALF_TRANSC;
	mprintf("MODE_REG 0x%x\n", val);
	Pe0003_CbusWriteWord(CBUSPORT, MODE_REG, (MODE_AUDIO_SRC_CBUS << 8) | (MODE_AUDIO_DST_VAL << 4) | MODE_HALF_TRANSC);			//Mode register





	//Run main loop
	res = RunCBusOutAnaInOp(&file_id, nSamples);
	if (res == FALSE)
		return FALSE;

	EndCBusInOp(&file_id, CFG_IN_FILE);

	return TRUE;
}



uint8_t Custom_Decoder_Loop_Op(uint32_t nSamples)
{
	//uint8_t res;
	uint8_t file_id = 0;
	uint32_t maxSamples = nSamples;
	uint16_t val;

	if (maxSamples > OUTSTATICBUFFER_SIZE)
		maxSamples = OUTSTATICBUFFER_SIZE;

	RunFileInputRequired_Loop(sBufferOut, maxSamples);

	Pe0003_CbusWriteWord(CBUSPORT, MODE_REG, 0);				//Idle mode to configure
	Pe0003_CbusWriteWord(CBUSPORT, FIFO_CONTROL, 0x8080);		//Flush FIFO

	Pe0003_TimerDelayUs(10000);

	Pe0003_CbusWriteWord(CBUSPORT, INPUT_TYPE, INPUT_TYPE_VAL | INPUT_RATE_VAL);			//Unpacked CVSD 32Kbps
	val = INPUT_TYPE_VAL | INPUT_RATE_VAL;
	mprintf("INPUT_REG 0x%x\n", val);
	Pe0003_CbusWriteWord(CBUSPORT, OUTPUT_TYPE, OUTPUT_TYPE_VAL | OUTPUT_RATE_VAL);		//PCM 16 bit signed linear
	val = OUTPUT_TYPE_VAL | OUTPUT_RATE_VAL;
	mprintf("OUTPUT_REG 0x%x\n", val);

	Pe0003_CbusWriteWord(CBUSPORT, ANAOUT_CONF, ANAOUT_CONF_VAL);	//0x802 power up ANAOUT driver
	mprintf("ANAOUT_CONF_REG 0x%x\n", ANAOUT_CONF_VAL);
	Pe0003_CbusWriteWord(CBUSPORT, ANAOUT_COARSE_GAIN, ANAOUT_COARSE_GAIN_VAL);							//0dB gain
	mprintf("ANAOUT_COARSE_GAIN_REG 0x%x\n", ANAOUT_COARSE_GAIN_VAL);

	Pe0003_CbusWriteWord(CBUSPORT, REG_DONE_SELECT, REG_DONE_MODE);					//Set interrupt on Mode Reg Done
	Pe0003_CbusWriteWord(CBUSPORT, MODE_REG, 0);				//Idle mode to configure
	//FIXME DANIEL SET INTERRUPT

	val  = (MODE_AUDIO_SRC_CBUS << 8) | (MODE_AUDIO_DST_VAL << 4) | MODE_HALF_TRANSC;
	mprintf("MODE_REG 0x%x\n", val);
	Pe0003_CbusWriteWord(CBUSPORT, MODE_REG, (MODE_AUDIO_SRC_CBUS << 8) | (MODE_AUDIO_DST_VAL << 4) | MODE_HALF_TRANSC);			//Mode register


	//Run main loop
	RunCBusOutAnaInOp_Loop(sBufferOut, maxSamples);

	EndCBusInOp(&file_id, CFG_IN_FILE);

	return TRUE;
}


uint8_t Custom_EncoderDecoder_Op()
{
	uint16_t val;

	Pe0003_CbusWriteWord(CBUSPORT, MODE_REG, 0);				//Idle mode to configure

	Pe0003_CbusWriteWord(CBUSPORT, ANAIN_CONF, ANAIN_CONF_VAL);			//Power up AnlogIn
	mprintf("ANAIN_CONF_REG 0x%x\n", ANAIN_CONF_VAL);
	Pe0003_CbusWriteWord(CBUSPORT, ANAIN_COARSE_GAIN, ANAIN_COARSE_GAIN_VAL);		//0dB gain
	mprintf("ANAIN_COARSE_GAIN_REG 0x%x\n", ANAIN_COARSE_GAIN_VAL);

	Pe0003_CbusWriteWord(CBUSPORT, FIFO_CONTROL, 0x8080);		//Flush FIFO

	Pe0003_TimerDelayUs(10000);

	val = INPUT_TYPE_VAL | INPUT_RATE_VAL;
	Pe0003_CbusWriteWord(CBUSPORT, INPUT_TYPE, val);			//Unpacked CVSD 32Kbps
	mprintf("INPUT_REG 0x%x\n", val);
	//Pe0003_CbusWriteWord(CBUSPORT, OUTPUT_TYPE, OUTPUT_TYPE_VAL | OUTPUT_RATE_VAL);		//PCM 16 bit signed linear

	val = ANAOUT_CONF_VAL;
	Pe0003_CbusWriteWord(CBUSPORT, ANAOUT_CONF, val);	//0x802 power up ANAOUT driver
	mprintf("ANAOUT_CONF_REG 0x%x\n", val);

	Pe0003_CbusWriteWord(CBUSPORT, ANAOUT_COARSE_GAIN_VAL, ANAOUT_COARSE_GAIN_VAL);							//0dB gain
	mprintf("ANAOUT_COARSE_GAIN_REG 0x%x\n", ANAOUT_COARSE_GAIN_VAL);

	Pe0003_CbusWriteWord(CBUSPORT, REG_DONE_SELECT, REG_DONE_MODE);					//Set interrupt on Mode Reg Done
	Pe0003_CbusWriteWord(CBUSPORT, MODE_REG, 0);				//Idle mode to configure
	//FIXME DANIEL SET INTERRUPT

	val = (MODE_AUDIO_SRC_ANA << 8) | (MODE_AUDIO_DST_ANA << 4) | MODE_ENCDEC;
	mprintf("MODE_REG 0x%x\n", val);
	mprintf("Encoder-Decoder Running\n");
	Pe0003_CbusWriteWord(CBUSPORT, MODE_REG, val);			//Mode register


	return TRUE;
}



uint8_t LoadSamplesFromFile(uint16_t *sBufferIn, uint32_t nSamples, uint32_t *recoverSamples)
{
	uint16_t tmpBufferOut[OUTBUFFER_SIZE];
	uint8_t file_id = 0;
	uint32_t dataLeft = 0;
	uint8_t res = TRUE;
	uint32_t nDataRead = 0;
	uint32_t i = 0;
	uint32_t maxOutSamples = nSamples;

	//Open data file
	char filename[] = "dummy.dat";
	res = PR7261_FileDialogOpen(&file_id, filename, FILE_READ, CFG_IN_FILE);
	if (res != GUI_FILE_RESULT_OK)
	{
		mprintf("ERROR - Opening file for writing\n");
		return FALSE;
	}

	//Store data into the buffer
	res = PR7261_FileReadSamples(file_id, (uint16_t *)tmpBufferOut, OUTBUFFER_SIZE , &nDataRead, CFG_IN_FILE);

	i = 0;
	while(nDataRead != 0)
	{
		memcpy(&sBufferIn[i], tmpBufferOut, nDataRead * sizeof(uint16_t));
		i += nDataRead;

		res = PR7261_FileReadSamples(file_id, (uint16_t *)tmpBufferOut, OUTBUFFER_SIZE , &nDataRead, CFG_IN_FILE);

		if(i + nDataRead > maxOutSamples)
			break;
	}

	if (nDataRead != 0)
	{
		if (i <= nSamples)
		{
			dataLeft = nSamples - i;
			memcpy(&sBufferIn[i], tmpBufferOut, dataLeft * sizeof(uint16_t));
			i += dataLeft;
		}

		*recoverSamples = nSamples;
	}
	else
	{
		*recoverSamples = i;
	}

	//Close file
	res = PR7261_FileClose(file_id, CFG_IN_FILE);

	return TRUE;
}

uint8_t StoreSamplesIntoFile(uint16_t *sBufferOut, uint32_t nSamples)
{
	uint16_t tmpBufferIn[INBUFFER_SIZE];
	uint8_t file_id = 0;
	uint32_t i = 0;
	uint32_t j = 0;
	uint32_t nDataWritten = 0;
	uint8_t res = TRUE;

	//Open data file
	char filename[] = "dummy.dat";
	res = PR7261_FileDialogOpen(&file_id, filename, FILE_WRITE, CFG_OUT_FILE);
	if (res != GUI_FILE_RESULT_OK)
	{
		mprintf("ERROR - Opening file for writing\n");
		return FALSE;
	}

	while(i < nSamples)
	{
		tmpBufferIn[j++] = sBufferOut[i++];
		if (j == INBUFFER_SIZE)
		{
			j = 0;
			res = PR7261_FileWriteSamples(file_id, (uint16_t *)tmpBufferIn, INBUFFER_SIZE , &nDataWritten, CFG_OUT_FILE);
			if (res != GUI_FILE_RESULT_OK)
			{
				mprintf("ERROR - Writing data into a file\n");
				return FALSE;
			}
		}
	}

	//Store data left in tmpBufferIn
	if (j != INBUFFER_SIZE)
	{
		res = PR7261_FileWriteSamples(file_id, (uint16_t *)tmpBufferIn, j , &nDataWritten, CFG_OUT_FILE);
		if (res != GUI_FILE_RESULT_OK)
		{
			mprintf("ERROR - Writing data into a file\n");
			return FALSE;
		}
		j = 0;
	}

	//Close file
	res = PR7261_FileClose(file_id, CFG_OUT_FILE);

	return TRUE;
}



uint8_t RunTranscoder(uint16_t *sBufferIn, uint16_t *sBufferOut, uint32_t maxInSamples, uint32_t maxOutSamples)
{
	uint32_t countIn = 0;
	uint32_t countOut = 0;
	uint8_t enableEncoder = TRUE;
	uint8_t enableDecoder = TRUE;
	uint16_t level = 0;
	uint16_t val;
	uint32_t j = 0;
	uint32_t i = 0;
	uint32_t dispCount = 0;
	uint16_t nstatus = 0;


	countIn = 0;
	countOut = 0;
	while(enableEncoder || enableDecoder)
	{
		//Encoder part
		if (enableEncoder)
		{
			level = Pe0003_CbusReadByte(CBUSPORT, FIFO_OUT_LEVEL);

			if (level > 0)
			{
				val = Pe0003_CbusReadWord(CBUSPORT, FIFO_OUT_WORD);

				sBufferIn[j++] = val;
				countIn++;

				if (DEBUG_DISP)
				{
					if ((countIn % 255) == 0)
						mprintf("s%d In\n", countIn);
				}

				if (countIn == maxInSamples)
					enableEncoder = FALSE;
			}

			/*
			if (level == WARNING_FIFO_LEVEL)
			{
				mprintf("ERROR - Buffer overflow\n");
			}
			*/

			//Check status for underflows
			nstatus = Pe0003_CbusReadWord(CBUSPORT, STATUS);

			if (nstatus & IRQ_OFLOW)			//Check for overflows
			{
				mprintf("ERROR - Buffer overflow\n");
			}

			//Case there is not more samples to process by the decoder
			//Samples must be provided to the encoder While the decoder is still running
			if (!enableDecoder)
			{
				level = Pe0003_CbusReadByte(CBUSPORT, FIFO_IN_LEVEL);

				if (level < MAX_FIFO_SIZE)
					Pe0003_CbusWriteWord(CBUSPORT,  FIFO_IN_WORD, 0);
			}
		}

		//Decoder part
		if (enableDecoder)
		{
			level = Pe0003_CbusReadByte(CBUSPORT, FIFO_IN_LEVEL);


			if (level < MAX_FIFO_SIZE)
			{

				Pe0003_CbusWriteWord(CBUSPORT,  FIFO_IN_WORD, sBufferOut[i++]);
				countOut++;

				if (i == maxOutSamples)
					break;
			}


			nstatus = Pe0003_CbusReadWord(CBUSPORT, STATUS);

			if (nstatus & IRQ_UFLOW)			//Check for underflow
			{
				mprintf("ERROR - Data underflow\n");
			}

			if (countOut == maxOutSamples)
				enableDecoder = FALSE;

			if (DEBUG_DISP)
			{
				if (countOut > dispCount)
				{
					dispCount += 255;
					mprintf("s%d \n", countOut);
				}
			}

			//This is in case there is not more samples to process by the encoder and still there are smples from the decoder
			//Must continue getting samples while the Decoder is still running
			if (!enableEncoder)
			{
				level = Pe0003_CbusReadByte(CBUSPORT, FIFO_OUT_LEVEL);
				if (level > 0)
					val = Pe0003_CbusReadWord(CBUSPORT, FIFO_OUT_WORD);
			}
		}
	}

	return TRUE;
}



//FIXME REMEMBER NOTE In case the number of samples is bigger than staticbuffer sizes,
//the samples are limited to these sizes
uint8_t Custom_Transcopder_Op(uint32_t nSamples)
{
	uint8_t res;
	uint32_t readSamples = 0;
	uint16_t val;

	uint32_t maxInSamples = 0;
	uint32_t maxOutSamples = 0;

	//Set maximum number of samples for encoder and decoder
	if (nSamples > INSTATICBUFFER_SIZE)
		maxInSamples = INSTATICBUFFER_SIZE;
	else
		maxInSamples = nSamples;

	if (nSamples > OUTSTATICBUFFER_SIZE)
		maxOutSamples = OUTSTATICBUFFER_SIZE;
	else
		maxOutSamples = nSamples;

	//Store samples into sBufferIn, The file can contain less samples than expected (return readSamples)
	res = LoadSamplesFromFile(sBufferIn, maxInSamples, &readSamples);
	if (res == FALSE)
	{
		return FALSE;
	}

	//Main configuration
	Pe0003_CbusWriteWord(CBUSPORT, MODE_REG, 0);								//Idle mode to configure
	Pe0003_CbusWriteWord(CBUSPORT, ANAIN_CONF, ANAIN_CONF_VAL);					//ANAIN Conf Val
	mprintf("ANAIN_CONF_REG 0x%x\n", ANAIN_CONF_VAL);
	Pe0003_CbusWriteWord(CBUSPORT, ANAIN_COARSE_GAIN, ANAIN_COARSE_GAIN_VAL);	//ANAIN Gain
	mprintf("ANAIN_COARSE_GAIN_REG 0x%x\n", ANAIN_COARSE_GAIN_VAL);

	Pe0003_CbusWriteWord(CBUSPORT, FIFO_CONTROL, 0x8080);				//Flush FIFO

	Pe0003_TimerDelayUs(10000);

	Pe0003_CbusWriteWord(CBUSPORT, INPUT_TYPE, INPUT_TYPE_VAL | INPUT_RATE_VAL);		//Input register
	val = INPUT_TYPE_VAL | INPUT_RATE_VAL;
	mprintf("INPUT_REG 0x%x\n", val);
	Pe0003_CbusWriteWord(CBUSPORT, OUTPUT_TYPE, OUTPUT_TYPE_VAL | OUTPUT_RATE_VAL);		//Output register
	val = OUTPUT_TYPE_VAL | OUTPUT_RATE_VAL;
	mprintf("OUTPUT_REG 0x%x\n", val);

	Pe0003_CbusWriteWord(CBUSPORT, ANAOUT_CONF, ANAOUT_CONF_VAL);					//ANAOUT Conf Val
	mprintf("ANAOUT_CONF_REG 0x%x\n", ANAOUT_CONF_VAL);
	Pe0003_CbusWriteWord(CBUSPORT, ANAOUT_COARSE_GAIN, ANAOUT_COARSE_GAIN_VAL);		//ANAOUT Gain
	val = ANAOUT_COARSE_GAIN, ANAOUT_COARSE_GAIN_VAL;
	mprintf("ANAOUT_COARSE_GAIN_REG 0x%x\n", val);

	val = (MODE_AUDIO_SRC_VAL << 8) | (MODE_AUDIO_DST_VAL << 4) | MODE_FULL_TRANSC;
	mprintf("MODE_REG 0x%x\n", val);
	Pe0003_CbusWriteWord(CBUSPORT, MODE_REG, (MODE_AUDIO_SRC_VAL << 8) | (MODE_AUDIO_DST_VAL << 4) | MODE_FULL_TRANSC);

	//Main operation
	res = RunTranscoder(sBufferIn, sBufferOut, maxInSamples, maxOutSamples);
	if (res == FALSE)
	{
		return FALSE;
	}

	//Store samples from encoder into a file. Store the maxNumberofSamples
	res = StoreSamplesIntoFile(sBufferOut, maxOutSamples);
	if (res == FALSE)
	{
		return FALSE;
	}


	return TRUE;
}












