//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//+
//+   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 "monitor.h"
#include "messages.h"
#include "mon_general.h"

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

#include <stdio.h>

//To use the GUI printfs
#define printf		mprintf
#define scanf       mscanf


//Local functions
uint8_t ProgramRegisters();

uint16_t status = 0;



int main(void) {
	uint8_t res;
	uint8_t opt = 0;

	//Init the board and Gui functions
	res = BoardInit();

	//Load FI
	res = LoadFI();
	if (res == FALSE)
	{
		mprintf("ERROR - Loading FI\n");
	}


	opt = Menu_DefaultSelection(DEFAULT_OPT);


	//Set idle mode
	Pe0003_CbusWriteWord(CBUS1, MODE_REG, 0);

	//Flush FIFOs
	Pe0003_CbusWriteWord(CBUS1, FIFO_CONTROL, 8080);


	//Configure device for the correct xtal Freq
	res = ProgramRegisters();

	uint32_t nSamples = NSAMPLES;

	//Ask for the number of samples from option 1-9
	switch (opt)
	{
		case(1):
		case(2):
		case(3):
		case(5):
		case(8):
			nSamples = GetNumberOfSamples();
			break;
		default: nSamples = NSAMPLES;
	}

	mprintf("Number of samples: %d\n", nSamples);

	switch(opt)
	{
		case(1): res = G711_Encoder_Op(nSamples);	break;
		case(2): res = G723_Encoder_Op(nSamples);	break;
		case(3): res = G711_Decoder_Op(nSamples);	break;
		case(4): res = G711_Decoder_Op_Loop(nSamples);	break;
		case(5): res = G723_Decoder_Op(nSamples);	break;
		case(6): res = G723_Decoder_Op_Loop(nSamples);	break;
		case(7): res = G711_EncoderDecoder_Op(); break;
		case(8): res = G723_Encoder_Decoder_FullDuplex_Op(nSamples) break;
	}

	if (res ==FALSE)
	{
		mprintf("ERROR - Some error happened\n");
	}

	mprintf("END OF PROGRAM\n");

	return 1 ;
}



/**
 * @brief Wait for an interrupt flag to set.
 * @param timeout - timeout value in us.
 * @param mask - flag to wait on.
 * @return Return false if a timeout occurs.
 */

uint8_t WaitStatusIrq(uint32_t timeout, uint16_t mask)
{
	uint8_t timed_out = 0;

	SetDelay(timeout);
	timed_out = DelayReached();
	while (!timed_out)
	{
		__WFI();
		if (((status) & mask) == mask)
		{
			status &= ~mask;
			return TRUE;
		}

		timed_out = DelayReached();
	}

	mprintf("Timeout!!\n ");
	return FALSE;
}


/**
 * IRQn1 interrupt handler
 */
void GPIO0_IRQHandler(void)
{
	status |= Pe0003_CbusReadWord(CBUSPORT, STATUS);
	//Clear interrupt
	//Needs to clear interrupts otherwise, the previous comment will cause an usb overflow
	LPC_GPIO_PIN_INT->IST |= (1<<0);
}





uint8_t ProgramRegisters()
{
	uint16_t status_mask = 0;

	status_mask = ST_IRQ | ST_PRG;
	Pe0003_CbusWriteWord(CBUSPORT, IRQ_ENABLE, status_mask);

	//Clear status value
	status = Pe0003_CbusReadWord(CBUSPORT, STATUS);
	status = 0;
	Pe0003_IrqnEnable();

	//Programming Block Clock	P1.X, 19.2MHz configuration selected
	Pe0003_CbusWriteWord(CBUSPORT, MODE_REG, 0x0210);
	Pe0003_CbusWriteWord(CBUSPORT, PROG_REG, P1_2_VAL);				//P1.2
	WaitStatusIrq(1000, ST_PRG);

	Pe0003_CbusWriteWord(CBUSPORT, PROG_REG, P1_3_VAL);				//P1.3
	WaitStatusIrq(1000, ST_PRG);

	Pe0003_CbusWriteWord(CBUSPORT, PROG_REG, P1_4_VAL);				//P1.4
	WaitStatusIrq(1000, ST_PRG);

	Pe0003_CbusWriteWord(CBUSPORT, PROG_REG, P1_5_VAL);				//P1.5
	WaitStatusIrq(1000, ST_PRG);

	return TRUE;
}





