blob: 44196c3cefb8b8a1c9a7ea38e7fccd4872b819f4 [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) 2005
*
* 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:
* ---------
* sp_3g.c
*
* Project:
* --------
* Maui
*
* Description:
* ------------
* 3G speech interface
*
* Author:
* -------
* -------
*
*------------------------------------------------------------------------------
* 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!
*
* 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!
*
* 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!
* 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!
* 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!
*
*
*******************************************************************************/
//#define TK6291_FAKE_COMPILE
#include "kal_public_api.h"
#include "kal_general_types.h"
#include "sync_data.h"
//#include "string.h"
#include "kal_trace.h"
#include "reg_base.h"
//MPD
//#include "l4_ps_api.h"
#include "ps_em_exported_enum.h"
//#include "l4_ps_api_public.h"
extern ps_conf_test_mode_enum query_ps_conf_test_mode(void);
//#include "speech_def.h"
#include "audio_dsp_d2c_def.h"
#include "l1aud_common_def.h"
#include "l1audio.h"
//#ifndef TK6291_FAKE_COMPILE
//#include "uas_export_api.h"
#include "csr_export_api.h"
//#endif //#ifndef TK6291_FAKE_COMPILE
#include "am.h"
#include "l1audio_trace_utmd.h"
#include "media.h"
#include "l1sp_trc.h"
#include "amr_table.h"
#include "sal_exp.h"
#include "sal_def.h"
#include "sp_enhance.h"
#include "sp_cc.h"
#if defined(__VOLTE_SUPPORT__)
#include "sp_ps.h"
#endif
#ifdef __VIDEO_CALL_SUPPORT__
extern void vt_SP3G_Callback( kal_uint8 event, void *data );
#endif
extern const kal_uint16* tblAMR_WBOrder[9];
#define __DLDCH_DELAY_IMPROVE__
#if defined(__DLDCH_DELAY_IMPROVE__)
#define __SP3G_UL_DSP_RESYNC_CSR__
#define __SP3G_DIRECT_TO_DSP__
#define ust_get_duration_true(prev, cur) (((cur) >= (prev))? (((cur) - (prev))): ((USCNT_WRAP - (prev) + (cur))))
#endif
#if defined(__SP3G_UL_DSP_RESYNC_CSR__)
#include "us_timer.h"
#define MINIMUM_DELAY_READ_THRESHOLD 14
#endif
extern kal_enhmutexid sp_handover_mutex;//sp_4g.c
#if defined( __UMTS_RAT__ )
#define _EXTRA_LOG_FOR_BIT_TRUE_
#if defined(_EXTRA_LOG_FOR_BIT_TRUE_)
kal_bool CS_NeedSpeechExtraLog( void );
kal_bool g_bNeedExtraLog;
#endif
extern void L1SP_3G_Request(void);
kal_uint32 SP4G_GetCodecMode(void);
#define AMR_SID_FRAME 8
#define AMR_NO_DATA 15
#define AWB_SID_FRAME 9
#define WB_AMR_SID_FRAME 25
#define UL_HARD_REAL_TIME_DEMAND
#define UL_MAX_DATA_SIZE 62 // frame_type, UL : len / DL : FQI_flag , DATA(23.85=>60)
#define DL_MAX_DATA_SIZE 66 // frame_type, UL : len / DL : FQI_flag , CFN(4 bytes), DATA(23.85=>60)
#define MAX_DSP_FRAME_LEN 30
#define MAXIMUM_UL_DELAY 15 // CSR define for debug
#define START_SHRINK_UL_DELAY 10 // L1Audio shrink UL delay from 40ms to 20ms
#define HARD_REAL_TIME_UL_BUFFER_NUM 1 // could not revise
#define RAT_3G_UL_BUFFER_NUM 2 // could not revise
#if defined(__SP3G_UL_DSP_RESYNC_CSR__)
#define RAT_3G_DL_BUFFER_NUM 1 // do not suggest to revise
#define RAT_3G_DL_BUFFER_NUM_BEFORE_RESYNC 2 // do not suggest to revise
#else
#define RAT_3G_DL_BUFFER_NUM 2 // do not suggest to revise
#define RAT_3G_DL_BUFFER_NUM_BEFORE_RESYNC 2 // do not suggest to revise
#endif
#ifdef __VIDEO_CALL_SUPPORT__
#define MAX_3G_UL_BUFFER_NUM 5
#define MAX_3G_DL_BUFFER_NUM 20
#elif defined(__CSHSPA_SUPPORT__)
#define MAX_3G_UL_BUFFER_NUM 2
//In theory, Max CS delay is 200ms at most, which is 10 frames
#define MAX_3G_DL_BUFFER_NUM 10
#else
#define MAX_3G_UL_BUFFER_NUM RAT_3G_UL_BUFFER_NUM
#define MAX_3G_DL_BUFFER_NUM RAT_3G_DL_BUFFER_NUM_BEFORE_RESYNC
#endif
#define __SP3G_DL_BUFFER_BEFORE_PLAY__
/* Enable more buffering before put frame to DSP to keep start of speech smooth.
If not defined this compile option, it can reduce delay but maybe can't cover the initial discontinous.
*/
// here should be careful for this will limit MAX_DL_BUFFER_NUM to 1 << DL_BUF_INDEX_BIT_NUM
// and MAX_UL_BUFFER_NUM to 1 << UL_BUF_INDEX_BIT_NUM
#define DL_BUF_INDEX_BIT_NUM 5
#define UL_BUF_INDEX_BIT_NUM (8 - DL_BUF_INDEX_BIT_NUM)
#define SP3G324M_DL_EXTRA_LEN 5//frameType(1), len(1), l1_frame : recieve(3)
#define SP3G_DL_EXTRA_LEN 6//frameType(1), FQI_flag(1), CFN(4)(unit:byte)
//AMRWB 23.85 classB 405 bits=>51 bytes
#define MAX_BYTES_IN_SINGLE_SUBFLOW ((405 + 7)>>3)
#define _IGNORE_TYPE_ERROR_ // for 3G324M since the CRC is weaker, it's possible wrong pattern.
// so ignore it instead of assert.
typedef struct
{
uint16 dsp_buffer[MAX_DSP_FRAME_LEN];
uint16 dsp_buffer_dl[MAX_DSP_FRAME_LEN];
uint8 dl_buffer[MAX_3G_DL_BUFFER_NUM][DL_MAX_DATA_SIZE];
#if defined(_EXTRA_LOG_FOR_BIT_TRUE_)
uint8 dl_buffer2[MAX_3G_DL_BUFFER_NUM][DL_MAX_DATA_SIZE];
#endif
/*0: CFN, 1:RSSI|RSCP|ECIO|HHO_SHO ,2:crc_result ,3:s_value[0], 4:tpc_SIR_lta, 5:dpdch_SIR_lta, 6:TFCI_max_corr */
uint32 L1_Info[4][7];
#if defined(__SP3G_UL_DSP_RESYNC_CSR__)
uint32 int_time[5];//0: UL, 1: DL, 2: temp UL, 3: DSP UL time, 4: send DSP resync time
bool ul_request_resync;
uint8 uDelW;
#endif
uint8 ul_buffer[MAX_3G_UL_BUFFER_NUM][UL_MAX_DATA_SIZE]; // prevent sp3g_hisr , CSR race condition
uint8 ul_write_idx;
uint8 ul_read_idx;
uint8 ul_count;
bool is_getting_ul_data;
uint8 ul_delay;
uint8 dl_count;
uint8 dl_write_idx;
uint8 dl_read_idx;
bool under_interact;
uint8 ul_codec_mode;
uint8 ul_report;
uint8 dl_report;
uint8 pre_ul_report;
uint8 pre_dl_report;
bool waiting; // 1-message-1-get policy
bool ul_refresh; // detect change codec_mode
uint8 l1_info_idx;
uint8 sp3g_mode;
uint8 ul_buffer_size;
uint8 dl_buffer_size;
uint8 dtx_state; //enter dtx mode
uint8 dtx_force; //occured that force AMR frame
#if defined(__CSHSPA_SUPPORT__)
uint8 dl_subflow[MAX_BYTES_IN_SINGLE_SUBFLOW];
#endif
}SP3G_Struct;
static SP3G_Struct sp3gInfo;
SP3G_Struct *sp3g;
kal_spinlockid sp3g_spinlockID;
static kal_uint32 sp3g_rab_id;
static kal_bool sp3g_rab_state;
static kal_bool sp3g_is_csr_ready;
static kal_uint32 l1AInfo;
static kal_uint8 sp3g_reset_flag; // speech on and InterRAT : set TRUE
static kal_bool sp3g_dtx_mode;
#if defined(__CSHSPA_SUPPORT__)
static kal_uint8 sp3g_max_cs_delay;
#endif
#define INIT_3G_CODEC (0xA) //// 4.75 NB AMR
const uint16 RAB_subflow[][4] = {
{42, 53, 0, 13}, // 4.75
{49, 54, 0, 14}, // 5.15
{55, 63, 0, 15}, // 5.9
{58, 76, 0, 18}, // 6.7
{61, 87, 0, 19}, // 7.4
{75, 84, 0, 21}, // 7.95
{65, 99, 40, 27}, // 10.2
{81, 103,60, 32}, // 12.2
{39, 0, 0, 5}, // SID
{39, 0, 0, 5}, // dummy
{39, 0, 0, 5}, // dummy
{39, 0, 0, 5}, // dummy
{39, 0, 0, 5}, // dummy
{39, 0, 0, 5}, // dummy
{39, 0, 0, 5}, // For Future use
{8, 0, 0, 0}, // AMR NoData
/* TS26.201, Table 7 */
{54, 78, 0, 17},/* WB type 0, AMR-WB 6.60 */
{64, 113, 0, 23},/* WB type 1, AMR-WB 8.85 */
{72, 181, 0, 32},/* WB type 2, AMR-WB 12.65 */
{72, 213, 0, 36},/* WB type 3, AMR-WB 14.25 */
{72, 245, 0, 40},/* WB type 4, AMR-WB 15.85 */
{72, 293, 0, 46},/* WB type 5, AMR-WB 18.25 */
{72, 325, 0, 50},/* WB type 6, AMR-WB 19.85 */
{72, 389, 0, 58},/* WB type 7, AMR-WB 23.05 */
{72, 405, 0, 60},/* WB type 8, AMR-WB 23.85 */
{40, 0, 0, 5}/* WB type 9, AMR-WB SID */
/* WB type 10-13, Not Used */
};
const uint8 RAB_Order[8] = {
0x80,0x40,0x20,0x10,0x08,0x04,0x02,0x01 /* bits order of AMR frame */
};
const uint16 DSP_Order[16] = {
0x0001,0x0002,0x0004,0x0008,0x0010,0x0020,0x0040,0x0080, /* bits order of SHERIF */
0x0100,0x0200,0x0400,0x0800,0x1000,0x2000,0x4000,0x8000
};
#ifdef __VIDEO_CALL_SUPPORT__
const uint8 AMR_IF2_Order[8] = {
0x10,0x20,0x40,0x80,0x01,0x02,0x04,0x08 /* bits order of AMR IF2 frame */
};
const uint8 AMR_IF2_FRAME_LENGTH[16] = {/* byte length of AMR IF2 frame */
13, 14, 16, 18, 19, 21, 26, 31, 6,
0 , 0, 0, 0, 0, 0, 1
};
#endif
const uint8 AmrFrameType2DspMode[25] = {0x0A, 0x09, 0x08, 0x07, 0x06,
0x05, 0x04, 0x03, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x20, 0x21, 0x22, 0x23,
0x24, 0x25, 0x26, 0x27, 0x28};
//** From {0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x00};
//** mapping to
const uint8 NB_DspMode2AmrFrameType[17] = {0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00};
//** From {0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28};
//** mapping to
const uint8 WB_DspMode2AmrFrameType[17] = {0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18};
//** From {0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x00};
//** mapping to
const uint8 NB_DspModeLen[17] = {0x10, 0x0D, 0x0A, 0x0A, 0x09, 0x08, 0x07, 0x06};
//** From {0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28};
//** mapping to
const uint8 WB_DspModeLen[17] = {0x09, 0x0C, 0x10, 0x12, 0x14, 0x17, 0x19, 0x1D, 0x1E};
#define GetFrameType2DspMode(ftype) (AmrFrameType2DspMode[(ftype)])
#define GetDspMode2FrameType(mode) (((0x20 <= (mode)) && ((mode) <= 0x28)) ? (WB_DspMode2AmrFrameType[(mode)-0x20]) : \
(((0x03 <= (mode)) && ((mode) <= 0x0A)) ? (NB_DspMode2AmrFrameType[(mode)-0x03]) : (-1)))
#define GetDspModeLen(mode) (((0x20 <= (mode)) && ((mode) <= 0x28)) ? (WB_DspModeLen[(mode)-0x20]) : \
(((0x03 <= (mode)) && ((mode) <= 0x0A)) ? (NB_DspModeLen[(mode)-0x03]) : (0x00)))
#define GetRab2DspMapping(ftype) (((0x10 <= (ftype)) && ((ftype) <= 0x18)) ? (tblAMR_WBOrder[(ftype) - 0x10]) : \
(((0x00 <= (ftype)) && ((ftype) <= 0x07)) ? (tblAMROrder[(ftype)-0x00]) : (0)))
extern const uint8* tblAMROrder[8];
#define AMR_DATA_LOG
#ifdef __FAKE_3G_LOOPBACK__
void fake_CSR_Speech_Callback(SP3G_Event event, void *data){}
#endif
#if defined(__L1_STANDALONE__)
void CSR_SP3G_Callback( SP3G_Event event, void *data){}
void CSR_SP4G_Callback( SP4G_Event event, void *data ){}
#else
fp_CSR_SP3G_Callback CSR_SP3G_Callback;
extern void CSR_SP4G_Callback( SP4G_Event event, void *data );
#endif
extern uint32 L1I_GetTimeStamp( void );
#if defined(_EXTRA_LOG_FOR_BIT_TRUE_)
kal_bool CS_NeedSpeechExtraLog( void )
{
return g_bNeedExtraLog;
}
#endif
extern void sp3g_vmRecordService( uint32 *l1_info, uint16 crc_result, uint16 buf_status, uint16 *ul_frame_data, uint16* dl_frame_data, kal_bool bBufferOK);
/* SP3G_UpdateL1InFo */
/* called by L1A to update DCH on/off and TX in/off(DCH UL on/off) */
/* bit 0: DCH on/off (1: on, 0: off) */
/* bit 1: DCH UL on/off (1: on, 0: off) */
/* bit 2: indicate RLF status (1: indicate RLF, 0: reset RLF) */
/* bit 3: 3 bits to indicate DCH setup type */
void SP3G_UpdateL1AInFo_P( kal_uint8 bitmap, kal_uint8 value )
{
ASSERT( bitmap <= 3 );
MD_TRC_SP3G_L1A_UPDATE_INFO(bitmap, value);
kal_take_enh_mutex( sp_handover_mutex );
if( bitmap == 3 ){
l1AInfo |= (value << 3);
} else {
if( value > 0 )
l1AInfo |= (1 << bitmap);
else
l1AInfo &= ~(1 << bitmap);
}
kal_give_enh_mutex( sp_handover_mutex );
}
extern kal_enhmutexid sp_mutex;
//CSR inform RAB is established, the rab_id should be set as parameter when callback to CSR
void CSR_Codec_Ready(int rab_id)
{
if(!sp3g_is_csr_ready && NULL != CSR_SP3G_Callback){
MD_TRC_SP3G_CODEC_READY_OK(rab_id);
CSR_SP3G_Callback(SP3G_CODEC_READY, (void*)rab_id ); // It means that l1sp_speechon is not invoked and callback will be replied until l1sp_speechon is triggered.
sp3g_is_csr_ready = true;
}else{
MD_TRC_SP3G_CODEC_READY_SKIP(rab_id, sp3g_is_csr_ready, (NULL==CSR_SP3G_Callback));
}
}
void CSR_Codec_Close(int rab_id)
{
if(sp3g_is_csr_ready && NULL != CSR_SP3G_Callback){
MD_TRC_SP3G_CODEC_CLOSE_OK(rab_id);
CSR_SP3G_Callback(SP3G_CODEC_CLOSED, (void*)rab_id );
sp3g_is_csr_ready = false;
}else{
MD_TRC_SP3G_CODEC_CLOSE_SKIP(rab_id, sp3g_is_csr_ready, (NULL==CSR_SP3G_Callback));
}
}
void SP3G_Rab_Est_sub()
{
CSR_Codec_Ready(sp3g_rab_id);
SP3G_Reset();
AM_InterRAT_2G_to_3G(sp3g->ul_codec_mode);
L1SP_SetState( L1SP_STATE_3G_SPEECH_ON );
}
#ifdef __FAKE_3G_LOOPBACK__
extern kal_uint32 get_is_fake_3g(void);
#endif
void SP3G_Rab_Est( uint32 rab_id, kal_uint8 default_speech_codec )
{
#ifdef __FAKE_3G_LOOPBACK__
if(get_is_fake_3g()){
uint32 codec;
kal_prompt_trace(MOD_L1SP, "[SP3G]SP3G_Rab_Est %d %d", rab_id, default_speech_codec);
codec = AmrFrameType2DspMode[default_speech_codec];
sp3g->ul_codec_mode = codec;
}
#endif
sp3g_rab_id = rab_id;
sp3g_rab_state = KAL_TRUE;
//sp3g_codec_mode = default_speech_codec;
MD_TRC_SP3G_RAB_EST_0(L1SP_GetState());
#if defined(_MODEM_RESYNC_3G_)
MD_TRC_L1Audio_Msg_AM_3G_Reset_Time_Drift();
#if defined( __UMTS_RAT__ )
switch(L1SP_GetSIMStatus()){
case SP_3G_SIM_FDD_ACTIVE:
#if defined(__UMTS_FDD_MODE__)
UL1D_Speech_Resync_Reset_Time_Offset();
#endif
break;
case SP_3G_SIM_TDD_ACTIVE:
#if defined( __UMTS_TDD128_MODE__ )
TL1C_Reset_Time_Drift();
#endif
break;
default:
ASSERT(0);
}
#endif
#endif
#if defined( __UMTS_RAT__ ) && !defined(__L1_STANDALONE__)
switch(L1SP_GetSIMStatus()){
case SP_3G_SIM_FDD_ACTIVE:
if(query_ps_conf_test_mode()==PS_CONF_TEST_FTA)
SP3G_SetDTX(false);
else
SP3G_SetDTX(true);
break;
case SP_3G_SIM_TDD_ACTIVE:
break;
default:
ASSERT(0);
}
#endif
kal_take_enh_mutex( sp_handover_mutex );
MD_TRC_SP3G_RAB_EST();
//CSR_SP3G_Callback(SP3G_CODEC_READY, (void*)sp3g_rab_id );
SAL_Set_LinkStatus(SAL_LINKSTATUS_3G , true);
CSR_Codec_Ready(sp3g_rab_id);
#if defined(__C2K_SPEECH_SUPPORT__)
if( L1SP_GetState() == L1SP_STATE_C2K_SPEECH_ON ){//
//PSR_C2K_Callback(C2K_CODEC_READY, (void*)0 );
//C2k_Reset();
AM_InterRAT_C2K_to_3G(sp3g->ul_codec_mode);
L1SP_SetState( L1SP_STATE_3G_SPEECH_ON );
}else
#endif
#if defined(__VOLTE_SUPPORT__)
if( L1SP_GetState() == L1SP_STATE_4G_SPEECH_ON ){//
PSR_SP4G_Callback(SP4G_CODEC_CLOSED, (void*)0 );
SP3G_Reset();
AM_InterRAT_4G_to_3G(sp3g->ul_codec_mode);
L1SP_SetState( L1SP_STATE_3G_SPEECH_ON );
}else
#endif
if( L1SP_GetState() == L1SP_STATE_2G_SPEECH_ON ){//prepare InterRAT HO
SP3G_Reset();
AM_InterRAT_2G_to_3G(sp3g->ul_codec_mode);
L1SP_SetState( L1SP_STATE_3G_SPEECH_ON );
}
kal_give_enh_mutex( sp_handover_mutex );
}
void SP3G_Rab_Deest( void )
{
sp3g_rab_state = KAL_FALSE;
MD_TRC_SP3G_RAB_DEEST_0(L1SP_GetState());
kal_take_enh_mutex( sp_handover_mutex );
MD_TRC_SP3G_RAB_DEEST();
//CSR_SP3G_Callback(SP3G_CODEC_CLOSED, (void*)sp3g_rab_id );
SAL_Set_LinkStatus(SAL_LINKSTATUS_3G , false);
CSR_Codec_Close(sp3g_rab_id);
#if defined(__C2K_SPEECH_SUPPORT__)
if( L1SP_isC2KSO_Connected() && L1SP_GetState() != L1SP_STATE_C2K_SPEECH_ON && L1SP_GetState() != L1SP_STATE_IDLE ){//3G->4G
//PSR_C2K_Callback(C2K_CODEC_READY, (void*)0 );
//C2k_Reset();
AM_InterRAT_3G_to_C2K(L1SP_GetC2KSO_Codec());
L1SP_SetState( L1SP_STATE_C2K_SPEECH_ON );
}else
#endif
#if defined(__VOLTE_SUPPORT__)
if( SP4G_Rab_State() && L1SP_GetState() != L1SP_STATE_4G_SPEECH_ON && L1SP_GetState() != L1SP_STATE_IDLE ){//3G->4G
PSR_SP4G_Callback(SP4G_CODEC_READY, (void*)0 );
SP4G_Reset();
AM_InterRAT_3G_to_4G(SP4G_GetCodecMode());
L1SP_SetState( L1SP_STATE_4G_SPEECH_ON );
}else
#endif
if( L1SP_TCH_State() && L1SP_GetState() != L1SP_STATE_2G_SPEECH_ON && L1SP_GetState() != L1SP_STATE_IDLE ){//2G->3G fail case
AM_InterRAT_3G_to_2G();
L1SP_SetState( L1SP_STATE_2G_SPEECH_ON );
}
kal_give_enh_mutex( sp_handover_mutex );
}
kal_bool SP3G_Rab_State( void )
{
return sp3g_rab_state;
}
kal_uint32 SP3G_Rab_Id( void )
{
return sp3g_rab_id;
}
void SP3G_GetSyncDelayRW( kal_uint16 *u16DelayR, kal_uint16 *u16DelayW, kal_uint16 *u16DelayM, kal_uint32 *u32CurTime64us)
{
kal_uint16 msDelayR, msDelayW;
kal_uint32 cur_time, delay, idx;
kal_uint32 MODE_3G;
#if defined( __UMTS_RAT__ )
if(!SP3G_Rab_State()){
MODE_3G = SAL_DEALY_3G_FDD;
} else {
switch(L1SP_GetSIMStatus()){
case SP_3G_SIM_FDD_ACTIVE:
#if defined(__UMTS_FDD_MODE__)
MODE_3G = SAL_DEALY_3G_FDD;
#endif
break;
case SP_3G_SIM_TDD_ACTIVE:
#if defined( __UMTS_TDD128_MODE__ )
MODE_3G = SAL_DEALY_3G_TDD;
#endif
break;
default:
ASSERT(0);
}
}
#endif
*u32CurTime64us = fma_get_glb_ts();
cur_time = ust_get_current_time();
sp3g->int_time[4] = cur_time;
MD_TRC_L1Audio_Msg_SP3G_GetSyncDelayRW( sp3g->ul_codec_mode );
if( sp3g_reset_flag == 2 ){
idx = ( ( ust_us_duration( sp3g->int_time[0], sp3g->int_time[1] ) ) / 1000 ) % 20;
SAL_Get_Delay(MODE_3G, 0, idx, u16DelayR, u16DelayW, u16DelayM);
// ASSERT( 0==((*u16DelayR)&0x7) );
// ASSERT( 0==((*u16DelayW)&0x7) );
// ASSERT( 0==((*u16DelayM)&0x7) );
msDelayR = (*u16DelayR)>>3;
msDelayW = (*u16DelayW)>>3;
MD_TRC_L1Audio_Msg_SP3G_SEND_RESYNC_INFO( idx, msDelayR, sp3g->int_time[0]/1000, sp3g->int_time[1]/1000, cur_time/1000);
delay = ( ust_us_duration( sp3g->int_time[1], cur_time ) ) / 1000 ;
if(delay >= msDelayR || delay >= msDelayW){ //error handling
SAL_Get_Delay(MODE_3G, SAL_DELAY_NA, SAL_DELAY_NA, u16DelayR, u16DelayW, u16DelayM);
// ASSERT( 0==((*u16DelayR)&0x7) );
// ASSERT( 0==((*u16DelayW)&0x7) );
// ASSERT( 0==((*u16DelayM)&0x7) );
msDelayR = (*u16DelayR)>>3;
msDelayW = (*u16DelayW)>>3;
MD_TRC_L1Audio_Msg_SP3G_REYSNC_DELAY_OVERFLOW(msDelayR, msDelayW);
sp3g->uDelW = msDelayW;
} else {
*u16DelayR = (msDelayR - delay) * 8;//samples
sp3g->uDelW = (msDelayW - delay);
*u16DelayW = sp3g->uDelW * 8;
}
} else {
SAL_Get_Delay(MODE_3G, SAL_DELAY_NA, SAL_DELAY_NA, u16DelayR, u16DelayW, u16DelayM);
// ASSERT( 0==((*u16DelayR)&0x7) );
// ASSERT( 0==((*u16DelayW)&0x7) );
// ASSERT( 0==((*u16DelayM)&0x7) );
//msDelayR = (*u16DelayR)>>3;
msDelayW = (*u16DelayW)>>3;
sp3g->uDelW = msDelayW;
}
}
void sp3g_hisr_ul(void *data)
{
int32 I, J = 0, K;
uint16 *ptr16;
uint16 tx_type, sc_mode;
uint8 *ptr8;
uint8 len;
const uint8* RAB_To_DSP_Mapping;
uint16 total_bits, idx, rabBitsCount;
uint8 frame_type = 0,bit8Data;
bool bWrite;
kal_take_spinlock(sp3g_spinlockID, KAL_INFINITE_WAIT);
if(L1SP_GetState() != L1SP_STATE_3G_SPEECH_ON){
MD_TRC_SP3G_UL_HISR_SKIP(L1SP_GetState());
kal_give_spinlock(sp3g_spinlockID);
return;
}
ASSERT(sp3g != (SP3G_Struct*) 0);
sp3g->ul_report = SAL_3G_GetValue(SAL_3G_VALUE_TX_CODEC_MODE);
/*for catcher log codec information*/
if( sp3g->ul_report != sp3g->pre_ul_report ){
MD_TRC_L1Audio_Msg_SPEECH_CODEC( L1SP_Speech_Codec_Mode(sp3g->ul_report), L1SP_Speech_Codec_Mode(sp3g->dl_report) );
sp3g->pre_ul_report = sp3g->ul_report;
}
#if defined(__SP3G_UL_DSP_RESYNC_CSR__)
sp3g->int_time[3] = ust_get_current_time();
MD_TRC_SP3G_D2M_UL_TIMING((sp3g->int_time[3])/1000);
#endif
// UL side
ptr16 = (uint16*)sp3g->dsp_buffer;
{
// get data from DSP UL buffer
volatile uint16 *addr;
tx_type = SAL_3G_GetValue(SAL_3G_VALUE_TX_TYPE);
sc_mode = sp3g->ul_report;
if( sc_mode < 0x03 || sc_mode > 0x28 )
{
MD_TRC_SP3G_INVALID_UL_CODEC_MODE(sc_mode);
tx_type = SAL_3G_TX_NO_DATA;
sc_mode = 3;
}
addr = SAL_3G_GetAddr(SAL_3G_ADDR_TXHB);
for(I = GetDspModeLen(sc_mode); --I >= 0 ; )
*ptr16++ = *addr++;
}
// do bit re-ordering
ptr16 = (uint16*)sp3g->dsp_buffer;
#if defined(_EXTRA_LOG_FOR_BIT_TRUE_)
if (g_bNeedExtraLog == true){
ptr16 = (uint16*)sp3g->dsp_buffer;
//kal_prompt_trace(MOD_L1SPHISR,"SP3GHISR UL DSP len %d, %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x",
// DspModeLen[sc_mode - 3], ptr16[0], ptr16[1], ptr16[2], ptr16[3], ptr16[4], ptr16[5], ptr16[6], ptr16[7],
// ptr16[8], ptr16[9], ptr16[10], ptr16[11], ptr16[12], ptr16[13], ptr16[14], ptr16[15]);
MD_TRC_SP3G_UL_BIT_TRUE_DSP_F8(
GetDspModeLen(sc_mode), ptr16[0], ptr16[1], ptr16[2], ptr16[3], ptr16[4], ptr16[5], ptr16[6], ptr16[7]);
MD_TRC_SP3G_UL_BIT_TRUE_DSP_N8(
ptr16[8], ptr16[9], ptr16[10], ptr16[11], ptr16[12], ptr16[13], ptr16[14], ptr16[15]);
}
#endif
ptr8 = (uint8*)sp3g->ul_buffer[sp3g->ul_write_idx];
bWrite = KAL_FALSE;
if(SAL_3G_IsULReady()){//DSP tell MCU the data of DSP is ready
if( sp3g->ul_count < sp3g->ul_buffer_size ){
bWrite = KAL_TRUE;
}
if( sp3g->ul_count == sp3g->ul_buffer_size ){
if( sp3g->is_getting_ul_data ){
bWrite = KAL_FALSE;
}else{
sp3g->ul_read_idx++; //drop oldest frame
sp3g->ul_count--;
bWrite = KAL_TRUE;
if( sp3g->ul_read_idx == sp3g->ul_buffer_size )
sp3g->ul_read_idx = 0;
}
}
SAL_3G_SetULEmpty();
}else{//DSP tell MCU the data of DSP is not ready
sp3g->ul_report = sp3g->ul_codec_mode;
sc_mode = sp3g->ul_report;
AM_FillSilencePatternInBuffer( ptr16, sp3g->ul_report );
tx_type = SAL_3G_TX_SPEECH_GOOD;
bWrite = KAL_TRUE;
MD_TRC_SP3G_UL_DSP_NOT_READY_WARNING_AND_FILL_SILENCE();
}
if(sp3g->under_interact){
MD_TRC_SP3G_SKIP_UL_REFRESH(sp3g->ul_report, sp3g->ul_codec_mode);
kal_give_spinlock(sp3g_spinlockID);
return;
}
if( bWrite ){
frame_type = GetDspMode2FrameType(sc_mode);
switch(tx_type)
{
case SAL_3G_TX_SPEECH_GOOD:
if( sp3g->sp3g_mode == RAT_3G_MODE ){
*ptr8++ = frame_type;
len = RAB_subflow[frame_type][3];
*ptr8++ = len;
if(frame_type >= 0x10) //AMR-WB
RAB_To_DSP_Mapping = (const uint8 *)tblAMR_WBOrder[frame_type-0x10];
else
RAB_To_DSP_Mapping = tblAMROrder[frame_type];
// do bit reorder , move speech information bits to rab_byte_array
total_bits = RAB_subflow[frame_type][0] + RAB_subflow[frame_type][1] + RAB_subflow[frame_type][2];
for(I = len; --I >= 0; *ptr8++ = 0);
for(idx = 0, ptr8 -= len, I = 0; I < 3; I ++){
rabBitsCount = RAB_subflow[frame_type][I];
if( frame_type >= 16 ){
const uint16* WB_RAB_To_DSP_Mapping;
WB_RAB_To_DSP_Mapping = (const uint16*)RAB_To_DSP_Mapping;
for(J = 0; J < rabBitsCount; J++)
{
K = WB_RAB_To_DSP_Mapping[idx++];
bit8Data = (ptr16[K >> 4] & DSP_Order[K & 15])? RAB_Order[J & 0x7] : 0;
ptr8[J >> 3] |= bit8Data;
}
} else {
for(J = 0; J < rabBitsCount; J++)
{
K = RAB_To_DSP_Mapping[idx++];
bit8Data = (ptr16[K >> 4] & DSP_Order[K & 15])? RAB_Order[J & 0x7] : 0;
ptr8[J >> 3] |= bit8Data;
}
}
ptr8 += (rabBitsCount + 7) >> 3;
}
ASSERT(idx == total_bits);
}
#ifdef __VIDEO_CALL_SUPPORT__
else{
len = AMR_IF2_FRAME_LENGTH[frame_type]; //frame length
*ptr8++ = len;
RAB_To_DSP_Mapping = tblAMROrder[frame_type];
total_bits = RAB_subflow[frame_type][0] + RAB_subflow[frame_type][1] + RAB_subflow[frame_type][2];
for(I = len; --I >= 0 ; )
*ptr8++ = 0;
idx = 0;
ptr8 -= len;
// do bit reorder , first byte contains frame_type
*ptr8 = frame_type;
I = 4;
for(J = 0; J < total_bits; J++,I++)
{
K = RAB_To_DSP_Mapping[idx++];
bit8Data = (ptr16[K >> 4] & DSP_Order[K & 15])? AMR_IF2_Order[J & 0x7] : 0;
ptr8[I >> 3] |= bit8Data;
}
}
#endif
#if defined(_EXTRA_LOG_FOR_BIT_TRUE_)
//kal_prompt_trace(MOD_L1SPHISR,"SP3G_HISR UL is TX_SPEECH_GOOD");
MD_TRC_SP3G_TX_SPEECH_GOOD();
#endif
break;
case SAL_3G_TX_SID_FIRST:
if( sp3g->sp3g_mode == RAT_3G_MODE ){
if( sp3g->ul_report >= 0x20 )
*ptr8++ = WB_AMR_SID_FRAME;//WB SID
else
*ptr8++ = AMR_SID_FRAME;
*ptr8++ = 5;
for(I = 4; --I >= 0; )
*ptr8++ = 0;
if( sp3g->ul_report >= 0x20 )
*ptr8 = (uint8)(sp3g->ul_report - 0x20);
else
*ptr8 = (uint8)(frame_type << 1);
#ifdef AMR_DATA_LOG
ptr8 -= 6;
MD_TRC_SP3G_TX_SID_FIRST();
#endif
}
#ifdef __VIDEO_CALL_SUPPORT__
else{//3G 324M
*ptr8++ = 6;//frame length
for(I = 5; --I >= 0; )
*ptr8++ = 0;
*ptr8 = (uint8)(frame_type);
ptr8 -= 5;
*ptr8 |= AMR_SID_FRAME;
}
#endif
break;
case SAL_3G_TX_SID_UPDATE:
if( sp3g->sp3g_mode == RAT_3G_MODE ){
if( sp3g->ul_report >= 0x20 )
*ptr8++ = WB_AMR_SID_FRAME;//WB SID
else
*ptr8++ = AMR_SID_FRAME;
*ptr8++ = 5;
// do bit reorder , move sid information bits to rab_byte_array
for(I = 5; --I >= 0; )
*ptr8++ = 0;
ptr8 -= 5;
for(I = 0; I < 35; I ++)
{
bit8Data = (ptr16[I >> 4] & DSP_Order[I & 15])? RAB_Order[I & 0x7] : 0;
ptr8[I >> 3] |= bit8Data;
}
frame_type = (frame_type >> 2) | ((frame_type & 0x1) << 2) | (frame_type & 0x2);
if( sp3g->ul_report >= 0x20 )
ptr8[4] |= (uint8)(sp3g->ul_report - 0x20)|0x10;
else
ptr8[4] |= (uint8)(frame_type << 1)|0x10;
#ifdef AMR_DATA_LOG
ptr8 -= 2;
MD_TRC_SP3G_TX_SID_UPDATE();
#endif
}
#ifdef __VIDEO_CALL_SUPPORT__
else{//3G 324M
*ptr8++ = 6;//frame length
for(I = 5; --I >= 0; )
*ptr8++ = 0;
*ptr8 = (uint8)(frame_type);
ptr8 -= 5;
*ptr8 |= AMR_SID_FRAME;
J = 4;
for(I = 0; I < 35; J++, I++)
{
bit8Data = (ptr16[I >> 4] & DSP_Order[I & 15])? AMR_IF2_Order[I & 0x7] : 0;
ptr8[J >> 3] |= bit8Data;
}
ptr8[4] |= 0x80;
}
#endif
break;
case SAL_3G_TX_NO_DATA:
if( sp3g->sp3g_mode == RAT_3G_MODE ){
*ptr8++ = AMR_NO_DATA;
*ptr8++ = 0;
}
#ifdef __VIDEO_CALL_SUPPORT__
else{//3G324M
*ptr8++ = 1;
*ptr8++ = AMR_NO_DATA;
}
#endif
#if defined(_EXTRA_LOG_FOR_BIT_TRUE_)
//kal_prompt_trace(MOD_L1SPHISR,"SP3G_HISR UL is NO DATA");
MD_TRC_SP3G_UL_NO_DATA();
#endif
break;
default:
ASSERT(false);
break;
}
#if defined(_EXTRA_LOG_FOR_BIT_TRUE_)
if (g_bNeedExtraLog == true){
//kal_prompt_trace(MOD_L1SPHISR,"SP3G_HISR UL Type %d, Frm %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x",
// tx_type, ptr8[0], ptr8[1],ptr8[2],ptr8[3],ptr8[4],
// ptr8[5],ptr8[6],ptr8[7],ptr8[8],ptr8[9],ptr8[10],ptr8[11],ptr8[12],ptr8[13],ptr8[14],ptr8[15], ptr8[16],ptr8[17],ptr8[18],ptr8[19],ptr8[20]);
uint8 *tmp_ = (uint8*)sp3g->ul_buffer[sp3g->ul_write_idx];
MD_TRC_SP3G_DEBUG_UL_BUFF(sp3g->ul_write_idx);
MD_TRC_SP3G_UL_BIT_TRUE_F8(
1, tx_type, tmp_[0], tmp_[1],tmp_[2],tmp_[3],tmp_[4],tmp_[5],tmp_[6],tmp_[7]);
MD_TRC_SP3G_UL_BIT_TRUE_N13(
tmp_[8],tmp_[9],tmp_[10],tmp_[11],tmp_[12],tmp_[13],tmp_[14],tmp_[15],
tmp_[16],tmp_[17],tmp_[18],tmp_[19],tmp_[20]);
}
#endif
}
if( sp3g->ul_refresh )
{
if((sp3g->ul_report <= 0x0A && sp3g->ul_codec_mode >= 0x20) || //WB, NB handover
(sp3g->ul_report >= 0x20 && sp3g->ul_codec_mode <= 0xA)){
ASSERT(0);
}else if(sp3g->ul_report != sp3g->ul_codec_mode ){
SAL_3G_Upd_Enc_Cod(sp3g->ul_codec_mode);
}
sp3g->ul_refresh = KAL_FALSE;
}
if( bWrite ){
sp3g->ul_write_idx++;
if( sp3g->ul_write_idx == sp3g->ul_buffer_size )
sp3g->ul_write_idx = 0;
sp3g->ul_count++;
#if defined(_EXTRA_LOG_FOR_BIT_TRUE_)
if (g_bNeedExtraLog == true) {
//kal_prompt_trace(MOD_L1SPHISR,"SP3GVT UL cnt=%d,r=%d,w=%d",sp3g->ul_count,sp3g->ul_read_idx,sp3g->ul_write_idx);
MD_TRC_SP3G_UL_BUFFER(sp3g->ul_count,sp3g->ul_read_idx,sp3g->ul_write_idx);
}
#endif
if( sp3g->sp3g_mode == RAT_3G_MODE && sp3g->ul_delay > START_SHRINK_UL_DELAY && !sp3g->is_getting_ul_data){
sp3g->ul_read_idx++;
if( sp3g->ul_read_idx == sp3g->ul_buffer_size )
sp3g->ul_read_idx = 0;
if(sp3g->ul_count > 1)
sp3g->ul_count--;
}//when ul write updated, check ul_delay. keep newest one
}
if( sp3g->waiting == KAL_FALSE )
{
sp3g->waiting = KAL_TRUE;
if( sp3g->sp3g_mode == RAT_3G_MODE ){
ASSERT( NULL != CSR_SP3G_Callback );
CSR_SP3G_Callback( SP3G_UL_DATA_NOTIFY, (void*)0 );
}
}
else
{
sp3g->ul_delay ++;
if( sp3g->sp3g_mode == RAT_3G_MODE ){
ASSERT( NULL != CSR_SP3G_Callback );
CSR_SP3G_Callback(SP3G_UL_DATA_DEALY_TICK, (void *)(kal_uint32)sp3g->ul_delay);
}
MD_TRC_SP3G_UL_DELAY(sp3g->ul_delay);
#if 0
/* under construction !*/
#endif
}
kal_give_spinlock(sp3g_spinlockID);
#ifdef __FAKE_3G_LOOPBACK__
if(get_is_fake_3g()){
msg_send6(MOD_L1SP, MOD_MED, AUDIO_SAP, MSG_ID_AUDIO_M2M_SP3G_UL_EVENT, NULL, NULL);
}
#endif
}
void sp3g_updateL1DSync(void)
{
#if defined(_MODEM_RESYNC_3G_)
int16 time_drift;
#if defined( __UMTS_RAT__ )
if(!SP3G_Rab_State()){
MD_TRC_SP3G_L1D_Resync_Skip();
return;
}
switch(L1SP_GetSIMStatus()){
case SP_3G_SIM_FDD_ACTIVE:
#if defined(__UMTS_FDD_MODE__)
time_drift = UL1D_Speech_Resync_Get_Time_Offset(); //us
MD_TRC_SP3G_L1D_Resync(1, time_drift);
if(time_drift > 1000){
MD_TRC_L1D_RESYNC_UPDATE(1);
UL1D_Speech_Resync_Update_Time_Offset(true);
SAL_8K_Resync(true, 8, true, 8);
}else if(time_drift < -1000){
MD_TRC_L1D_RESYNC_UPDATE(0);
UL1D_Speech_Resync_Update_Time_Offset(false);
SAL_8K_Resync(true, -8, true, -8);
}
#endif
break;
case SP_3G_SIM_TDD_ACTIVE:
#if defined( __UMTS_TDD128_MODE__ )
time_drift = TL1C_Get_Time_Drift(); //us
MD_TRC_SP3G_L1D_Resync(2, time_drift);
if(time_drift > 1000){
MD_TRC_L1D_RESYNC_UPDATE(1);
TL1C_Update_Time_Drift(true);
SAL_8K_Resync(true, 8, true, 8);
}else if(time_drift < -1000){
MD_TRC_L1D_RESYNC_UPDATE(0);
TL1C_Update_Time_Drift(false);
SAL_8K_Resync(true, -8, true, -8);
}
#endif
break;
default:
ASSERT(0);
}
#endif
#endif
}
extern void vmSet3GNetworkInfo( uint32 *l1_info, uint16 crc_result, uint16 buf_status, uint8 dl_count );
void sp3g_hisr_dl(void *data)
{
int32 I, J = 0, K;
uint16 *ptr16;
uint16 rx_type = 0, sd_mode = 0, rx_len = 0;
uint8 *ptr8;
#if defined(_EXTRA_LOG_FOR_BIT_TRUE_)
uint8 *ptr8_bak;
#endif
const uint8* RAB_To_DSP_Mapping, *Order = NULL;
uint16 total_bits, idx, rabBitsCount;
uint8 frame_type = 0;
uint16 bit16Data;
uint8 sidData;
bool FQI_flag = false;
#if defined(__SP3G_UL_DSP_RESYNC_CSR__)
MD_TRC_SP3G_D2M_DL_TIMING((ust_get_current_time())/1000);
#endif
if(L1SP_GetState() != L1SP_STATE_3G_SPEECH_ON)
return;
ASSERT(sp3g != (SP3G_Struct*) 0);
sp3g->dl_report = SAL_3G_GetValue(SAL_3G_VALUE_RX_CODEC_MODE);
/*for catcher log codec information*/
if( sp3g->dl_report != sp3g->pre_dl_report ){
MD_TRC_L1Audio_Msg_SPEECH_CODEC( L1SP_Speech_Codec_Mode(sp3g->ul_report), L1SP_Speech_Codec_Mode(sp3g->dl_report) );
sp3g->pre_dl_report = sp3g->dl_report;
}
{
uint32 *l1_info = NULL;
//uint16 crc_result = 0;
uint16 buf_status, crc_result = 0;
if( sp3g->dl_count == 0 ){
crc_result = (l1AInfo << 8);
}
else
{
uint32 CFN = 0;
if( sp3g->sp3g_mode == RAT_3G324M_MODE ){
l1_info = NULL;
}
else{
ptr8 = (uint8*) sp3g->dl_buffer[sp3g->dl_read_idx];
ptr8 += 2;
CFN = ptr8[0] + (ptr8[1] << 8) + (ptr8[2] << 16) + (ptr8[3] << 24);
for(I = 0 ; I < 4 ; I ++)
if( CFN == sp3g->L1_Info[I][0] )
break;
if( I == 4 ){
crc_result = (l1AInfo << 8);
l1_info = NULL;
}else{
l1_info = sp3g->L1_Info[I];
crc_result = (uint16)(l1AInfo << 8) | (uint16)(sp3g->L1_Info[I][2] & 0xF); //[0:7]:CRC, [8:15]:l1AInfo
}
/*SID BAD False alarm work around, log in VM first*/
{
uint8 * ptrDL;
ptrDL = (uint8*) sp3g->dl_buffer[sp3g->dl_read_idx];
if( sp3g->dtx_state == 0 && ptrDL[0] == 8 /*AMR_SID*/ && ptrDL[1] == KAL_FALSE/*CRC fail*/)
crc_result |= 0x8000;// The flag indicate working around
if( ptrDL[0] == AMR_NO_DATA && sp3g->dtx_force == KAL_TRUE )
//crc_result |= 0x4000;
crc_result |= 0x0080;//move from bit14 to bit7. 20100821
}
}
}
buf_status = ( ( (sp3g->ul_read_idx << DL_BUF_INDEX_BIT_NUM) + sp3g->dl_read_idx ) << 8 ) +
(sp3g->ul_write_idx << DL_BUF_INDEX_BIT_NUM) + sp3g->dl_write_idx;
vmSet3GNetworkInfo(l1_info, crc_result, buf_status, sp3g->dl_count);
}
l1AInfo &= ~0xFFFC;
// DL side
if( sp3g->dl_count == 0 || sp3g_reset_flag != 2 ){ // buffer under flow
SAL_3G_Set_RxType(SAL_3G_RX_NO_DATA);
rx_type = SAL_3G_RX_NO_DATA;
sp3g->dtx_state = 1;
MD_TRC_SP3G_DTX_NO_DATA();
}
else
{
MD_TRC_SP3G_BUFFER_STATUS(sp3g->dl_read_idx, sp3g->dl_write_idx,sp3g->dl_count, sp3g->dl_buffer[sp3g->dl_read_idx][0]);
ptr8 = (uint8*) sp3g->dl_buffer[sp3g->dl_read_idx];
#if defined(_EXTRA_LOG_FOR_BIT_TRUE_)
ptr8_bak = (uint8*) sp3g->dl_buffer2[sp3g->dl_read_idx];
#endif
ptr16 = (uint16*) sp3g->dsp_buffer_dl;
if( sp3g->sp3g_mode == RAT_3G_MODE ){
frame_type = *ptr8++; // here 0 ~ 7 and includes SID and NO_DATA
FQI_flag = (bool)*ptr8++;
ptr8 += 4; // skip CFN
#if defined(_EXTRA_LOG_FOR_BIT_TRUE_)
ptr8_bak += 6;
#endif
}
#ifdef __VIDEO_CALL_SUPPORT__
else{//3G 324M
FQI_flag = KAL_TRUE;
frame_type = *ptr8++; // here 0 ~ 7 and includes SID and NO_DATA
ptr8++; // skip frame length
}
#endif
#if defined(_EXTRA_LOG_FOR_BIT_TRUE_)
if (g_bNeedExtraLog == true){
//kal_prompt_trace(MOD_L1SPHISR,"SP3G_HISR DL Type %d, Frm %x %x %x %x %x", frame_type, ptr8[0], ptr8[1],ptr8[2],ptr8[3],ptr8[4]);
MD_TRC_SP3G_DL_BIT_TRUE(frame_type, ptr8[0], ptr8[1],ptr8[2],ptr8[3],ptr8[4]);
}
#endif
if( frame_type == AMR_NO_DATA && sp3g->dtx_force == KAL_TRUE ){
frame_type = AMR_SID_FRAME;
FQI_flag = KAL_FALSE; // force enter SID_BAD;
sp3g->dtx_state = 1;
}
sp3g->dtx_force = KAL_FALSE;
if( sp3g->dtx_state == 0 && frame_type == AMR_SID_FRAME && FQI_flag == KAL_FALSE ){//previous dtx_state is false, but suddenly SID_BAD, regard it as false alarm.
frame_type = AMR_NO_DATA;
sp3g->dtx_force = KAL_TRUE;
}
if( data == (void *)2 )
{
#if defined(__SP3G_DL_BUFFER_BEFORE_PLAY__)
MD_TRC_SP3G_FORCE_NODATA_WHEN_RESYNC();
frame_type = AMR_NO_DATA;
#endif
}
switch(frame_type)
{
case 0: // 4.75 kbps
case 1: // 5.15 kbps
case 2: // 5.9 kbps
case 3: // 6.7 kbps
case 4: // 7.4 kbps
case 5: // 7.95 kbps
case 6: // 10.2 kbps
case 7: // 12.2 kbps
case 16:/* WB type 0, AMR-WB 6.60 */
case 17:/* WB type 1, AMR-WB 8.85 */
case 18:/* WB type 2, AMR-WB 12.65 */
case 19:/* WB type 3, AMR-WB 14.25 */
case 20:/* WB type 4, AMR-WB 15.85 */
case 21:/* WB type 5, AMR-WB 18.25 */
case 22:/* WB type 6, AMR-WB 19.85 */
case 23:/* WB type 7, AMR-WB 23.05 */
case 24:/* WB type 8, AMR-WB 23.85 */
if( frame_type >= 16 )
RAB_To_DSP_Mapping = (const uint8 *) tblAMR_WBOrder[frame_type-16];
else
RAB_To_DSP_Mapping = tblAMROrder[frame_type];
if( FQI_flag == KAL_TRUE )
rx_type = SAL_3G_RX_SPEECH_GOOD;
else
rx_type = SAL_3G_RX_SPEECH_BAD;
sd_mode = GetFrameType2DspMode(frame_type);
rx_len = GetDspModeLen(sd_mode);
// move amr data to dl_buffer
total_bits = RAB_subflow[frame_type][0] + RAB_subflow[frame_type][1] + RAB_subflow[frame_type][2];
for(I = rx_len; --I >= 0; )
*ptr16++ = 0;
ptr16 -= rx_len;
idx = 0;
if( sp3g->sp3g_mode == RAT_3G_MODE ){
for(I = 0; I < 3; I ++)
{
if(RAB_subflow[frame_type][I] == 0)
break;
#if defined(_EXTRA_LOG_FOR_BIT_TRUE_)
if (g_bNeedExtraLog == true){
ASSERT( *ptr8 == *ptr8_bak );
}
#endif
rabBitsCount = RAB_subflow[frame_type][I];
if(frame_type >= 16){
const uint16* WB_RAB_To_DSP_Mapping;
WB_RAB_To_DSP_Mapping = (const uint16*)RAB_To_DSP_Mapping;
for(J = 0; J < rabBitsCount; J++)
{
K = WB_RAB_To_DSP_Mapping[idx++];
bit16Data = (ptr8[J >> 3] & RAB_Order[J & 7])? DSP_Order[K & 15] : 0;
ptr16[K >> 4] |= bit16Data;
}
} else {
for(J = 0; J < rabBitsCount; J++)
{
uint32 t1;
uint16 *t2;
K = RAB_To_DSP_Mapping[idx++];
bit16Data = (ptr8[J >> 3] & RAB_Order[J & 7])? DSP_Order[K & 15] : 0;
t1 = K >> 4;
t2 = ptr16 + t1;
//ptr16[K >> 4] |= bit16Data;
*t2 |= bit16Data;
}
}
ptr8 += (rabBitsCount + 7) >> 3;
#if defined(_EXTRA_LOG_FOR_BIT_TRUE_)
ptr8_bak += (rabBitsCount + 7) >> 3;
#endif
}
ASSERT(idx == total_bits);
}
#ifdef __VIDEO_CALL_SUPPORT__
else{//3G 324M
I = 4;
for(J = 0; J < total_bits; J++, I++)
{
K = RAB_To_DSP_Mapping[idx++];
bit16Data = (ptr8[I >> 3] & AMR_IF2_Order[J & 7])? DSP_Order[K & 15] : 0;
ptr16[K >> 4] |= bit16Data;
}
}
#endif
sp3g->dtx_state = 0;
break;
case 8: // AMR SID
case 25:
sidData = ptr8[4];
if( sp3g->sp3g_mode == RAT_3G_MODE ){
if( FQI_flag == KAL_TRUE )
{
if( sidData & 0x10 )
rx_type = SAL_3G_RX_SID_UPDATE;
else
rx_type = SAL_3G_RX_SID_FIRST;
sp3g->dtx_state = 1;
}
else
rx_type = SAL_3G_RX_SID_BAD;
if( frame_type == 25 ){
sd_mode = (sidData & 0xF);
if(sd_mode >= 10)
{
rx_type = SAL_3G_RX_SID_BAD;
sd_mode = sp3g->pre_dl_report;
} else if(9 == sd_mode){
sd_mode = sp3g->pre_dl_report;
} else {
sd_mode = GetFrameType2DspMode(sd_mode+16);
}
} else
{
sd_mode = (sidData & 0xE) >> 1;// should reverse
sd_mode = (sd_mode >> 2) | ((sd_mode & 0x1) << 2) | (sd_mode & 0x2);
sd_mode = GetFrameType2DspMode(sd_mode);
//sd_mode = AmrFrameType2DspMode[sd_mode]; // RX SD Mode
}
}
#ifdef __VIDEO_CALL_SUPPORT__
else{//3G 324M
if( sidData & 0x80 )
rx_type = SAL_3G_RX_SID_UPDATE;
else
rx_type = SAL_3G_RX_SID_FIRST;
sd_mode = GetFrameType2DspMode((ptr8[5] & 0x7));
}
#endif
rx_len = 3; // 35 information bits
// move sid data to dl_buffer
for(I = 3; --I >= 0; )
*ptr16++ = 0;
ptr16 -= 3;
Order = RAB_Order;
if( sp3g->sp3g_mode == RAT_3G_MODE ){
J = 0;
Order = RAB_Order;
}
#ifdef __VIDEO_CALL_SUPPORT__
else{//3G324M
J = 4;
Order = AMR_IF2_Order;
}
#endif
for(I = 0; I < 35; I++,J++)
{
bit16Data = (ptr8[J >> 3] & Order[I & 7])? DSP_Order[I & 15] : 0;
ptr16[I >> 4] |= bit16Data;
}
#ifdef AMR_DATA_LOG
if( rx_type == SAL_3G_RX_SID_FIRST )
MD_TRC_SP3G_RX_SID_FIRST();
else if( rx_type == SAL_3G_RX_SID_UPDATE )
MD_TRC_SP3G_RX_SID_UPDATE();
#endif
break;
case 15: // NO DATA
MD_TRC_SP3G_RX_NO_DATA();
rx_type = SAL_3G_RX_NO_DATA;
rx_len = 0;
// no need to record codec mode , inherit from previous
break;
default:
ASSERT(false);
break;
}
// get codec_mode , set RX codec_mode
// get data from dl_read
ptr16 = (uint16*) sp3g->dsp_buffer_dl;
SAL_3G_Set_RxType(rx_type);
//For NB/WB handover, it's decided by network set UL codec.
// If downlink happens, set it as NO data.
if( rx_type != SAL_3G_RX_NO_DATA )
{
if( (sd_mode <= 0x0A && sp3g->dl_report >= 0x20) ||
(sd_mode >= 0x20 && sp3g->dl_report <= 0x0A) )
{
SAL_3G_Set_RxType(SAL_3G_RX_NO_DATA);
SAL_3G_Upd_Dec_Cod(sp3g->dl_report);
rx_type = SAL_3G_RX_NO_DATA;
MD_TRC_SP3G_RX_FORCE_NO_DATA_WHEN_CHANGE_BAND();
}
}
else if (data == (void *)2) {
#if defined(__SP3G_DL_BUFFER_BEFORE_PLAY__)
AM_3G_INTRARAT(sp3g->ul_codec_mode);
sp3g->ul_request_resync = KAL_FALSE;
#endif
}
if( rx_type != SAL_3G_RX_NO_DATA && rx_type != SAL_3G_RX_SID_BAD ) //if RX_NO_DATA or RX_SID_BAD, codec mode will use the previous one
{
volatile uint16 *addr;
SAL_3G_Upd_Dec_Cod(sd_mode);
addr = SAL_3G_GetAddr(SAL_3G_ADDR_RXHB);
for(I = rx_len ; --I >= 0; )
*addr++ = *ptr16++;
Data_Sync_Barrier();
}
#if defined(__SP3G_UL_DSP_RESYNC_CSR__)
if( data == (void *)2 ){
sp3g->dl_count --;
sp3g->dl_read_idx++;
sp3g->dl_buffer_size = RAT_3G_DL_BUFFER_NUM; // 1 or 2
} else
#endif
{
// update 3G dl_count
sp3g->dl_count --;
sp3g->dl_read_idx++;
}
if( sp3g->dl_read_idx >= sp3g->dl_buffer_size ){//near end of buffer
sp3g->dl_read_idx = 0;
}
}
MD_TRC_SP3G_SYNC(((uint8)SAL_3G_IsDLEmpty()<<1) + (uint8)SAL_3G_IsULReady());
SAL_3G_SetDLReady(); // MCU tell DSP the data is ready
{ /*for catcher log codec information*/
uint8 txType, rxType, ber;
txType = SAL_3G_GetValue(SAL_3G_VALUE_TX_TYPE);
rxType = rx_type >> 1;
ber = 255;//useless both for dsp and driver;
//ber = (*DP_3G_DL_RX_TYPE & 0xFF00);
MD_TRC_L1Audio_Msg_SPEECH_FRAME( L1SP_Speech_TX_Type(txType), L1SP_Speech_RX_Type(rxType), ber );
//L1Audio_Msg_VM_DEBUG( DP2_3G_debug_info0, DP2_3G_debug_info1, DP2_3G_debug_info7 );
}
}
void SP3G_Reset( void )
{
sp3g_reset_flag = 1;
}
kal_bool SP3G_IsDTXOn()
{
return sp3g_dtx_mode;
}
void SP3G_SetDTX(kal_bool on)
{
sp3g_dtx_mode = on;
MD_TRC_SP3G_SET_DTX(on);
if( L1SP_GetState() == L1SP_STATE_3G_SPEECH_ON )
{
kal_take_spinlock(sp3g_spinlockID, KAL_INFINITE_WAIT);
SAL_3G_SetDtx(on);
kal_give_spinlock(sp3g_spinlockID);
}
}
// Force Rx Type to No data frame, used in speech off
void SP3G_SetRxTypeToNoData( void )
{
SAL_3G_Set_RxType(SAL_3G_RX_NO_DATA);
}
void sp3g_reset_internal( void )
{
// DL side
sp3g->dl_count = 0;
sp3g->dl_write_idx = 0;
sp3g->dl_read_idx = 0;
#if defined(__CSHSPA_SUPPORT__)
sp3g->dl_buffer_size = sp3g_max_cs_delay;
#else
sp3g->dl_buffer_size = RAT_3G_DL_BUFFER_NUM_BEFORE_RESYNC;
#endif
sp3g_reset_flag = 0; // clear reset flag, wait it to be 2
}
void sp3g_init( void )
{
sp3g_is_csr_ready = false;
sp3g_rab_id = 0;
sp3g_rab_state = KAL_FALSE;
l1AInfo = 0;
#if !defined(__L1_STANDALONE__)
CSR_SP3G_Callback = NULL;
#endif
#if defined(__CSHSPA_SUPPORT__)
sp3g_max_cs_delay = 2;
#endif
sp3g_dtx_mode = 0;
#if defined(_EXTRA_LOG_FOR_BIT_TRUE_)
g_bNeedExtraLog = KAL_FALSE;
#endif
sp3g_spinlockID = kal_create_spinlock("sp3g_spinlock");
sp3g = &sp3gInfo;
}
void sp3g_speech_init(uint8 RAT_Mode)
{
ASSERT( (RAT_Mode == RAT_3G_MODE) || (RAT_Mode == RAT_3G324M_MODE) );
ASSERT( L1SP_GetState() == L1SP_STATE_IDLE );
#if !defined(__L1_STANDALONE__)
#ifdef __FAKE_3G_LOOPBACK__
CSR_SP3G_Callback = fake_CSR_Speech_Callback;
g_bNeedExtraLog = KAL_TRUE;
#else
CSR_SP3G_Callback = csr_get_fp_CSR_SP3G_Callback();
#endif
#endif
memset(sp3g, 0, sizeof(SP3G_Struct));
sp3g->sp3g_mode = RAT_Mode;
// UL side
sp3g->waiting = KAL_FALSE;
sp3g->ul_write_idx = 0;
sp3g->ul_read_idx = 0;
sp3g->ul_count = 0;
sp3g->is_getting_ul_data = KAL_FALSE;
sp3g->under_interact = KAL_FALSE;
sp3g->ul_delay = 0;
sp3g->pre_ul_report = sp3g->pre_dl_report = sp3g->ul_report = sp3g->dl_report = INIT_3G_CODEC;
if( sp3g->sp3g_mode == RAT_3G_MODE )
sp3g->ul_buffer_size = RAT_3G_UL_BUFFER_NUM;
#ifdef __VIDEO_CALL_SUPPORT__
else //3G324M
sp3g->ul_buffer_size = MAX_3G_UL_BUFFER_NUM;
#endif
#if defined(UL_HARD_REAL_TIME_DEMAND)
sp3g->ul_buffer_size = HARD_REAL_TIME_UL_BUFFER_NUM;
#endif
#ifdef __FAKE_3G_LOOPBACK__
if(get_is_fake_3g()){
;//sp3g->ul_codec_mode = INIT_3G_CODEC; applya the previous codec
}else{
sp3g->ul_codec_mode = INIT_3G_CODEC;
}
#else
sp3g->ul_codec_mode = INIT_3G_CODEC;
#endif
sp3g->ul_refresh = KAL_FALSE; // detect change codec_mode
// DL side
sp3g->dl_count = 0;
sp3g->dl_write_idx = 0;
sp3g->dl_read_idx = 0;
if( sp3g->sp3g_mode == RAT_3G_MODE ){
#if defined(__CSHSPA_SUPPORT__)
sp3g->dl_buffer_size = sp3g_max_cs_delay;
#else
sp3g->dl_buffer_size = RAT_3G_DL_BUFFER_NUM_BEFORE_RESYNC;
#endif
sp3g_reset_flag = 1;
}
else{ // 3G324M
sp3g->dl_buffer_size = MAX_3G_DL_BUFFER_NUM;
sp3g_reset_flag = 2;
}
#if defined(SP3G_UNIT_TEST)
L1Audio_HookHisrHandler(DP_D2C_3G,(L1Audio_EventHandler)sp3g_hisr_2, 0);
#else
#if 0//!defined(__UNIFIED_ISR_LEVEL__)
/* under construction !*/
#endif
L1Audio_HookHisrHandler(DP_D2C_3G_DONE_UL,(L1Audio_EventHandler)sp3g_hisr_ul, 0);
#endif
SAL_3G_Upd_Enc_Cod(sp3g->ul_codec_mode);
SAL_3G_Upd_Dec_Cod(sp3g->ul_codec_mode);
#if defined(__SP3G_UL_DSP_RESYNC_CSR__)
sp3g->int_time[0] = 0;
sp3g->int_time[1] = 0;
sp3g->int_time[2] = 0;
sp3g->int_time[3] = 0;
sp3g->int_time[4] = 0;
sp3g->ul_request_resync = KAL_FALSE;
#endif
sp3g->l1_info_idx = 0;
sp3g->dtx_state = 0;
}
void sp3g_speech_close( bool IsInterRAT )
{
#if 0//!defined(__UNIFIED_ISR_LEVEL__)
/* under construction !*/
#endif
L1Audio_UnhookHisrHandler(DP_D2C_3G_DONE_UL);
//kal_take_spinlock(sp3g_spinlockID, KAL_INFINITE_WAIT);
//free_ctrl_buffer(sp3g);
//sp3g = (SP3G_Struct*) 0;
//kal_give_spinlock(sp3g_spinlockID);
#if defined(__CSHSPA_SUPPORT__)
sp3g_max_cs_delay = 2;
//reset to 2 frame
#if defined(CSHSPA_UNIT_TEST)
L1Audio_FreeAudioID(sp3g_hspa_aud_id);
#endif
#endif
/* only these cases should wait state, if only 2G happen, then return to idle */
if( L1SP_GetState() == L1SP_STATE_3G_SPEECH_ON || L1SP_GetState() == L1SP_STATE_3G_SPEECH_CLOSING || IsInterRAT
#ifdef __VIDEO_CALL_SUPPORT__
|| L1SP_GetState() == L1SP_STATE_3G324M_SPEECH_ON
#endif
){
//uint32 waitTime;
#ifdef __VIDEO_CALL_SUPPORT__
if( L1SP_GetState() == L1SP_STATE_3G324M_SPEECH_ON )
vt_SP3G_Callback( (kal_uint8)SP3G_CODEC_CLOSED, (void*)0);
else
#endif
CSR_Codec_Close(SP3G_Rab_Id());
}
#if !defined(__L1_STANDALONE__)
kal_take_spinlock(sp3g_spinlockID, KAL_INFINITE_WAIT);
CSR_SP3G_Callback = NULL;
kal_give_spinlock(sp3g_spinlockID);
#endif
}
void SP3G_Request(void)
{
MD_TRC_SP3G_REQUEST();
L1SP_3G_Request();
}
kal_uint32 SP3G_GetCodecMode(void)
{
if(sp3g != NULL)
return sp3g->ul_codec_mode;
else
return INIT_3G_CODEC;
}
void SP3G_UL_SetFrameType(uint8 amr_frame_type) // function call
{
uint8 state;
uint32 codec;
if( (state = L1SP_GetState()) != L1SP_STATE_3G_SPEECH_ON)
{
//if(state == L1SP_STATE_3G_SPEECH_CLOSING)
return;
//else
//ASSERT(false);
}
ASSERT(sp3g != (SP3G_Struct*) 0);
codec = AmrFrameType2DspMode[amr_frame_type];
if((sp3g->ul_codec_mode >= 0x20 && codec <= 0x0A) ||
(sp3g->ul_codec_mode <= 0x0A && codec >= 0x20)){//Intrarat
sp3g->under_interact = KAL_TRUE;
sp3g->ul_codec_mode = codec;
AM_3G_INTRARAT(codec);
sp3g->under_interact = KAL_FALSE;
SP3G_Reset();
MD_TRC_SP3G_DEBUG_UL_SETFRAMETYPE(1, sp3g->ul_codec_mode, codec, amr_frame_type);
//L1SP_SetState( L1SP_STATE_3G_SPEECH_ON );
}else{
MD_TRC_SP3G_DEBUG_UL_SETFRAMETYPE(2, sp3g->ul_codec_mode, codec,amr_frame_type);
sp3g->ul_codec_mode = codec;
sp3g->ul_refresh = KAL_TRUE;
}
}
// do bit reorder here
void sub_SP3G_UL_GetSpeechFrame(kal_uint16*frame_index, kal_uint8 *frame_type, kal_uint8 *rab_byte_array, kal_uint8 *len)
{
uint8 *ptr8;
int32 I;
uint16 sc_mode=0;
uint8 state;
if( (state = L1SP_GetState()) != L1SP_STATE_3G_SPEECH_ON){
*frame_index = 0xABCD;
*frame_type = AMR_NO_DATA;
*len = 0;
MD_TRC_SP3G_UL_PUT_SPEECH_FRAME_DEBUG(0);
return;
}
ASSERT(sp3g != (SP3G_Struct*) 0);
MD_TRC_SP3G_UL_GET_SPEECH_FRAME();
//ASSERT(sp3g->waiting == KAL_TRUE); // 1 message 1 get ,
// should take care if CSR doesn't get by DATA_NOTIFY message
#if defined(__SP3G_UL_DSP_RESYNC_CSR__)
sp3g->int_time[2] = ust_get_current_time(); // log temp UL time
MD_TRC_SP3G_UL_TIMING(sp3g->int_time[2]/1000);
#endif
*frame_index = 0xABCD; // tmp setting , should be apply true value in near future , Adam
kal_take_spinlock(sp3g_spinlockID, KAL_INFINITE_WAIT);
sp3g->is_getting_ul_data = KAL_TRUE;
kal_give_spinlock(sp3g_spinlockID);
if(sp3g->ul_count == 0)// or should repeat last frame
{
*frame_type = AMR_NO_DATA;
*len = 0;
sp3g->is_getting_ul_data = KAL_FALSE;
SAL_3G_SetULUnsync();
MD_TRC_SP3G_UL_PUT_SPEECH_FRAME_DEBUG(1);
return;
}
#if defined(__SP3G_UL_DSP_RESYNC_CSR__)
{
kal_uint32 time_diff, time_diff_request_resync;
static kal_uint32 time_request_resync = 0;
time_diff = ust_us_duration( sp3g->int_time[3], sp3g->int_time[2] ) / 1000;
time_diff_request_resync = ust_us_duration( time_request_resync, sp3g->int_time[2] ) / 1000;
if( (time_diff == 0 || time_diff >= 20 ) && sp3g->ul_request_resync == KAL_FALSE && time_diff_request_resync > 200 /*larger than a certain time to wait resync done*/) {
sp3g_reset_flag = 1;
//Do not repeat set sp3g_reset_flag = 1
sp3g->ul_request_resync = KAL_TRUE;
time_request_resync = sp3g->int_time[2];
MD_TRC_SP3G_FOUND_UL_SYNC_TIMING_ERROR();
}
}
#endif
//frame_index = 0xABCD; // tmp setting , should be apply true value in near future , Adam
//sp3g->is_getting_ul_data = KAL_TRUE;
ptr8 = (uint8*)sp3g->ul_buffer[sp3g->ul_read_idx];
*frame_type = *ptr8;
#if defined(_EXTRA_LOG_FOR_BIT_TRUE_)
if (g_bNeedExtraLog == true){
uint8 *tmp_ = (uint8*)sp3g->ul_buffer[sp3g->ul_read_idx];
//kal_prompt_trace(MOD_L1SP,"SP3G UL Type %d, Frm %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x",
// *frame_type, ptr8[0], ptr8[1],ptr8[2],ptr8[3],ptr8[4],
// ptr8[5],ptr8[6],ptr8[7],ptr8[8],ptr8[9],ptr8[10],ptr8[11],ptr8[12],ptr8[13],ptr8[14],ptr8[15], ptr8[16],ptr8[17],ptr8[18],ptr8[19],ptr8[20]);
MD_TRC_SP3G_DEBUG_UL_GETSPEECHFRAME(sp3g->ul_read_idx);
MD_TRC_SP3G_UL_BIT_TRUE_F8(
0, *frame_type, tmp_[0], tmp_[1],tmp_[2],tmp_[3],tmp_[4],tmp_[5],tmp_[6],tmp_[7]);
MD_TRC_SP3G_UL_BIT_TRUE_N13(
tmp_[8],tmp_[9],tmp_[10],tmp_[11],tmp_[12],tmp_[13],tmp_[14],tmp_[15],
tmp_[16],tmp_[17],tmp_[18],tmp_[19],tmp_[20]);
}
#endif
if(*frame_type < AMR_SID_FRAME)
sc_mode = AmrFrameType2DspMode[*frame_type];
else if(*frame_type >= 16 && *frame_type <= 24){
sc_mode = AmrFrameType2DspMode[*frame_type];
*ptr8 -= 16;//in subflow data, remap to 0~8?????
}else if( *frame_type == 25 ){ //WB AMR SID
*ptr8 = AWB_SID_FRAME; //in subflow data, remap to 9
}
ptr8++;
#if defined( __UMTS_RAT__ )
if(!SP3G_Rab_State()){
MD_TRC_SP3G_UL_GET_SPEECH_FRAME_SKIP(0);
*frame_type = AMR_NO_DATA;
*len = 0;
return;
}else{
switch(L1SP_GetSIMStatus()){
case SP_3G_SIM_FDD_ACTIVE:
if((*frame_type < 8) && sc_mode < sp3g->ul_codec_mode) // maximum bit_rate limitation
{
MD_TRC_SP3G_UL_GET_SPEECH_FRAME_SKIP(1);
*frame_type = AMR_NO_DATA;
*len = 0;
}
else
{
*len = *ptr8++;
ASSERT( *len <= 60 );
for( I = *len; --I >= 0 ; )
*rab_byte_array++ = *ptr8++;
}
break;
case SP_3G_SIM_TDD_ACTIVE:
if( sc_mode != sp3g->ul_codec_mode) // maximum bit_rate limitation
{
MD_TRC_SP3G_UL_GET_SPEECH_FRAME_SKIP(2);
*frame_type = AMR_NO_DATA;
*len = 0;
}
else
{
*len = *ptr8++;
ASSERT( *len <= 60 );
for( I = *len; --I >= 0 ; )
*rab_byte_array++ = *ptr8++;
}
break;
default:
ASSERT(0);
}
}
#endif
// kal_take_spinlock(sp3g_spinlockID, KAL_INFINITE_WAIT);
sp3g->waiting = KAL_FALSE;
sp3g->ul_delay = 0;
sp3g->ul_count--;
// kal_give_spinlock(sp3g_spinlockID);
sp3g->ul_read_idx++;
if( sp3g->ul_read_idx == sp3g->ul_buffer_size )
sp3g->ul_read_idx = 0;
sp3g->is_getting_ul_data = KAL_FALSE;
}
void SP3G_UL_GetSpeechFrame(kal_uint16*frame_index, kal_uint8 *frame_type, kal_uint8 *rab_byte_array, kal_uint8 *len)
{
kal_take_enh_mutex( sp_handover_mutex );
sub_SP3G_UL_GetSpeechFrame(frame_index, frame_type, rab_byte_array, len);
kal_give_enh_mutex( sp_handover_mutex );
}
const uint8 last_sub_flow_id[26] = { 1, 1, 1, 1, 1, 1, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0};
// do bit reorder here
void sub_SP3G_DL_PutSpeechFrame(uint32 CFN, uint8 sub_flow_id, uint8 frame_type, bool crc_status, uint8 *subflow)
{
int32 I;
uint8 *ptr8;
#if defined(_EXTRA_LOG_FOR_BIT_TRUE_)
uint8 *ptr8_bak;
#endif
uint16 rabBitsCount, state;
if( (state = L1SP_GetState()) != L1SP_STATE_3G_SPEECH_ON)
{
if(state == L1SP_STATE_3G_SPEECH_CLOSING){
MD_TRC_SP3G_DL_PUT_SPEECH_FRAME_DEBUG(0);
}else {
MD_TRC_SP3G_DL_PUT_SPEECH_FRAME_DEBUG(1);
}
return;
}
ASSERT(sp3g != (SP3G_Struct*) 0);
MD_TRC_SP3G_DL_PUT_SPEECH_FRAME(sub_flow_id, frame_type, crc_status);
#if defined(_EXTRA_LOG_FOR_BIT_TRUE_)
if( sub_flow_id == 0 && (frame_type == 8 || frame_type == 25) ) {
//kal_prompt_trace(MOD_L1SP,"SP3G DL Frm %x %x %x %x %x", subflow[0], subflow[1],subflow[2],subflow[3],subflow[4]);
MD_TRC_SP3G_DL_BIT_TRUE_TASK(subflow[0], subflow[1],subflow[2],subflow[3],subflow[4]);
}
#endif
//if( frame_type == AMR_NO_DATA )
// return;
ASSERT( frame_type <= 25 );
if( sp3g_reset_flag == 1 ){
sp3g_reset_internal();
}
if( sub_flow_id > last_sub_flow_id[frame_type] ){
return;
}
if( sp3g->dl_count >= sp3g->dl_buffer_size )
{
sp3g->dl_read_idx++;
if( sp3g->dl_read_idx >= sp3g->dl_buffer_size )
sp3g->dl_read_idx = 0;
sp3g->dl_count --;
}//keep only 2 frame
ptr8 = sp3g->dl_buffer[sp3g->dl_write_idx];
#if defined(_EXTRA_LOG_FOR_BIT_TRUE_)
ptr8_bak = sp3g->dl_buffer2[sp3g->dl_write_idx];
#endif
if( sub_flow_id == 0 )
{
//frame_len = RAB_subflow[frame_type][3];
// before first RB-subflow write
*ptr8++ = frame_type;
#if defined(_EXTRA_LOG_FOR_BIT_TRUE_)
*ptr8_bak++ = frame_type;
#endif
*ptr8++ = (uint8)crc_status;
#if defined(_EXTRA_LOG_FOR_BIT_TRUE_)
*ptr8_bak++ = (uint8)crc_status;
#endif
*ptr8++ = CFN & 0xFF;
#if defined(_EXTRA_LOG_FOR_BIT_TRUE_)
*ptr8_bak++ = CFN & 0xFF;
#endif
*ptr8++ = (CFN >> 8) & 0xFF;
#if defined(_EXTRA_LOG_FOR_BIT_TRUE_)
*ptr8_bak++ = (CFN >> 8) & 0xFF;
#endif
*ptr8++ = (CFN >> 16) & 0xFF;
#if defined(_EXTRA_LOG_FOR_BIT_TRUE_)
*ptr8_bak++ = (CFN >> 16) & 0xFF;
#endif
*ptr8++ = (CFN >> 24) & 0xFF;
#if defined(_EXTRA_LOG_FOR_BIT_TRUE_)
*ptr8_bak++ = (CFN >> 24) & 0xFF;
#endif
}
else
{
if( frame_type > AMR_NO_DATA && sub_flow_id == 1 ){
//For WB-AMR, the frame type can not be differed in subflow 0,
// so that update it at subflow 1
*ptr8 = frame_type;//Range 16~25
}
//kal_prompt_trace(MOD_L1SP,"SP3G DL r=%d,w=%d,n=%d",sp3g->dl_read,sp3g->dl_write,sp3g->dl_count);
ptr8 += 6;
#if defined(_EXTRA_LOG_FOR_BIT_TRUE_)
ptr8_bak += 6;
#endif
for(I = 0 ; I < sub_flow_id ; I ++)
{
rabBitsCount = RAB_subflow[frame_type][I];
ptr8 += (rabBitsCount + 7) >> 3;
#if defined(_EXTRA_LOG_FOR_BIT_TRUE_)
ptr8_bak += (rabBitsCount + 7) >> 3;
#endif
}
}
rabBitsCount = RAB_subflow[frame_type][sub_flow_id];
for( I = 0; I < (rabBitsCount + 7) >> 3; I++ ){
#if defined(_EXTRA_LOG_FOR_BIT_TRUE_)
*ptr8++ = *subflow;
*ptr8_bak++ = *subflow++;
#else
*ptr8++ = *subflow++;
#endif
}
// after last RB-subflow write
if( sub_flow_id == last_sub_flow_id[frame_type] )
{
kal_uint8 u8CheckBufFinish = 0;
sp3g->dl_write_idx++;
if( sp3g->dl_write_idx >= sp3g->dl_buffer_size )
sp3g->dl_write_idx = 0;
#if defined(__SP3G_UL_DSP_RESYNC_CSR__)
sp3g->int_time[1] = ust_get_current_time();
if(sp3g->int_time[1] > sp3g->int_time[2]){
sp3g->int_time[0] = sp3g->int_time[2];
}
MD_TRC_SP3G_DL_TIMING(sp3g->int_time[1]/1000);
#endif
#if defined(__SP3G_DIRECT_TO_DSP__)
if(sp3g_reset_flag == 2 ){// reset done
uint32 time_diff;
time_diff = ust_get_duration_true( sp3g->int_time[4], sp3g->int_time[1] );
time_diff = ( ( time_diff / 1000 ) - sp3g->uDelW ) % 20; //Time difference between sending-resync and SP3G_DL_PUT_SPEECH_FRAME
if(time_diff == 0){ //It's too close, trigger reset
MD_TRC_SP3G_FOUND_DL_SYNC_TIMING_ERROR();
sp3g_reset_flag = 1;
}
}
if(sp3g_reset_flag == 2 ){// reset done
u8CheckBufFinish = 1;
}
#endif
sp3g->dl_count ++;
if( sp3g->dl_count == sp3g->dl_buffer_size && sp3g_reset_flag == 0 ){
sp3g_reset_flag = 2;// reset done
u8CheckBufFinish = 2;
}
#ifdef __FAKE_3G_LOOPBACK__
if(get_is_fake_3g()){
sp3g_reset_flag = 2;// reset done
u8CheckBufFinish = 1;
}
#endif
if( u8CheckBufFinish == 1 ){
#if 1//defined(__UNIFIED_ISR_LEVEL__) //Since MT6290, LISR has been depricated, and only HISR and Task are left. Therefore, to avoid affecting the OS scheduling, System Service prohibits any attempt to invoke HISR from a task level
sp3g_hisr_dl((void *)0);
#else
/* under construction !*/
#endif
} else if ( u8CheckBufFinish == 2 ){
#if 1//defined(__UNIFIED_ISR_LEVEL__)
sp3g_hisr_dl((void *)2);
#else
/* under construction !*/
#endif
MD_TRC_SP3G_DL_BUFFER_FINISH();
}
}
}
void SP3G_DL_PutSpeechFrame(uint32 CFN, uint8 sub_flow_id, uint8 frame_type, bool crc_status, uint8 *subflow)
{
kal_take_enh_mutex( sp_handover_mutex );
sub_SP3G_DL_PutSpeechFrame(CFN, sub_flow_id, frame_type, crc_status, subflow);
kal_give_enh_mutex( sp_handover_mutex );
}
typedef struct
{
kal_uint8 RSSI;
kal_uint8 RSCP;
kal_uint8 ECIO;
kal_uint8 HHO_SHO;
/* Used by UMAC */
/* Modified CRC = CRC |(S value decision)
S value decision=1 => S value < S Threshold. this frame is not reliable
S value decision =0 => S value > S Threshold. This frame is reliable
Modified CRC =0, speech good, CRC=0, S value decision =0
Modified CRC=1, CRC =1 or S value decision=1
crc_result value meaning :
0 : Modified CRC = 0
1 : Modified CRC = 1, CRC = 0
2 : Modified CRC = 1, CRC = 1
*/
kal_uint8 crc_result[3]; /* For Class A/B/C */
kal_uint32 s_value[3]; /* For Class A/B/C */
kal_int16 tpc_SIR_lta; // For recording into speech VM
kal_int16 dpdch_SIR_lta; // For recording into speech VM
kal_int16 TFCI_max_corr; // For recording into speech VM
}L1_info_struct;
void SP3G_Log_L1_Info(uint32 CFN, L1_info_struct *p_L1_Info)
{
uint32 *l1_info;
uint32 l1_data, crc_result;
kal_take_enh_mutex( sp_handover_mutex );
if(L1SP_GetState() != L1SP_STATE_3G_SPEECH_ON){
kal_give_enh_mutex( sp_handover_mutex );
return;
}
l1_info = sp3g->L1_Info[sp3g->l1_info_idx++];
sp3g->l1_info_idx &= 0x3;
l1_info[0] = CFN;
l1_data = (uint32)(p_L1_Info->RSSI) + ((uint32)(p_L1_Info->RSCP) << 8) +
((uint32)(p_L1_Info->ECIO) << 16) + ((uint32)(p_L1_Info->HHO_SHO) << 24);
crc_result = (uint32)(p_L1_Info->crc_result[0]) + ((uint32)(p_L1_Info->crc_result[1]) << 8) +
((uint32)(p_L1_Info->crc_result[2]) << 16);
l1_info[1] = l1_data;
l1_info[2] = crc_result;
l1_info[3] = p_L1_Info->s_value[0];
l1_info[4] = (uint32)p_L1_Info->tpc_SIR_lta;
l1_info[5] = (uint32)p_L1_Info->dpdch_SIR_lta;
l1_info[6] = (uint32)p_L1_Info->TFCI_max_corr;
MD_TRC_SP3G_LOG_L1_INFO(
l1_info[0], l1_info[1], crc_result, p_L1_Info->s_value[0], p_L1_Info->s_value[1],p_L1_Info->s_value[2]);
kal_give_enh_mutex( sp_handover_mutex );
}
void SP3G_Closed_Confirm( void )
{
//ASSERT( L1SP_GetState() != L1SP_STATE_3G_SPEECH_ON );
//L1SP_SetState(L1SP_STATE_3G_SPEECH_CLOSED);
}
/*====================== CS over HSPA interface ============================*/
#if defined(__CSHSPA_SUPPORT__)
void SP3GHSPA_UL_GetSpeechFrame(kal_uint8 *frame_type, kal_uint8 *rab_byte_array, kal_uint8 *len)
{
kal_uint16 frame_index, I, J, K, rabBitsCount;
kal_uint8 *ptr8, *ptr8_swap, byte_swap, bit8Data;
kal_take_enh_mutex( sp_handover_mutex );
#if 0
/* under construction !*/
/* under construction !*/
/* under construction !*/
/* under construction !*/
/* under construction !*/
/* under construction !*/
/* under construction !*/
/* under construction !*/
/* under construction !*/
/* under construction !*/
/* under construction !*/
/* under construction !*/
/* under construction !*/
/* under construction !*/
/* under construction !*/
/* under construction !*/
#else
//#if 1
sub_SP3G_UL_GetSpeechFrame(&frame_index, frame_type, rab_byte_array, len);
//reorder to AMR IF1
if( *frame_type != AMR_NO_DATA && *frame_type != 25 && *frame_type != AMR_SID_FRAME )
{
ptr8 = rab_byte_array;
ptr8_swap = rab_byte_array;
byte_swap = *ptr8_swap;
*ptr8 = 0;
K = 0;
for( I = 0 ; I < 3 ; I++ ){
rabBitsCount = RAB_subflow[*frame_type][I];
for( J = 0; J < rabBitsCount ; J++, K++ ){
bit8Data = (byte_swap & RAB_Order[J & 7])? RAB_Order[K & 7] : 0;
*ptr8 |= bit8Data;
if( (J&7) == 7 ){
ptr8_swap++;
byte_swap = *ptr8_swap;
}
if( (K&7) == 7 ){
ptr8++;
*ptr8 = 0;
}
}
if( (J&7) != 0 ){ // avoid false advance a byte
ptr8_swap++;
byte_swap = *ptr8_swap;
}
}
//recalculate rab length
rabBitsCount = 0;
for( I = 0 ; I < 3 ; I++ )
rabBitsCount += RAB_subflow[*frame_type][I];
*len = ((rabBitsCount+7)>>3);
}
#endif
MD_TRC_SP3G_HSPA_UL_GET_SPEECH_FRAME(*frame_type, *len, rab_byte_array[0], rab_byte_array[1]);
kal_give_enh_mutex( sp_handover_mutex );
}
kal_uint8 subflow_null[32];
void SP3GHSPA_DL_PutSpeechFrame(kal_uint32 CFN, kal_uint8 frame_type, kal_bool crc_status, kal_uint8 *subflow)
{
kal_take_enh_mutex( sp_handover_mutex );
if(NULL != subflow) {
MD_TRC_SP3G_HSPA_DL_PUT_SPEECH_FRAME(frame_type, CFN, crc_status, subflow[0], subflow[1]);
}
else {
MD_TRC_SP3G_HSPA_DL_PUT_SPEECH_FRAME(frame_type, CFN, crc_status, 0, 0);
}
if( frame_type != AMR_NO_DATA && frame_type != 25 && frame_type != AMR_SID_FRAME ){
kal_uint16 I, J, K, rabBitsCount;
kal_uint8 *ptr8, *ptr8_swap, byte_swap, bit8Data;
K = 0;
ptr8_swap = subflow;
byte_swap = *ptr8_swap;
for( I = 0 ; I < 3 ; I++ ){
rabBitsCount = RAB_subflow[frame_type][I];
if( rabBitsCount == 0 )
break;
ptr8 = &sp3g->dl_subflow[0];
*ptr8 = 0;//reset
for( J = 0; J < rabBitsCount ; J++, K++ ){
bit8Data = (byte_swap & RAB_Order[K & 7])? RAB_Order[J & 7] : 0;
*ptr8 |= bit8Data;
if( (J&7) == 7 ){
ptr8++;
*ptr8 = 0;
}
if( (K&7) == 7 ){
ptr8_swap++;
byte_swap = *ptr8_swap;
}
}
sub_SP3G_DL_PutSpeechFrame(CFN, I, frame_type, crc_status, sp3g->dl_subflow);
}
} else {
if(NULL != subflow) {
sub_SP3G_DL_PutSpeechFrame(CFN, 0, frame_type, crc_status, subflow);
}
else {
sub_SP3G_DL_PutSpeechFrame(CFN, 0, frame_type, crc_status, subflow_null);
}
}
kal_give_enh_mutex( sp_handover_mutex );
}
void SP3GHSPA_DL_SetMaxCsDelay(kal_uint8 max_cs_delay)
{
MD_TRC_SP3G_HSPA_DL_MAX_CS_DELAY(max_cs_delay);
sp3g_max_cs_delay = (max_cs_delay + 19) / 20;
ASSERT(sp3g_max_cs_delay <= 10);
if( sp3g_max_cs_delay < 2 )
sp3g_max_cs_delay = 2;
#if 1
if(L1SP_GetState() != L1SP_STATE_3G_SPEECH_ON || sp3g == NULL )
return;
kal_take_spinlock(sp3g_spinlockID, KAL_INFINITE_WAIT);
//Already in speech, allow extend buffer size
if(sp3g->dl_buffer_size < sp3g_max_cs_delay){
sp3g->dl_buffer_size = sp3g_max_cs_delay;
}
kal_give_spinlock(sp3g_spinlockID);
#endif
}
#endif // if defined(__CSHSPA_SUPPORT__)
#endif // __UMTS_RAT__