/*-------------------------------------------------------------------------
   AR168R function copy right information

   Copyright (c) 2011-2014. Lin, Rongrong <woody@palmmicro.com>

   All rights reserved.

   Redistribution and use in source and binary forms, with or without
   modification, are permitted provided that the following conditions are met:
    * Redistributions of source code must retain the above copyright
      notice, this list of conditions and the following disclaimer.
    * Redistributions in binary form must reproduce the above copyright
      notice, this list of conditions and the following disclaimer in the
      documentation and/or other materials provided with the distribution.
    * Neither the name of Palmmicro nor the names of its contributors may be
	  used to endorse or promote products derived from this software without
	  specific prior written permission.

   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
   ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
   WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   DISCLAIMED. IN NO EVENT SHALL COPYRIGHT OWNER BE LIABLE FOR ANY
   DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
   (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
   LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-------------------------------------------------------------------------*/

#include "version.h"
#include "type.h"
#include "core.h"
#include "apps.h"
#include "bank1.h"
#include "dsp.h"
#include "sfr.h"

#ifdef SYS_ROIP

extern BOOLEAN _bLogoned;	// function.c

#define VOICE_LEVEL		1

#ifdef OEM_ROIP
const UCHAR _pcCOR_HIGH[] = "COR HIGH"; 
const UCHAR _pcCOR_LOW[] = "COR LOW"; 
#ifdef PTT_RFC2833
#define KEY_COR_HIGH	'2'
#define KEY_COR_LOW		'1'
#endif
#define MAX_TALK_INTERVAL	30
#endif

#define AUTO_DIAL_INTERVAL	30

extern volatile BOOLEAN _bCOR;
extern volatile UCHAR _iGPIO_COR;		// GPIO B2 COR input
UCHAR _iOldCOR;

USHORT _sRtpTotal;
UCHAR _iAutoDialCounter;

#ifdef OEM_ROIP
UCHAR _iMaxTalkCounter;
UCHAR _iMaxListenCounter;

void _PTT_High()
{
	if (!(rGPIO_B & 0x01))
	{
		rGPIO_B |= 0x01;
		UdpDebugString("PTT HIGH");
	}
}

void _PTT_Low()
{
	if (rGPIO_B & 0x01)
	{
		rGPIO_B &= 0xfe;
		UdpDebugString("PTT LOW");
//		UdpDebugVal(_sRtpTotal, 10);
	}
	_iMaxListenCounter = 0;
}

void _Send_COR_Text(PCHAR pcCOR)
{
	UCHAR pc[9];

	strcpy(pc, pcCOR);
	TaskHandleEvent(UI_EVENT_TEXT, (USHORT)pc);
}

void _COR_High()
{
	if (!Sys_bOptVad)
	{	
#ifdef PTT_RFC2833
		// Send 'KEY_COR_HIGH' key to inform COR high
		TaskHandleEvent(UI_EVENT_DIGIT, (USHORT)KEY_COR_HIGH);
#else
		_Send_COR_Text(_pcCOR_HIGH);
#endif
	}
	CodecMicMute(TRUE);
	CodecSetVol(Sys_iSpeakerVol);
	_iMaxTalkCounter = 0;
	UdpDebugString(_pcCOR_HIGH);
}

void _COR_Low()
{
	if (!Sys_bOptVad)
	{	
#ifdef PTT_RFC2833
		// Send 'KEY_COR_LOW' key to inform COR low
		TaskHandleEvent(UI_EVENT_DIGIT, (USHORT)KEY_COR_LOW);
#else
		_Send_COR_Text(_pcCOR_LOW);
#endif
	}
	CodecMicMute(FALSE);
	CodecSetVol(0);
	UdpDebugString(_pcCOR_LOW);
}
#endif

void RoIP_Start()
{
	_bCOR = FALSE;
	_iOldCOR = 0;
	_sRtpTotal = 0;
	_iAutoDialCounter = 0;
#ifdef OEM_ROIP
	_iMaxTalkCounter = 0;
	_PTT_Low();
#endif

#ifndef LCD_HY1602
	// GPIO G0 as input when LCD not used
	rGPIO_G_Enable &= 0xfe;
	rGPIO_G_Enable |= 0x10;
#endif

	// GPIO B4 output
	rGPIO_B_Output_Enable |= 0x10;	
	rGPIO_B_Input_Enable &= ~0x10;
	rGPIO_B &= ~0x10;	// B4 output low

	// GPIO B5 input
	rGPIO_B_Output_Enable &= ~0x20;	
	rGPIO_B_Input_Enable |= 0x20;

#ifdef OEM_ROIP
	SpeakerRing();
	CodecSetVol(Sys_iSpeakerVol);
#elif defined OEM_UART
	SpeakerOff();
	CodecSetVol(Sys_iHandsetVol);
#endif
}

