blob: 787dfda6aaf01c4311b1800c07659629a8ca4344 [file] [log] [blame]
/*****************************************************************************
* Copyright Statement:
* --------------------
* This software is protected by Copyright and the information contained
* herein is confidential. The software may not be copied and the information
* contained herein may not be used or disclosed except with the written
* permission of MediaTek Inc. (C) 2011
*
* BY OPENING THIS FILE, BUYER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
* THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
* RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO BUYER ON
* AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT.
* NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE
* SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR
* SUPPLIED WITH THE MEDIATEK SOFTWARE, AND BUYER AGREES TO LOOK ONLY TO SUCH
* THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. MEDIATEK SHALL ALSO
* NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE RELEASES MADE TO BUYER'S
* SPECIFICATION OR TO CONFORM TO A PARTICULAR STANDARD OR OPEN FORUM.
*
* BUYER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND CUMULATIVE
* LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE,
* AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE,
* OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY BUYER TO
* MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
*
* THE TRANSACTION CONTEMPLATED HEREUNDER SHALL BE CONSTRUED IN ACCORDANCE
* WITH THE LAWS OF THE STATE OF CALIFORNIA, USA, EXCLUDING ITS CONFLICT OF
* LAWS PRINCIPLES. ANY DISPUTES, CONTROVERSIES OR CLAIMS ARISING THEREOF AND
* RELATED THERETO SHALL BE SETTLED BY ARBITRATION IN SAN FRANCISCO, CA, UNDER
* THE RULES OF THE INTERNATIONAL CHAMBER OF COMMERCE (ICC).
*
*****************************************************************************/
/*******************************************************************************
*
* Filename:
* ---------
* eCall_drv.c
*
* Project:
* --------
* MAUI
*
* Description:
* ------------
* eCall Modem Driver
*
* Author:
* -------
* -------
*
*==============================================================================
* HISTORY
* Below this line, this part is controlled by PVCS VM. DO NOT MODIFY!!
*------------------------------------------------------------------------------
* removed!
* removed!
* removed!
*
* removed!
* removed!
* removed!
* removed!
*
* removed!
* removed!
*
* removed!
* removed!
* removed!
* removed!
*
* removed!
* removed!
* removed!
* removed!
*
* removed!
* removed!
* removed!
* removed!
*
* removed!
* removed!
* removed!
* removed!
*
* removed!
* removed!
* removed!
* removed!
*
* removed!
* removed!
* removed!
*
* removed!
* removed!
* removed!
*
* removed!
* removed!
* removed!
* removed!
*
* removed!
* removed!
* removed!
*
* removed!
* removed!
*
* removed!
* removed!
* removed!
*
* removed!
* removed!
* removed!
*
* removed!
* removed!
* removed!
*
* removed!
* removed!
* removed!
*
* removed!
* removed!
* removed!
*
* removed!
* removed!
* removed!
*
* removed!
* removed!
* removed!
*
* removed!
* removed!
* removed!
*
* removed!
* removed!
* removed!
*
* removed!
* removed!
* removed!
*
* removed!
*------------------------------------------------------------------------------
* Upper this line, this part is controlled by PVCS VM. DO NOT MODIFY!!
*==============================================================================
*******************************************************************************/
#include <stdio.h>
#include "ecall_defines.h"
#include "ecall_control.h"
#include "modemx.h"
#include "kal_public_api.h"
#include "kal_trace.h"
#include "l1sp_trc.h"
#include "l1audio.h"
#include "pcm4way.h"
#include "am.h"
#include "media.h"
#include "sp_enhance.h"
#include "bli_exp.h"
#include "spc_drv.h"
#include "sal_def.h"
#include "sal_exp.h"
Int16 eCall_TX_CTRL_SEQ_State[800];
Int16 eCall_TX_CTRL_SEQ_dlData[800];
Int16 eCall_TX_CTRL_SEQ_dlMetric[800];
Int16 eCall_RX_CTRL_SEQ_State[800];
Int16 eCall_RX_CTRL_SEQ_dlData[800];
Int16 eCall_RX_CTRL_SEQ_dlMetric[800];
Int16 eCall_RX_Ctrl_Index;
#define PCM_FIFO_LEN 2 // could be 1 ~ N
#define ECALL_SWB_BUF_LEN 640 // 32k*20ms = 640
#define ECALL_WB_BUF_LEN 320 // 16k*20ms = 320
#define ECALL_NB_BUF_LEN 160 // 8k*20ms = 160
typedef enum {
Udef = -1, Ivs, IvsRx, IvsTx, Psap, PsapRx, PsapTx
} RunMode;
typedef struct {
RunMode mode;
kal_bool ivsPush;
kal_bool msdReceived;
kal_bool msdSet;
kal_uint8 aud_id;
kal_uint8 Ctrl_Par_Switch;
kal_bool TxRx;
int frameStartHlack;
int frameStartHlackCur;
Ord8 NewMsd[ECALL_MSD_MAX_LENGTH];
Ord8 CurMsd[ECALL_MSD_MAX_LENGTH];
// For PCM4Way
kal_uint16 pcm_fifo_read;
kal_uint16 pcm_fifo_write;
kal_uint16 next_to_process;
kal_uint16 reserve_2byte;
// speech-channel PCM buffer
// Input from PCM4WAY
kal_uint16 ul_pcm_input[2*PCM_FIFO_LEN][ECALL_SWB_BUF_LEN]; // input buffer size = 640
kal_uint16 dl_pcm_input[2*PCM_FIFO_LEN][ECALL_SWB_BUF_LEN];
kal_uint16 ul_pcm_input_len[2*PCM_FIFO_LEN];
kal_uint16 dl_pcm_input_len[2*PCM_FIFO_LEN];
// SRC temp buffer (NB 8k only)
kal_uint16 ul_pcm_fifo[2*PCM_FIFO_LEN][ECALL_NB_BUF_LEN]; // input buffer size = 160
kal_uint16 dl_pcm_fifo[2*PCM_FIFO_LEN][ECALL_NB_BUF_LEN];
// Output to PCM4WAY
kal_uint16 ul_pcm_output_nb[2*PCM_FIFO_LEN][ECALL_NB_BUF_LEN]; //160
kal_uint16 ul_pcm_output_wb[2*PCM_FIFO_LEN][ECALL_WB_BUF_LEN]; //320
kal_uint16 ul_pcm_output_swb[2*PCM_FIFO_LEN][ECALL_SWB_BUF_LEN]; //640
kal_bool isUpdateUL[2*PCM_FIFO_LEN];
// SRC handler internal buffer
// 32k <-> 8k
kal_uint8 internal_buf_ul_out[2184]; // internal buffer for src
kal_uint8 internal_buf_dl_in[2184]; // internal buffer for src
// 16k <-> 8k
kal_uint8 internal_buf_ul_out2[2184]; // internal buffer for src
kal_uint8 internal_buf_dl_in2[2184]; // internal buffer for src
BLI_HANDLE * dl_downsample_16_8;
BLI_HANDLE * dl_downsample_32_8;
BLI_HANDLE * ul_upsample_8_16;
BLI_HANDLE * ul_upsample_8_32;
// For HRT
kal_uint16 HRT_status;
kal_uint16 HRT_status_backup;
eCall_Callback handler;
void *allocMem;
} EcallShell;
static EcallShell *eCallModemIVS;
static EcallShell *eCallModemPSAP;
kal_enhmutexid eCall_mutex;
/*------------------------------------------------*/
/* The private functions of eCall modem driver. */
/*------------------------------------------------*/
//#pragma arm section code="SECONDARY_ROCODE"
void eCall_Init(void)
{
eCall_mutex= kal_create_enh_mutex( "ECALL_MUTEX" );
}
static void eCall_HRT_Set(void)
{
eCallModemIVS->HRT_status = 1;
}
static void eCall_HRT_Clean(void)
{
eCallModemIVS->HRT_status = 0;
}
static void eCall_IVS_hisr(void)
{
kal_uint16 read_idx, write_idx;
if (eCallModemIVS == NULL)
return;
read_idx = eCallModemIVS->pcm_fifo_read;
write_idx = eCallModemIVS->pcm_fifo_write;
if (eCallModemIVS->pcm_fifo_read == eCallModemIVS->next_to_process) {
// Processed data isn't enough
if(spc_Get_Ecall_Lib_Status()==SPC_ECALL_ENABLE ){
PCM4WAY_FillSE(0);
PCM4WAY_FillSpk(0);
}
} else {
if(spc_Get_Ecall_Lib_Status()==SPC_ECALL_ENABLE ) {
// uplink-path
if (eCallModemIVS->isUpdateUL[read_idx] == KAL_FALSE) {
PCM4WAY_PutToSE((const uint16*)(eCallModemIVS->ul_pcm_input[read_idx]));
} else {
uint16 bufLen = SAL_PcmEx_GetBufLen(SAL_PCMEX_PNW_BUF_M2D_UL1);
if(ECALL_NB_BUF_LEN == bufLen) {
PCM4WAY_PutToSE((const uint16*)(eCallModemIVS->ul_pcm_output_nb[read_idx]));
} else if(ECALL_WB_BUF_LEN == bufLen) {
PCM4WAY_PutToSE((const uint16*)(eCallModemIVS->ul_pcm_output_wb[read_idx]));
} else {
PCM4WAY_PutToSE((const uint16*)(eCallModemIVS->ul_pcm_output_swb[read_idx]));
}
eCallModemIVS->isUpdateUL[read_idx] = KAL_FALSE;
MD_TRC_ECALL_IVS_PCM_UPDATE_PUTTOSE(read_idx, bufLen);
}
// downlink-path no change
PCM4WAY_PutToSpk((const uint16*)(eCallModemIVS->dl_pcm_input[read_idx]));
}
// Update index
eCallModemIVS->pcm_fifo_write++;
if (eCallModemIVS->pcm_fifo_write == 2*PCM_FIFO_LEN) {
eCallModemIVS->pcm_fifo_write = 0;
}
}
if (read_idx != write_idx) {
// There is enough space to write data from microphone
eCallModemIVS->ul_pcm_input_len[write_idx] = PCM4WAY_GetFromMic((uint16*)(eCallModemIVS->ul_pcm_input[write_idx]));
eCallModemIVS->dl_pcm_input_len[write_idx] = PCM4WAY_GetFromSD((uint16*)(eCallModemIVS->dl_pcm_input[write_idx]));
MD_TRC_ECALL_IVS_PCM_INPUT_LEN(write_idx, eCallModemIVS->ul_pcm_input_len[write_idx], write_idx, eCallModemIVS->dl_pcm_input_len);
// Update index
eCallModemIVS->pcm_fifo_read++;
if (eCallModemIVS->pcm_fifo_read == 2*PCM_FIFO_LEN) {
eCallModemIVS->pcm_fifo_read = 0;
}
}
eCallModemIVS->HRT_status_backup = eCallModemIVS->HRT_status;
eCall_HRT_Set();
L1Audio_SetEvent(eCallModemIVS->aud_id, (void*)0);
}
//#pragma arm section
static void eCall_IVS_ProcessFrame(void)
{
kal_uint32 proc_idx;
// Here we only do DL downsample, UL upsample
kal_uint32 dl_ds_inLen, dl_ds_outLen;
kal_uint32 ul_us_inLen, ul_us_outLen;
kal_uint16 *p_dl_ds_inBuf, *p_dl_ds_outBuf;
kal_uint16 *p_ul_us_inBuf, *p_ul_us_outBuf;
if (eCallModemIVS == NULL)
return;
proc_idx = eCallModemIVS->next_to_process;
switch (eCallModemIVS->mode) {
case Ivs:
if (eCallModemIVS->ivsPush == KAL_TRUE) {
IvsSendStart();
eCallModemIVS->ivsPush = KAL_FALSE;
}
/******************************************************
* dl_pcm_input -> dl_pcm_fifo -> dl_pcm_output *
* 32k 8k 32k *
* [BAUDOT] -> [ECALLLIB] *
******************************************************/
/* [ECALL blisrc] DL downsample start */
p_dl_ds_inBuf = eCallModemIVS->dl_pcm_input[proc_idx];
p_dl_ds_outBuf = eCallModemIVS->dl_pcm_fifo[proc_idx];
if(ECALL_WB_BUF_LEN == eCallModemIVS->dl_pcm_input_len[proc_idx]) {
dl_ds_inLen = ECALL_WB_BUF_LEN << 1;
dl_ds_outLen = ECALL_NB_BUF_LEN << 1;
BLI_Convert(eCallModemIVS->dl_downsample_16_8, (short *)p_dl_ds_inBuf, &dl_ds_inLen, (short *)p_dl_ds_outBuf, &dl_ds_outLen);
} else if(ECALL_SWB_BUF_LEN ==eCallModemIVS->dl_pcm_input_len[proc_idx]) {
dl_ds_inLen = ECALL_SWB_BUF_LEN << 1;
dl_ds_outLen = ECALL_NB_BUF_LEN << 1;
BLI_Convert(eCallModemIVS->dl_downsample_32_8, (short *)p_dl_ds_inBuf, &dl_ds_inLen, (short *)p_dl_ds_outBuf, &dl_ds_outLen);
} else{
memcpy(p_dl_ds_outBuf, p_dl_ds_inBuf, ECALL_NB_BUF_LEN << 1);
}
/* [ECALL blisrc] DL downsample end */
#if 1
{
IvsState preRxState = IvsRxGetState();
IvsState curState;
IvsProcess((Int16 *)eCallModemIVS->dl_pcm_fifo[proc_idx]);
curState = IvsTxGetState();
if ((curState == IvsTrigger) || (curState == IvsStart) || (curState == IvsSendMsd) || (preRxState != IvsIdle) || (IvsRxGetState() != IvsIdle)) {
memcpy(eCallModemIVS->ul_pcm_fifo[proc_idx], eCallModemIVS->dl_pcm_fifo[proc_idx], ECALL_NB_BUF_LEN*sizeof(kal_uint16));
/*****************************************************
* dl_pcm_output <- dl_pcm_fifo <- dl_pcm_input *
* 32k 8k 32k *
* [ECALLLIB] <- [BAUDOT] *
*****************************************************/
/* [ECALL blisrc] UL up sampling start */
//NB output
p_ul_us_inBuf = eCallModemIVS->ul_pcm_fifo[proc_idx];
p_ul_us_outBuf = eCallModemIVS->ul_pcm_output_nb[proc_idx];
memcpy(p_ul_us_outBuf, p_ul_us_inBuf, ECALL_NB_BUF_LEN << 1);
//WB output
ul_us_inLen = ECALL_NB_BUF_LEN << 1;
ul_us_outLen = ECALL_WB_BUF_LEN << 1;
p_ul_us_outBuf = eCallModemIVS->ul_pcm_output_wb[proc_idx];
BLI_Convert(eCallModemIVS->ul_upsample_8_16, (short *)p_ul_us_inBuf, &ul_us_inLen, (short *)p_ul_us_outBuf, &ul_us_outLen);
//SWB output
ul_us_inLen = ECALL_NB_BUF_LEN << 1;
ul_us_outLen = ECALL_SWB_BUF_LEN << 1;
p_ul_us_outBuf = eCallModemIVS->ul_pcm_output_swb[proc_idx];
BLI_Convert(eCallModemIVS->ul_upsample_8_32, (short *)p_ul_us_inBuf, &ul_us_inLen, (short *)p_ul_us_outBuf, &ul_us_outLen);
/* [ECALL blisrc] UL up sampling end */
eCallModemIVS->isUpdateUL[proc_idx] = KAL_TRUE;
MD_TRC_ECALL_IVS_PCM_UPDATE_UL(proc_idx, curState, proc_idx, eCallModemIVS->isUpdateUL[proc_idx]);
}
}
#else
/* under construction !*/
/* under construction !*/
/* under construction !*/
/* under construction !*/
/* under construction !*/
#endif
break;
case IvsRx:
if (eCallModemIVS->ivsPush == KAL_TRUE) {
IvsSendStart();
eCallModemIVS->ivsPush = KAL_FALSE;
}
/******************************************************
* dl_pcm_input -> dl_pcm_fifo -> dl_pcm_output *
* 32k 8k 32k *
* [BAUDOT] -> [ECALLLIB] *
******************************************************/
/* [ECALL blisrc] DL downsample start */
p_dl_ds_inBuf = eCallModemIVS->dl_pcm_input[proc_idx];
p_dl_ds_outBuf = eCallModemIVS->dl_pcm_fifo[proc_idx];
if(ECALL_WB_BUF_LEN == eCallModemIVS->dl_pcm_input_len[proc_idx]) {
dl_ds_inLen = ECALL_WB_BUF_LEN << 1;
dl_ds_outLen = ECALL_NB_BUF_LEN << 1;
BLI_Convert(eCallModemIVS->dl_downsample_16_8, (short *)p_dl_ds_inBuf, &dl_ds_inLen, (short *)p_dl_ds_outBuf, &dl_ds_outLen);
} else if(ECALL_SWB_BUF_LEN ==eCallModemIVS->dl_pcm_input_len[proc_idx]) {
dl_ds_inLen = ECALL_SWB_BUF_LEN << 1;
dl_ds_outLen = ECALL_NB_BUF_LEN << 1;
BLI_Convert(eCallModemIVS->dl_downsample_32_8, (short *)p_dl_ds_inBuf, &dl_ds_inLen, (short *)p_dl_ds_outBuf, &dl_ds_outLen);
} else{
memcpy(p_dl_ds_outBuf, p_dl_ds_inBuf, ECALL_NB_BUF_LEN << 1);
}
/* [ECALL blisrc] DL downsample end */
#if 1
{
IvsState preRxState = IvsRxGetState();
IvsState curState;
IvsProcess((Int16 *)eCallModemIVS->dl_pcm_fifo[proc_idx]);
curState = IvsTxGetState();
if ((curState == IvsTrigger) || (curState == IvsStart) || (curState == IvsSendMsd) || (preRxState != IvsIdle) || (IvsRxGetState() != IvsIdle)) {
memcpy(eCallModemIVS->ul_pcm_fifo[proc_idx], eCallModemIVS->dl_pcm_fifo[proc_idx], ECALL_NB_BUF_LEN*sizeof(kal_uint16));
/*****************************************************
* dl_pcm_output <- dl_pcm_fifo <- dl_pcm_input *
* 32k 8k 32k *
* [ECALLLIB] <- [BAUDOT] *
*****************************************************/
/* [ECALL blisrc] UL up sampling start */
//NB output
p_ul_us_inBuf = eCallModemIVS->ul_pcm_fifo[proc_idx];
p_ul_us_outBuf = eCallModemIVS->ul_pcm_output_nb[proc_idx];
memcpy(p_ul_us_outBuf, p_ul_us_inBuf, ECALL_NB_BUF_LEN << 1);
//WB output
ul_us_inLen = ECALL_NB_BUF_LEN << 1;
ul_us_outLen = ECALL_WB_BUF_LEN << 1;
p_ul_us_outBuf = eCallModemIVS->ul_pcm_output_wb[proc_idx];
BLI_Convert(eCallModemIVS->ul_upsample_8_16, (short *)p_ul_us_inBuf, &ul_us_inLen, (short *)p_ul_us_outBuf, &ul_us_outLen);
//SWB output
ul_us_inLen = ECALL_NB_BUF_LEN << 1;
ul_us_outLen = ECALL_SWB_BUF_LEN << 1;
p_ul_us_outBuf = eCallModemIVS->ul_pcm_output_swb[proc_idx];
BLI_Convert(eCallModemIVS->ul_upsample_8_32, (short *)p_ul_us_inBuf, &ul_us_inLen, (short *)p_ul_us_outBuf, &ul_us_outLen);
/* [ECALL blisrc] UL up sampling end */
eCallModemIVS->isUpdateUL[proc_idx] = KAL_TRUE;
MD_TRC_ECALL_IVS_PCM_UPDATE_UL(proc_idx, curState, proc_idx, eCallModemIVS->isUpdateUL[proc_idx]);
}
}
#else
/* under construction !*/
/* under construction !*/
/* under construction !*/
/* under construction !*/
#endif
break;
default:
ASSERT(0);
break;
}
}
static void eCall_IVS_ProcessTask(void *data)
{
kal_take_enh_mutex( eCall_mutex);
if (eCallModemIVS == NULL) {
kal_give_enh_mutex( eCall_mutex);
return;
}
if (eCallModemIVS->HRT_status_backup != 0)
{
MD_TRC_ECALL_IVS_HRT_STATUS(eCallModemIVS->HRT_status_backup);
}
while (eCallModemIVS->next_to_process != eCallModemIVS->pcm_fifo_write) {
// Process each frame
eCall_IVS_ProcessFrame();
// Update index
eCallModemIVS->next_to_process++;
if (eCallModemIVS->next_to_process == 2 * PCM_FIFO_LEN) {
eCallModemIVS->next_to_process = 0;
}
eCall_HRT_Clean();
}
kal_give_enh_mutex( eCall_mutex);
}
static void eCall_IVS_OnHandler( void *data )
{
(void)data;
if(spc_Get_Ecall_Lib_Status()==SPC_ECALL_ENABLE )
{
PCM4WAY_Start(eCall_IVS_hisr, 0);
}
else
{
PCM4WAY_Start(eCall_IVS_hisr, 4);
}
}
static void eCall_IVS_OffHandler( void *data )
{
(void)data;
PCM4WAY_Stop(0);
}
/*------------------------------------------------*/
/* The public functions of eCall modem driver. */
/*------------------------------------------------*/
eCall_Modem_Status eCall_IVS_Open(eCall_Callback handler)
{
ASSERT( handler != NULL );
MD_TRC_ECALL_IVS_DRV_OPEN(spc_Get_Ecall_Lib_Status());
if (eCallModemPSAP != NULL) {
return eCALL_OPERATION_FAIL;
}
if ( eCallModemIVS != NULL ) {
return eCALL_OPERATION_ALREADY_OPEN;
}
//L1SP_EnableSpeechEnhancement(KAL_FALSE);
//eCallModemIVS = (EcallShell *)audio_alloc_mem_cacheable( sizeof(EcallShell) );
eCallModemIVS = (EcallShell *)get_ctrl_buffer( sizeof(EcallShell) );
ASSERT( eCallModemIVS != NULL );
memset(eCallModemIVS, 0, sizeof(EcallShell));
// Allocate for IVS internal structure
{
kal_uint32 reqSize;
reqSize = (kal_uint32) IvsGetMemSize();
// eCallModemIVS->allocMem = (void *)audio_alloc_mem_cacheable( reqSize );
eCallModemIVS->allocMem = (void *)get_ctrl_buffer( reqSize );
memset(eCallModemIVS->allocMem, 0, sizeof(reqSize));
IvsInit( eCallModemIVS->allocMem );
if (eCallModemIVS->allocMem == NULL) {
MD_TRC_ECALL_IVS_DRV_ALLOCMEM_NULL();
}
}
// open BLI Src for ecall
// 32k <-> 8k
eCallModemIVS->dl_downsample_32_8 = BLI_Open(32000, 1, 8000, 1, (signed char*)eCallModemIVS->internal_buf_dl_in, 0); // open DL down sampling src
eCallModemIVS->ul_upsample_8_32 = BLI_Open(8000, 1, 32000, 1, (signed char*)eCallModemIVS->internal_buf_ul_out, 0); // open UL up sampling src
// 16k <-> 8k
eCallModemIVS->dl_downsample_16_8 = BLI_Open(16000, 1, 8000, 1, (signed char*)eCallModemIVS->internal_buf_dl_in2, 0); // open DL down sampling src
eCallModemIVS->ul_upsample_8_16 = BLI_Open(8000, 1, 16000, 1, (signed char*)eCallModemIVS->internal_buf_ul_out2, 0); // open UL up sampling src
eCallModemIVS->aud_id = L1Audio_GetAudioID();
L1Audio_SetEventHandler(eCallModemIVS->aud_id , eCall_IVS_ProcessTask);
L1Audio_SetFlag(eCallModemIVS->aud_id);
IvsRxReset();
eCallModemIVS->mode = IvsRx;
eCallModemIVS->pcm_fifo_read = 0;
eCallModemIVS->pcm_fifo_write = PCM_FIFO_LEN;
eCallModemIVS->next_to_process = PCM_FIFO_LEN;
eCallModemIVS->handler = handler;
for (int i=0; i<2*PCM_FIFO_LEN; i++) {
eCallModemIVS->isUpdateUL[i] = KAL_FALSE;
}
//Init eCall RX ctrl seq
memset(eCall_RX_CTRL_SEQ_State, 0, 800*sizeof(Int16));
memset(eCall_RX_CTRL_SEQ_dlData, 0, 800*sizeof(Int16));
memset(eCall_RX_CTRL_SEQ_dlMetric, 0, 800*sizeof(Int16));
eCall_RX_Ctrl_Index = 1;
eCall_RX_CTRL_SEQ_dlMetric[0] = 0xFF;
eCall_RX_CTRL_SEQ_State[0] = 0xDD;
eCall_RX_CTRL_SEQ_dlData[0] = 0xEE;
if(spc_Get_Ecall_Lib_Status()==SPC_ECALL_SDT_ONLY ){
Ivs_Set_Ecall_Lib_Status(Ivs_ECALL_SDT_ONLY);
}else if(spc_Get_Ecall_Lib_Status()==SPC_ECALL_ENABLE){
Ivs_Set_Ecall_Lib_Status(Ivs_ECALL_ENABLE);
}else {
return eCALL_OPERATION_FAIL;
}
if ( AM_IsSpeechOn() ) {
eCall_IVS_OnHandler( (void *)0 );
}
// Hook service to L1SP
L1SP_Register_Pcm4WayService( eCall_IVS_OnHandler, eCall_IVS_OffHandler );
return eCALL_OPERATION_SUCCESS;
}
eCall_Modem_Status eCall_IVS_Close(void)
{
MD_TRC_ECALL_IVS_DRV_CLOSE();
kal_take_enh_mutex( eCall_mutex);
if ( eCallModemIVS == NULL ) {
kal_give_enh_mutex( eCall_mutex);
return eCALL_OPERATION_ALREADY_CLOSE;
}
if (eCallModemPSAP != NULL) {
kal_give_enh_mutex( eCall_mutex);
return eCALL_OPERATION_FAIL;
}
if(spc_Get_Ecall_Lib_Status()==SPC_ECALL_DISABLE){
kal_give_enh_mutex( eCall_mutex);
return eCALL_OPERATION_FAIL;
}
// Unhook service to L1SP
L1SP_UnRegister_Pcm4Way_Service();
if ( AM_IsSpeechOn() ) {
eCall_IVS_OffHandler( (void *)0 );
}
L1Audio_ClearFlag(eCallModemIVS->aud_id);
L1Audio_FreeAudioID(eCallModemIVS->aud_id);
BLI_Close(eCallModemIVS->dl_downsample_16_8, 0); // Close DL down sampling src
BLI_Close(eCallModemIVS->dl_downsample_32_8, 0); // Close DL down sampling src
BLI_Close(eCallModemIVS->ul_upsample_8_16, 0); // Close UL up sampling src
BLI_Close(eCallModemIVS->ul_upsample_8_32, 0); // Close UL up sampling src
// Deallocate for IVS internal structure
{
IvsDeinit();
if (eCallModemIVS->allocMem == NULL) {
MD_TRC_ECALL_IVS_DRV_ALLOCMEM_NULL();
} else {
free_ctrl_buffer( (void *) eCallModemIVS->allocMem );
}
}
free_ctrl_buffer( (void *) eCallModemIVS );
//L1SP_EnableSpeechEnhancement(KAL_TRUE);
eCallModemIVS = NULL;
//transfer ctrl data to AP
spc_eCall_RX_CTRL_Data(0xDD);
spc_eCall_RX_CTRL_Data(0xEE);
spc_eCall_RX_CTRL_Data(0xFF);
kal_give_enh_mutex( eCall_mutex);
return eCALL_OPERATION_SUCCESS;
}
eCall_Modem_Status eCall_IVS_PutMSD(const kal_uint8 *pMSD, const kal_uint32 uLen, kal_uint8 from)
{
kal_uint8 i=0;
if (eCallModemPSAP != NULL) {
return eCALL_OPERATION_FAIL;
}
if ( eCallModemIVS == NULL ) {
return eCALL_OPERATION_FAIL;
}
if(spc_Get_Ecall_Lib_Status()==SPC_ECALL_SDT_ONLY)
{
return eCALL_OPERATION_STOP;
}
ASSERT( pMSD != NULL );
ASSERT( uLen <= ECALL_MSD_MAX_LENGTH);
memset(eCallModemIVS->NewMsd, 0, ECALL_MSD_MAX_LENGTH*sizeof(Ord8));
memcpy(eCallModemIVS->NewMsd, pMSD, uLen*sizeof(Ord8));
// for(i=0;i<140;i=i+7)
// {
// MD_TRC_ECALL_IVS_DRV_PUT_MSD(pMSD[i],pMSD[i+1],pMSD[i+2],pMSD[i+3],pMSD[i+4],pMSD[i+5],pMSD[i+6]);
// }
// Check status and copy to current MSD
//if ( IvsTxGetState() == IvsIdle ) {
memcpy(eCallModemIVS->CurMsd, eCallModemIVS->NewMsd, ECALL_MSD_MAX_LENGTH*sizeof(Ord8));
//}
for(i=0;i<140;i=i+7)
{
MD_TRC_ECALL_IVS_DRV_PUT_MSD(eCallModemIVS->CurMsd[i],eCallModemIVS->CurMsd[i+1],eCallModemIVS->CurMsd[i+2],eCallModemIVS->CurMsd[i+3],eCallModemIVS->CurMsd[i+4],eCallModemIVS->CurMsd[i+5],eCallModemIVS->CurMsd[i+6]);
}
// 0: Internal, 1:L5
if (from == 1) {
eCallModemIVS->msdSet = KAL_TRUE;
}
MD_TRC_ECALL_IVS_DRV_MSD_SET(from, eCallModemIVS->msdSet);
IvsTxReset(eCallModemIVS->CurMsd, ECALL_MSD_MAX_LENGTH);
return eCALL_OPERATION_SUCCESS;
}
eCall_Modem_Status eCall_IVS_SendStart(void)
{
MD_TRC_ECALL_IVS_DRV_SEND_START();
if (eCallModemPSAP != NULL) {
return eCALL_OPERATION_FAIL;
}
if ( eCallModemIVS == NULL ) {
return eCALL_OPERATION_FAIL;
}
// Check state
if ( IvsTxGetState() != IvsIdle ) {
return eCALL_OPERATION_DURING_TRANSMISSION;
}
if(spc_Get_Ecall_Lib_Status()==SPC_ECALL_DISABLE){
return eCALL_OPERATION_FAIL;
}
eCallModemIVS->TxRx = KAL_TRUE;
IvsRxReset();
if (eCallModemIVS->msdSet) {
eCallModemIVS->mode = Ivs;
}
eCallModemIVS->ivsPush = KAL_TRUE;
return eCALL_OPERATION_SUCCESS;
}
#if 1
/*------------------------------------------------*/
/* The unit test code for callback. */
/*------------------------------------------------*/
void IvsCatchEvent(IvsEvent ie)
{
ASSERT(eCallModemIVS);
MD_TRC_ECALL_IVS_DRV_CATCH_EVENT(ie);
/* custom event handlers to be implemented here... */
/* see modemx.h for a list of possible events (enum IvsEvent) */
switch (ie) {
case IVSEVENT_SENDINGMSD:
#if defined(__L5_SUPPORT__)
if (eCallModemIVS->msdSet) {
spc_L5ECALL_Status_Info_Callback(0xE1,0);
} else {
MD_TRC_ECALL_IVS_DRV_MSD_NOT_SET();
}
#else
spc_eCall_Handshake_Info_Notify(0xE1,0);
#endif
break;
case IVSEVENT_CONTROLLOCK:
eCallModemIVS->mode = Ivs;
eCallModemIVS->TxRx = KAL_TRUE;
eCallModemIVS->handler( eCALL_EVENT_RECV_START, NULL);
break;
case IVSEVENT_NACKRECEIVED:
eCallModemIVS->handler( eCALL_EVENT_RECV_NACK, NULL);
break;
case IVSEVENT_LLACKRECEIVED:
#if defined(__L5_SUPPORT__)
spc_L5ECALL_Status_Info_Callback(0xE2,0);
#else
spc_eCall_Handshake_Info_Notify(0xE2,0);
#endif
eCallModemIVS->handler( eCALL_EVENT_RECV_LL_ACK, NULL);
break;
case IVSEVENT_HLACKRECEIVED:
eCallModemIVS->mode = IvsRx;
break;
case IVSEVENT_RECEIVESTART:
#if defined(__L5_SUPPORT__)
spc_L5ECALL_Status_Info_Callback(0xE4,0);
#else
spc_eCall_Handshake_Info_Notify(0xE4,0);
#endif
break;
default:
break;
}
}
void IvsReceiveHlack(const Ord8 data)
{
MD_TRC_ECALL_IVS_DRV_HLACK((eCallModemIVS->CurMsd[0] & 0x0F), (data & 0x0F));
#if defined(__L5_SUPPORT__)
spc_L5ECALL_Status_Info_Callback(0xE3,data);
#else
spc_eCall_Handshake_Info_Notify(0xE3,data);
#endif
if ((eCallModemIVS->CurMsd[0] & 0x0F) == (data & 0x0F)) {
//eCallModemIVS->handler( eCALL_EVENT_RECV_HL_ACK_CORRECT, (void *)data); //NEED TO CHECK
} else {
//eCallModemIVS->handler( eCALL_EVENT_RECV_HL_ACK_MISMATCH, (void *)data);
}
IvsRxReset();
IvsTxReset(eCallModemIVS->CurMsd, ECALL_MSD_MAX_LENGTH);
eCallModemIVS->TxRx = KAL_FALSE;
}
void PsapCatchEvent(PsapEvent pe)
{
MD_TRC_ECALL_PSAP_DRV_CATCH_EVENT(pe);
switch (pe) {
/* custom event handlers to be implemented here... */
/* see modemx.h for a list of possible events (enum PsapEvent) */
case PSAPEVENT_CONTROLLOCK:
eCallModemPSAP->TxRx = KAL_TRUE;
break;
case PSAPEVENT_IDLEPOSTHLACK:
PsapReset();
eCallModemPSAP->frameStartHlackCur = 0;
eCallModemPSAP->msdReceived = KAL_FALSE;
eCallModemPSAP->ivsPush = KAL_TRUE;
eCallModemPSAP->TxRx = KAL_FALSE;
break;
default:
break;
}
}
#endif
#if defined(__ECALL_PSAP_SUPPORT__)
/*------------------------------------------------*/
/* The unit test code for PSAP. */
/*------------------------------------------------*/
void PsapReceiveMsd(const Ord8 *msd, int length) {
int n;
MD_TRC_ECALL_PSAP_DRV_RECEIVE_MSD();
for (n = 0; n < ECALL_MSD_MAX_LENGTH; n++) {
eCallModemPSAP->CurMsd[n] = msd[n];
}
eCallModemPSAP->msdReceived = KAL_TRUE;
for (n=0; n<20; n++) {
kal_uint32 base = 7*n;
MD_TRC_ECALL_PSAP_DRV_MSD_DATA(
msd[base], msd[base+1], msd[base+2], msd[base+3], msd[base+4], msd[base+5], msd[base+6]);
}
eCallModemPSAP->handler( eCALL_EVENT_PSAP_RECV_MSD, eCallModemPSAP->CurMsd);
}
//#pragma arm section code="SECONDARY_ROCODE"
static void eCall_PSAP_hisr(void)
{
kal_uint16 read_idx, write_idx;
read_idx = eCallModemPSAP->pcm_fifo_read;
write_idx = eCallModemPSAP->pcm_fifo_write;
if (eCallModemPSAP->pcm_fifo_read == eCallModemPSAP->next_to_process) {
// Processed data isn't enough
PCM4WAY_FillSE(0);
PCM4WAY_FillSpk(0);
} else {
// uplink-path
if (eCallModemPSAP->isUpdateUL[read_idx] == KAL_FALSE) {
PCM4WAY_PutToSE((const uint16*)(eCallModemPSAP->ul_pcm_input[read_idx]));
} else {
uint16 bufLen = SAL_PcmEx_GetBufLen(SAL_PCMEX_PNW_BUF_M2D_UL1);
if(ECALL_NB_BUF_LEN == bufLen) {
PCM4WAY_PutToSE((const uint16*)(eCallModemPSAP->ul_pcm_output_nb[read_idx]));
} else if(ECALL_WB_BUF_LEN == bufLen) {
PCM4WAY_PutToSE((const uint16*)(eCallModemPSAP->ul_pcm_output_wb[read_idx]));
} else {
PCM4WAY_PutToSE((const uint16*)(eCallModemPSAP->ul_pcm_output_swb[read_idx]));
}
eCallModemPSAP->isUpdateUL[read_idx] = KAL_FALSE;
MD_TRC_ECALL_PSAP_PCM_UPDATE_PUTTOSE(read_idx, bufLen);
}
// downlink-path no change
PCM4WAY_PutToSpk((const uint16*)(eCallModemPSAP->dl_pcm_input[read_idx]));
// Update index
eCallModemPSAP->pcm_fifo_write++;
if (eCallModemPSAP->pcm_fifo_write == 2*PCM_FIFO_LEN) {
eCallModemPSAP->pcm_fifo_write = 0;
}
}
if (read_idx != write_idx) {
// There is enough space to write data from microphone
eCallModemPSAP->ul_pcm_input_len[write_idx] = PCM4WAY_GetFromMic((uint16*)(eCallModemPSAP->ul_pcm_input[write_idx]));
eCallModemPSAP->dl_pcm_input_len[write_idx] = PCM4WAY_GetFromSD((uint16*)(eCallModemPSAP->dl_pcm_input[write_idx]));
MD_TRC_ECALL_PSAP_PCM_INPUT_LEN(write_idx, eCallModemPSAP->ul_pcm_input_len[write_idx], write_idx, eCallModemPSAP->dl_pcm_input_len);
// Update index
eCallModemPSAP->pcm_fifo_read++;
if (eCallModemPSAP->pcm_fifo_read == 2*PCM_FIFO_LEN) {
eCallModemPSAP->pcm_fifo_read = 0;
}
}
L1Audio_SetEvent(eCallModemPSAP->aud_id, (void*)0);
}
//#pragma arm section
static void eCall_PSAP_ProcessFrame(void)
{
kal_uint32 proc_idx = eCallModemPSAP->next_to_process;
// Here we only do DL downsample, UL upsample
kal_uint32 dl_ds_inLen, dl_ds_outLen;
kal_uint32 ul_us_inLen, ul_us_outLen;
kal_uint16 *p_dl_ds_inBuf, *p_dl_ds_outBuf;
kal_uint16 *p_ul_us_inBuf, *p_ul_us_outBuf;
switch (eCallModemPSAP->mode) {
case Psap:
if (eCallModemPSAP->ivsPush == KAL_FALSE) {
PsapSendStart();
eCallModemPSAP->ivsPush = KAL_TRUE;
}
if (eCallModemPSAP->msdReceived == KAL_TRUE) {
if ( ++eCallModemPSAP->frameStartHlackCur == eCallModemPSAP->frameStartHlack)
PsapSendHlack(eCallModemPSAP->CurMsd[0] & 0x0F);
}
/******************************************************
* dl_pcm_input -> dl_pcm_fifo -> dl_pcm_output *
* 32k 8k 32k *
* [BAUDOT] -> [ECALLLIB] *
******************************************************/
/* [ECALL blisrc] DL downsample start */
p_dl_ds_inBuf = eCallModemPSAP->dl_pcm_input[proc_idx];
p_dl_ds_outBuf = eCallModemPSAP->dl_pcm_fifo[proc_idx];
if(ECALL_WB_BUF_LEN == eCallModemPSAP->dl_pcm_input_len[proc_idx]) {
dl_ds_inLen = ECALL_WB_BUF_LEN << 1;
dl_ds_outLen = ECALL_NB_BUF_LEN << 1;
BLI_Convert(eCallModemPSAP->dl_downsample_16_8, (short *)p_dl_ds_inBuf, &dl_ds_inLen, (short *)p_dl_ds_outBuf, &dl_ds_outLen);
} else if(ECALL_SWB_BUF_LEN ==eCallModemPSAP->dl_pcm_input_len[proc_idx]) {
dl_ds_inLen = ECALL_SWB_BUF_LEN << 1;
dl_ds_outLen = ECALL_NB_BUF_LEN << 1;
BLI_Convert(eCallModemPSAP->dl_downsample_32_8, (short *)p_dl_ds_inBuf, &dl_ds_inLen, (short *)p_dl_ds_outBuf, &dl_ds_outLen);
} else{
memcpy(p_dl_ds_outBuf, p_dl_ds_inBuf, ECALL_NB_BUF_LEN << 1);
}
/* [ECALL blisrc] DL downsample end */
PsapProcess( (Int16 *)eCallModemPSAP->dl_pcm_fifo[proc_idx]);
if (eCallModemPSAP->TxRx) {
memcpy(eCallModemPSAP->ul_pcm_fifo[proc_idx], eCallModemPSAP->dl_pcm_fifo[proc_idx], ECALL_NB_BUF_LEN*sizeof(kal_uint16));
/*****************************************************
* dl_pcm_output <- dl_pcm_fifo <- dl_pcm_input *
* 32k 8k 32k *
* [ECALLLIB] <- [BAUDOT] *
*****************************************************/
/* [ECALL blisrc] UL up sampling start */
//NB output
p_ul_us_inBuf = eCallModemPSAP->ul_pcm_fifo[proc_idx];
p_ul_us_outBuf = eCallModemPSAP->ul_pcm_output_nb[proc_idx];
memcpy(p_ul_us_outBuf, p_ul_us_inBuf, ECALL_NB_BUF_LEN << 1);
//WB output
ul_us_inLen = ECALL_NB_BUF_LEN << 1;
ul_us_outLen = ECALL_WB_BUF_LEN << 1;
p_ul_us_outBuf = eCallModemPSAP->ul_pcm_output_wb[proc_idx];
BLI_Convert(eCallModemPSAP->ul_upsample_8_16, (short *)p_ul_us_inBuf, &ul_us_inLen, (short *)p_ul_us_outBuf, &ul_us_outLen);
//SWB output
ul_us_inLen = ECALL_NB_BUF_LEN << 1;
ul_us_outLen = ECALL_SWB_BUF_LEN << 1;
p_ul_us_outBuf = eCallModemPSAP->ul_pcm_output_swb[proc_idx];
BLI_Convert(eCallModemPSAP->ul_upsample_8_32, (short *)p_ul_us_inBuf, &ul_us_inLen, (short *)p_ul_us_outBuf, &ul_us_outLen);
/* [ECALL blisrc] UL up sampling end */
eCallModemPSAP->isUpdateUL[proc_idx] = KAL_TRUE;
MD_TRC_ECALL_PSAP_PCM_UPDATE_UL(proc_idx, eCallModemPSAP->TxRx, proc_idx, eCallModemPSAP->isUpdateUL[proc_idx]);
}
break;
case PsapRx:
if (eCallModemPSAP->ivsPush == KAL_FALSE) {
PsapSendStart();
eCallModemPSAP->ivsPush = KAL_TRUE;
}
if (eCallModemPSAP->msdReceived == KAL_TRUE) {
if ( ++eCallModemPSAP->frameStartHlackCur == eCallModemPSAP->frameStartHlack)
PsapSendHlack(eCallModemPSAP->CurMsd[0] & 0x0F);
}
/******************************************************
* dl_pcm_input -> dl_pcm_fifo -> dl_pcm_output *
* 32k 8k 32k *
* [BAUDOT] -> [ECALLLIB] *
******************************************************/
/* [ECALL blisrc] DL downsample start */
p_dl_ds_inBuf = eCallModemPSAP->dl_pcm_input[proc_idx];
p_dl_ds_outBuf = eCallModemPSAP->dl_pcm_fifo[proc_idx];
if(ECALL_WB_BUF_LEN == eCallModemPSAP->dl_pcm_input_len[proc_idx]) {
dl_ds_inLen = ECALL_WB_BUF_LEN << 1;
dl_ds_outLen = ECALL_NB_BUF_LEN << 1;
BLI_Convert(eCallModemPSAP->dl_downsample_16_8, (short *)p_dl_ds_inBuf, &dl_ds_inLen, (short *)p_dl_ds_outBuf, &dl_ds_outLen);
} else if(ECALL_SWB_BUF_LEN ==eCallModemPSAP->dl_pcm_input_len[proc_idx]) {
dl_ds_inLen = ECALL_SWB_BUF_LEN << 1;
dl_ds_outLen = ECALL_NB_BUF_LEN << 1;
BLI_Convert(eCallModemPSAP->dl_downsample_32_8, (short *)p_dl_ds_inBuf, &dl_ds_inLen, (short *)p_dl_ds_outBuf, &dl_ds_outLen);
} else{
memcpy(p_dl_ds_outBuf, p_dl_ds_inBuf, ECALL_NB_BUF_LEN << 1);
}
/* [ECALL blisrc] DL downsample end */
PsapRxProcess( (Int16 *)eCallModemPSAP->dl_pcm_fifo[proc_idx] );
if (eCallModemPSAP->TxRx) {
memcpy(eCallModemPSAP->ul_pcm_fifo[proc_idx], eCallModemPSAP->dl_pcm_fifo[proc_idx], ECALL_NB_BUF_LEN*sizeof(kal_uint16));
/*****************************************************
* dl_pcm_output <- dl_pcm_fifo <- dl_pcm_input *
* 32k 8k 32k *
* [ECALLLIB] <- [BAUDOT] *
*****************************************************/
/* [ECALL blisrc] UL up sampling start */
//NB output
p_ul_us_inBuf = eCallModemPSAP->ul_pcm_fifo[proc_idx];
p_ul_us_outBuf = eCallModemPSAP->ul_pcm_output_nb[proc_idx];
memcpy(p_ul_us_outBuf, p_ul_us_inBuf, ECALL_NB_BUF_LEN << 1);
//WB output
ul_us_inLen = ECALL_NB_BUF_LEN << 1;
ul_us_outLen = ECALL_WB_BUF_LEN << 1;
p_ul_us_outBuf = eCallModemPSAP->ul_pcm_output_wb[proc_idx];
BLI_Convert(eCallModemPSAP->ul_upsample_8_16, (short *)p_ul_us_inBuf, &ul_us_inLen, (short *)p_ul_us_outBuf, &ul_us_outLen);
//SWB output
ul_us_inLen = ECALL_NB_BUF_LEN << 1;
ul_us_outLen = ECALL_SWB_BUF_LEN << 1;
p_ul_us_outBuf = eCallModemPSAP->ul_pcm_output_swb[proc_idx];
BLI_Convert(eCallModemPSAP->ul_upsample_8_32, (short *)p_ul_us_inBuf, &ul_us_inLen, (short *)p_ul_us_outBuf, &ul_us_outLen);
/* [ECALL blisrc] UL up sampling end */
eCallModemPSAP->isUpdateUL[proc_idx] = KAL_TRUE;
MD_TRC_ECALL_PSAP_PCM_UPDATE_UL(proc_idx, eCallModemPSAP->TxRx, proc_idx, eCallModemPSAP->isUpdateUL[proc_idx]);
}
break;
default:
ASSERT(0);
break;
}
}
static void eCall_PSAP_ProcessTask(void *data)
{
if (eCallModemPSAP == NULL) {
return;
}
while (eCallModemPSAP->next_to_process != eCallModemPSAP->pcm_fifo_write) {
// Process each frame
eCall_PSAP_ProcessFrame();
// Update index
eCallModemPSAP->next_to_process++;
if (eCallModemPSAP->next_to_process == 2 * PCM_FIFO_LEN) {
eCallModemPSAP->next_to_process = 0;
}
}
}
static void eCall_PSAP_OnHandler( void *data )
{
(void)data;
PCM4WAY_Start(eCall_PSAP_hisr, 0);
}
static void eCall_PSAP_OffHandler( void *data )
{
(void)data;
PCM4WAY_Stop(0);
}
eCall_Modem_Status eCall_PSAP_Open(eCall_Callback handler)
{
ASSERT( handler != NULL );
if ( eCallModemIVS != NULL ) {
return eCALL_OPERATION_FAIL;
}
if ( eCallModemPSAP != NULL ) {
return eCALL_OPERATION_ALREADY_OPEN;
}
//L1SP_EnableSpeechEnhancement(KAL_FALSE);
//eCallModemPSAP = (EcallShell *)audio_alloc_mem_cacheable( sizeof(EcallShell) );
eCallModemPSAP = (EcallShell *)get_ctrl_buffer( sizeof(EcallShell) );
ASSERT( eCallModemPSAP != NULL );
memset(eCallModemPSAP, 0, sizeof(EcallShell));
// Allocate for PSAP internal structure
{
kal_uint32 reqSize;
reqSize = (kal_uint32) PsapGetMemSize();
//eCallModemPSAP->allocMem = (void *)audio_alloc_mem_cacheable( reqSize );
eCallModemPSAP->allocMem = (void *)get_ctrl_buffer( reqSize );
memset(eCallModemPSAP->allocMem, 0, sizeof(reqSize));
PsapInit( eCallModemPSAP->allocMem );
}
// open BLI Src for ecall
// 32k <-> 8k
eCallModemPSAP->dl_downsample_32_8 = BLI_Open(32000, 1, 8000, 1, (signed char*)eCallModemPSAP->internal_buf_dl_in, 0); // open DL down sampling src
eCallModemPSAP->ul_upsample_8_32 = BLI_Open(8000, 1, 32000, 1, (signed char*)eCallModemPSAP->internal_buf_ul_out, 0); // open UL up sampling src
// 16k <-> 8k
eCallModemPSAP->dl_downsample_16_8 = BLI_Open(16000, 1, 8000, 1, (signed char*)eCallModemPSAP->internal_buf_dl_in2, 0); // open DL down sampling src
eCallModemPSAP->ul_upsample_8_16 = BLI_Open(8000, 1, 16000, 1, (signed char*)eCallModemPSAP->internal_buf_ul_out2, 0); // open UL up sampling src
eCallModemPSAP->aud_id = L1Audio_GetAudioID();
L1Audio_SetEventHandler(eCallModemPSAP->aud_id , eCall_PSAP_ProcessTask);
L1Audio_SetFlag(eCallModemPSAP->aud_id);
PsapReset();
eCallModemPSAP->mode = Psap; //PsapRx;
eCallModemPSAP->ivsPush = KAL_TRUE; //KAL_FALSE;
eCallModemPSAP->msdReceived = KAL_FALSE;
eCallModemPSAP->frameStartHlack = 10;
eCallModemPSAP->pcm_fifo_read = 0;
eCallModemPSAP->pcm_fifo_write = PCM_FIFO_LEN;
eCallModemPSAP->next_to_process = PCM_FIFO_LEN;
eCallModemPSAP->frameStartHlackCur = 0;
eCallModemPSAP->handler = handler;
for (int i=0; i<2*PCM_FIFO_LEN; i++) {
eCallModemPSAP->isUpdateUL[i] = KAL_FALSE;
}
if ( AM_IsSpeechOn() ) {
eCall_PSAP_OnHandler( (void *)0 );
}
// Hook service to L1SP
L1SP_Register_Pcm4WayService( eCall_PSAP_OnHandler, eCall_PSAP_OffHandler );
return eCALL_OPERATION_SUCCESS;
}
eCall_Modem_Status eCall_PSAP_Close(void)
{
if( eCallModemPSAP == NULL ) {
return eCALL_OPERATION_ALREADY_CLOSE;
}
if ( eCallModemIVS != NULL ) {
return eCALL_OPERATION_FAIL;
}
// Unhook service to L1SP
L1SP_UnRegister_Pcm4Way_Service();
if ( AM_IsSpeechOn() ) {
eCall_PSAP_OffHandler( (void *)0 );
}
L1Audio_ClearFlag(eCallModemPSAP->aud_id);
L1Audio_FreeAudioID(eCallModemPSAP->aud_id);
BLI_Close(eCallModemPSAP->dl_downsample_16_8, 0); // Close DL down sampling src
BLI_Close(eCallModemPSAP->dl_downsample_32_8, 0); // Close DL down sampling src
BLI_Close(eCallModemPSAP->ul_upsample_8_16, 0); // Close UL up sampling src
BLI_Close(eCallModemPSAP->ul_upsample_8_32, 0); // Close UL up sampling src
// Deallocate for PSAP internal structure
{
PsapDeinit();
free_ctrl_buffer( (void *) eCallModemPSAP->allocMem );
}
free_ctrl_buffer( (void *) eCallModemPSAP );
//L1SP_EnableSpeechEnhancement(KAL_TRUE);
eCallModemPSAP = NULL;
return eCALL_OPERATION_SUCCESS;
}
eCall_Modem_Status eCall_PSAP_SendStart(void)
{
if (eCallModemPSAP == NULL) {
return eCALL_OPERATION_FAIL;
}
if ( eCallModemIVS != NULL ) {
return eCALL_OPERATION_FAIL;
}
eCallModemPSAP->TxRx = KAL_TRUE;
eCallModemPSAP->mode = Psap;
eCallModemPSAP->ivsPush = KAL_FALSE;
return eCALL_OPERATION_SUCCESS;
}
#else
// Provide dummy function to support feature switchable
void PsapReceiveMsd(const Ord8 *msd, int length) { }
eCall_Modem_Status eCall_PSAP_Open(eCall_Callback handler) {return eCALL_OPERATION_FAIL;}
eCall_Modem_Status eCall_PSAP_Close(void) {return eCALL_OPERATION_FAIL;}
eCall_Modem_Status eCall_PSAP_SendStart(void) {return eCALL_OPERATION_FAIL;}
#endif