[Feature]Upload Modem source code
Change-Id: Id4294f30faced84d3e6fd6d5e61e1111bf287a37
diff --git a/mcu/driver/audio/src/v1/eCall_drv.c b/mcu/driver/audio/src/v1/eCall_drv.c
new file mode 100644
index 0000000..787dfda
--- /dev/null
+++ b/mcu/driver/audio/src/v1/eCall_drv.c
@@ -0,0 +1,1312 @@
+/*****************************************************************************
+* 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