void RoIP_Run()
{
#ifdef OEM_ROIP
	if (!_bCOR)				return;
	if (_iOldCOR == (_iGPIO_COR & 0x04))	return;
	if (TaskGetCallInfo(CALL_INFO_STATE) != CALL_STATE_TALKING)	return;

	_iOldCOR = _iGPIO_COR & 0x04;
	if (_iOldCOR)
	{
		_COR_High();
	}
	else
	{	// I am talking now.
		_COR_Low();
	}
#endif

	_bCOR = FALSE;
}

void _CheckAutoDial()
{
	if (rGPIO_B & 0x20)
	{	// do self-defined auto dial out when GPIO_B5 HIGH
		if (Sys_iCurMode == SYS_MODE_STANDBY)
		{
			if (!Sys_bAutoAnswer)
			{
				if (_bLogoned)
				{	// automatically dial out every minute.
					OnHook();	
				}
			}
		}
	}
}

void RoIP_Timer()
{
	BOOLEAN bTalking;

	bTalking = (TaskGetCallInfo(CALL_INFO_STATE) == CALL_STATE_TALKING) ? TRUE : FALSE;
#ifdef OEM_ROIP
	if (bTalking)
	{	// during a call
		if (_iOldCOR)
		{
			if (Sys_bOptVad)
			{
				if (_sRtpTotal < G729_FRAME_LEN * VOICE_LEVEL)
				{
					_PTT_Low();
				}
				_sRtpTotal = 0;
			}
			else
			{
				_iMaxListenCounter ++;
				if (_iMaxListenCounter >= MAX_TALK_INTERVAL)
				{	// listen too much, something might be wrong, turn off audio playing
					_PTT_Low();
				}
			}
		}
		else
		{	// I am talking
			_iMaxTalkCounter ++;
			if (_iMaxTalkCounter >= MAX_TALK_INTERVAL)
			{	// talk too much, shut up
				_COR_High();
			}
		}
	}
#endif

	if (!bTalking)
	{
		_iAutoDialCounter ++;
		if (_iAutoDialCounter >= AUTO_DIAL_INTERVAL)
		{
#ifdef OEM_ROIP
			// Keep PTT LOW in all unexpected situations.
			_PTT_Low();
#endif

			_iAutoDialCounter = 0;
			_CheckAutoDial();
		}
	}

#ifndef LCD_HY1602
	if (rGPIO_G & 0x01)
	{
		UdpDebugString("GPIO_G0 HIGH");
	}
	else
	{
		UdpDebugString("GPIO_G0 LOW");
	}
#endif
/*
	if (rGPIO_B & 0x20)
	{
		UdpDebugString("GPIO_B5 HIGH");
	}
	else
	{
		UdpDebugString("GPIO_B5 LOW");
	}
*/
}

#ifdef PTT_RFC2833
void RoIP_Key(UCHAR iKey)
{
	UdpDebugChar(iKey);
#ifdef OEM_ROIP
	if (!Sys_bOptVad)
	{
		if (iKey == (UCHAR)KEY_COR_LOW)
		{
			_PTT_High();
			return;
		}
		else if (iKey == (UCHAR)KEY_COR_HIGH)
		{
			_PTT_Low();
			return;
		}
	}
#endif
}
#else
void RoIP_Text(PCHAR pcText)
{
#ifdef OEM_ROIP
	if (Sys_bOptVad)							return;

	if (!memcmp_str(pcText, _pcCOR_LOW))
	{
		_PTT_High();
	}
	else if (!memcmp_str(pcText, _pcCOR_HIGH))
	{
		_PTT_Low();
	}
#else
	pcText;
#endif
}
#endif


void RoIP_LogonOk()
{
#ifdef OEM_ROIP
	_CheckAutoDial();
#endif
}

void RoIP_Ringing()
{
#ifdef OEM_ROIP
	_PTT_High();
	_iOldCOR = 0;
#endif
}

void RoIP_Dial()
{
	RoIP_Ringing();
}

void RoIP_Connected()
{
#ifdef OEM_ROIP
	_PTT_Low();
#endif
	_iAutoDialCounter = 0;
}

void RoIP_EndCall()
{
	RoIP_Connected();
}

void RoIP_IncomingData(USHORT sLen)
{
#ifdef OEM_ROIP
	if (Sys_bOptVad)
	{
		if (sLen >= G729_FRAME_LEN)
		{
			_PTT_High();
		}
		_sRtpTotal += sLen;
	}
//	UdpDebugVal(sLen, 10);
#else
	sLen;
#endif
}

#endif

