blob: 5b1b0fc2315118746e45e93b0b17005e08ffaeeb [file] [log] [blame]
yu.dongc33b3072024-08-21 23:14:49 -07001#include "kal_public_api.h"
2#include "kal_general_types.h"
3#include "sync_data.h"
4
5#include "kal_trace.h"
6#include "l1sp_trc.h"
7
8#include "l1audio.h"
9#include "am.h"
10//#include "speech_def.h"
11//#include "afe_def.h" // for output device setting
12//#include "sp_drv.h"
13
14#include "sal_exp.h"
15#include "bgSnd.h"
16
17//#define DSP_BGS_UP_DOWN_INT_SEPERATE
18
19
20#define BGSND_BUFFER_LEN_NB (160) //unit is sample (16bit)
21#define BGSND_BUFFER_LEN_WB (320) //unit is sample (16bit)
22#define BGSND_BUFFER_LEN_SWB (640) //unit is sample (16bit)
23#define BGSND_BUFFER_LEN_FB (960) //unit is sample (16bit)
24
25#define BGSND_BUFFER_LEN (BGSND_BUFFER_LEN_SWB)
26
27#define MAX_NUM_BGSND_PROCESS (2)
28
29
30//================= DSP BGSND INTERFACE ====================
31
32typedef enum {
33 DSP_BGSND_STATE_IDLE = 0,
34 DSP_BGSND_STATE_RUN,
35 DSP_BGSND_STATE_STOPPING,
36}DSP_BGSND_STATE_TYPE;
37
38typedef struct{
39 DSP_BGSND_STATE_TYPE state;
40
41 bool fSph[MAX_NUM_BGSND_PROCESS];
42 uint16 gain[MAX_NUM_BGSND_PROCESS];
43
44 void (*Ext_Hisr[MAX_NUM_BGSND_PROCESS])(void);
45}DSP_BKGSND_T;
46
47DSP_BKGSND_T DSP_BGSnd;
48
49//================= Extended BGSND INTERFACE ====================
50#define MAX_SIZE_EXT_BGSND_SRC (2) // AP bkgsnd + VoLTE UL bkgsnd
51#define EXT_BGSND_BUF_PTR_DIFF (2)
52#define EXT_BGSND_SRC_BUF_SIZE ((BGSND_BUFFER_LEN) * 2 + EXT_BGSND_BUF_PTR_DIFF) //buffering 2 frames
53
54
55#define MAX_LEVEL_EXT_BGSND_GAIN (7)
56
57typedef struct{
58 EXT_SRC_STATE_TYPE state[MAX_NUM_BGSND_PROCESS];
59 void (*offHdr)();//(int id); //TODO Trigger MED to close DSP bgsnd
60 void (*Hdr[MAX_NUM_BGSND_PROCESS])(void); // under HISR
61 uint16 dspLastSample[MAX_NUM_BGSND_PROCESS];
62
63 uint32 len_WriteSrcBuffer_this_time;
64 //event handling
65 //void (*EventHandler)(void);
66 //void *event_data;
67
68 //gain handling
69 bool fSph[MAX_NUM_BGSND_PROCESS];
70 uint16 gain[MAX_NUM_BGSND_PROCESS];
71
72 //buffer handling
73 uint32 bufSize[MAX_NUM_BGSND_PROCESS], bufRead[MAX_NUM_BGSND_PROCESS], bufWrite[MAX_NUM_BGSND_PROCESS];
74 uint32 bufDataCount[MAX_NUM_BGSND_PROCESS];
75 uint16 buffer[MAX_NUM_BGSND_PROCESS][EXT_BGSND_SRC_BUF_SIZE];
76
77}EXT_BGSND_SRC_T;
78
79typedef struct{
80 bool is_used[MAX_SIZE_EXT_BGSND_SRC];
81 bool is_send_event[MAX_SIZE_EXT_BGSND_SRC];
82 EXT_BGSND_SRC_T src[MAX_SIZE_EXT_BGSND_SRC];
83 uint16 num_src_used;
84
85 uint16 buffer[MAX_NUM_BGSND_PROCESS][BGSND_BUFFER_LEN]; //accumulate all sources multiplied by gains into this buffer
86
87 uint16 aud_id;
88 bool skip_hisr;
89 kal_spinlockid bgs_spinlockID;
90}EXT_BGSND_T;
91
92static EXT_BGSND_T Ext_BGSnd;
93
94void EXT_BGSND_Hisr(BGSND_PROCESS_TYPE type);
95
96/*
97int has_ul = 0;
98int has_dl = 0;
99int ul_data[320], dl_data[320];*/
100
101
102static void DSP_BGSND_INIT()
103{
104 MD_TRC_DSP_BGSND_INIT_ENTER();
105 memset(&DSP_BGSnd, 0, sizeof(DSP_BKGSND_T));
106 //has_ul = has_dl = 0;
107 MD_TRC_DSP_BGSND_INIT_LEAVE();
108}
109
110static void DSP_BGSND_ConfigMixer(kal_bool bSPHFlag, kal_int8 SNDGain, BGSND_PROCESS_TYPE type)
111{
112 MD_TRC_DSP_BGSND_CONFIGMIXER_ENTER();
113 MD_TRC_DSP_BGSND_CONFIGMIXER_BGSND_PROCESS_TYPE(type, bSPHFlag, SNDGain);
114
115 ASSERT(SNDGain>=0 && SNDGain<=7);
116 if( SNDGain == 0)
117 DSP_BGSnd.gain[type] = 0;
118 else {
119 DSP_BGSnd.gain[type] = (kal_int16)(32767 >> (7 - SNDGain));
120 }
121 DSP_BGSnd.fSph[type] = bSPHFlag;
122 MD_TRC_DSP_BGSND_CONFIGMIXER_LEAVE();
123}
124
125static void DSP_BGSND_UpdateMixer() // private
126{
127 MD_TRC_DSP_BGSND_UPDATEMIXER_ENTER();
128 if ( AM_IsSpeechOn() || AM_IsVoIPOn()) {
129 SAL_Bgsnd_Config(DSP_BGSnd.gain[BGSND_UL_PROCESS], DSP_BGSnd.gain[BGSND_DL_PROCESS], DSP_BGSnd.fSph[BGSND_UL_PROCESS], DSP_BGSnd.fSph[BGSND_DL_PROCESS]);
130 } else {
131 //When enable BT, spe_setSpeechMode() will do Speech Off and Speech On. This function may run between Off and ON, so do not use ASSERT().
132 //ASSERT(false);
133 SAL_Bgsnd_Config(DSP_BGSnd.gain[BGSND_UL_PROCESS], DSP_BGSnd.gain[BGSND_DL_PROCESS], 0, 0);
134 }
135 MD_TRC_DSP_BGSND_UPDATEMIXER_LEAVE();
136}
137
138
139void DSP_BGSND_Stop(void)
140{
141 MD_TRC_DSP_BGSND_STOP_ENTER();
142 DSP_BGSnd.state = DSP_BGSND_STATE_STOPPING;
143 { //turn off DSP BGSND
144 uint32 I;
145 if(SAL_Bgsnd_IsRunning())
146 SAL_Bgsnd_SetFinal();
147 for ( I = 0; ; I++ ) {
148 if ( SAL_Bgsnd_IsIdle()) /* DSP returns to idle state */
149 break;
150 ASSERT_REBOOT( I < 20 );
151 kal_sleep_task( AUD_1TICK(2) );
152 }
153
154 AM_SND_PlaybackOff( true );
155 }
156
157#ifdef DSP_BGS_UP_DOWN_INT_SEPERATE
158 L1Audio_UnhookHisrHandler(D2C_SOUND_EFFECT_INT_ID_DL);
159 L1Audio_UnhookHisrHandler(D2C_SOUND_EFFECT_INT_ID_UL);
160#else
161 L1Audio_UnhookHisrHandler(D2C_SOUND_EFFECT_INT_ID_DL);
162#endif
163 DSP_BGSnd.state = DSP_BGSND_STATE_IDLE;
164 MD_TRC_DSP_BGSND_STOP_LEAVE();
165}
166
167
168/*
169static kal_uint16 tempMicData[320]
170 // = { 0x4808,0x85, 0x156,0, 0x4,0, 0x146,0x9000,
171 = {
172 0xfff4,0x5a7a, 0x7fff, 0x5a8a, 0x000d, 0xa587, 0x8001, 0xa575, 0xfff4, 0x5a79,
173 0x7fff, 0x5a8a, 0x000d, 0xa587, 0x8001, 0xa575, 0xfff4, 0x5a7a, 0x7fff, 0x5a8a,
174 0x000d, 0xa587, 0x8001, 0xa575, 0xfff4, 0x5a79, 0x7fff, 0x5a8a, 0x000d, 0xa587,
175 0x8001, 0xa575, 0xfff4, 0x5a7a, 0x7fff, 0x5a8a, 0x000d, 0xa587, 0x8001, 0xa575,
176 0xfff4, 0x5a79, 0x7fff, 0x5a8a, 0x000d, 0xa587, 0x8001, 0xa575, 0xfff4, 0x5a78,
177 0x7fff, 0x5a8a, 0x000d, 0xa587, 0x8001, 0xa576, 0xfff3, 0x5a79, 0x7fff, 0x5a8b,
178 0x000d, 0xa587, 0x8001, 0xa575, 0xfff4, 0x5a79, 0x7fff, 0x5a8a, 0x000c, 0xa588,
179 0x8001, 0xa576, 0xfff4, 0x5a79, 0x7fff, 0x5a8b, 0x000d, 0xa587, 0x8001, 0xa575,
180
181 0xfff4,0x5a7a, 0x7fff, 0x5a8a, 0x000d, 0xa587, 0x8001, 0xa575, 0xfff4, 0x5a79,
182 0x7fff, 0x5a8a, 0x000d, 0xa587, 0x8001, 0xa575, 0xfff4, 0x5a7a, 0x7fff, 0x5a8a,
183 0x000d, 0xa587, 0x8001, 0xa575, 0xfff4, 0x5a79, 0x7fff, 0x5a8a, 0x000d, 0xa587,
184 0x8001, 0xa575, 0xfff4, 0x5a7a, 0x7fff, 0x5a8a, 0x000d, 0xa587, 0x8001, 0xa575,
185 0xfff4, 0x5a79, 0x7fff, 0x5a8a, 0x000d, 0xa587, 0x8001, 0xa575, 0xfff4, 0x5a78,
186 0x7fff, 0x5a8a, 0x000d, 0xa587, 0x8001, 0xa576, 0xfff3, 0x5a79, 0x7fff, 0x5a8b,
187 0x000d, 0xa587, 0x8001, 0xa575, 0xfff4, 0x5a79, 0x7fff, 0x5a8a, 0x000c, 0xa588,
188 0x8001, 0xa576, 0xfff4, 0x5a79, 0x7fff, 0x5a8b, 0x000d, 0xa587, 0x8001, 0xa575,
189
190 0xfff4,0x5a7a, 0x7fff, 0x5a8a, 0x000d, 0xa587, 0x8001, 0xa575, 0xfff4, 0x5a79,
191 0x7fff, 0x5a8a, 0x000d, 0xa587, 0x8001, 0xa575, 0xfff4, 0x5a7a, 0x7fff, 0x5a8a,
192 0x000d, 0xa587, 0x8001, 0xa575, 0xfff4, 0x5a79, 0x7fff, 0x5a8a, 0x000d, 0xa587,
193 0x8001, 0xa575, 0xfff4, 0x5a7a, 0x7fff, 0x5a8a, 0x000d, 0xa587, 0x8001, 0xa575,
194 0xfff4, 0x5a79, 0x7fff, 0x5a8a, 0x000d, 0xa587, 0x8001, 0xa575, 0xfff4, 0x5a78,
195 0x7fff, 0x5a8a, 0x000d, 0xa587, 0x8001, 0xa576, 0xfff3, 0x5a79, 0x7fff, 0x5a8b,
196 0x000d, 0xa587, 0x8001, 0xa575, 0xfff4, 0x5a79, 0x7fff, 0x5a8a, 0x000c, 0xa588,
197 0x8001, 0xa576, 0xfff4, 0x5a79, 0x7fff, 0x5a8b, 0x000d, 0xa587, 0x8001, 0xa575,
198
199 0xfff4,0x5a7a, 0x7fff, 0x5a8a, 0x000d, 0xa587, 0x8001, 0xa575, 0xfff4, 0x5a79,
200 0x7fff, 0x5a8a, 0x000d, 0xa587, 0x8001, 0xa575, 0xfff4, 0x5a7a, 0x7fff, 0x5a8a,
201 0x000d, 0xa587, 0x8001, 0xa575, 0xfff4, 0x5a79, 0x7fff, 0x5a8a, 0x000d, 0xa587,
202 0x8001, 0xa575, 0xfff4, 0x5a7a, 0x7fff, 0x5a8a, 0x000d, 0xa587, 0x8001, 0xa575,
203 0xfff4, 0x5a79, 0x7fff, 0x5a8a, 0x000d, 0xa587, 0x8001, 0xa575, 0xfff4, 0x5a78,
204 0x7fff, 0x5a8a, 0x000d, 0xa587, 0x8001, 0xa576, 0xfff3, 0x5a79, 0x7fff, 0x5a8b,
205 0x000d, 0xa587, 0x8001, 0xa575, 0xfff4, 0x5a79, 0x7fff, 0x5a8a, 0x000c, 0xa588,
206 0x8001, 0xa576, 0xfff4, 0x5a79, 0x7fff, 0x5a8b, 0x000d, 0xa587, 0x8001, 0xa575
207
208};*/
209
210
211void DSP_BGSND_Hisr(void * param)
212{
213 int i;
214 uint16 *src_buf;
215 volatile uint16 *dst_buf;
216
217 BGSND_PROCESS_TYPE type = (BGSND_PROCESS_TYPE) param;
218
219 MD_TRC_DSP_BGSND_HISR_ENTER();
220
221 MD_TRC_DSP_BGSND_HISR_BGSND_PROCESS_TYPE(type, DSP_BGSnd.state);
222
223 ASSERT( type == BGSND_DL_PROCESS || type == BGSND_UL_PROCESS );
224
225 if ((DSP_BGSND_STATE_RUN != DSP_BGSnd.state)){
226 return;
227 }
228
229 if(!SAL_Bgsnd_IsRunning())
230 return;
231
232 DSP_BGSnd.Ext_Hisr[type]();
233 src_buf = Ext_BGSnd.buffer[type];
234
235 dst_buf = src_buf;
236 //set up the DSP address and pointers
237 switch(type){
238 case BGSND_DL_PROCESS:
239 //dst_buf_len = SAL_Bgsnd_GetDataLen_DL();
240 dst_buf = SAL_Bgsnd_GetBuf_DL();
241 break;
242 case BGSND_UL_PROCESS:
243 //dst_buf_len = SAL_Bgsnd_GetDataLen_UL();
244 dst_buf = SAL_Bgsnd_GetBuf_UL();
245 break;
246 }
247
248 for(i=0; i<BGSND_BUFFER_LEN_SWB; i++){
249 //*dst_buf++ = *src_buf++;
250 dst_buf[i] = src_buf[i];
251 }
252 Data_Sync_Barrier();
253
254 MD_TRC_DSP_BGSND_HISR_LEAVE();
255}
256#if !defined(DSP_BGS_UP_DOWN_INT_SEPERATE)
257void DSP_BGSND_Shared_Hisr_DL_UL(void * param)
258{
259 MD_TRC_DSP_BGSND_SHARED_HISR_DL_UL_ENTER();
260 DSP_BGSND_Hisr((void * )BGSND_UL_PROCESS);
261 DSP_BGSND_Hisr((void * )BGSND_DL_PROCESS);
262 MD_TRC_DSP_BGSND_SHARED_HISR_DL_UL_LEAVE();
263}
264#endif
265
266static void DSP_BGSND_Start(void (*Ext_DLHisr)(void),
267 void (*Ext_ULHisr)(void))
268{
269 MD_TRC_DSP_BGSND_START_ENTER();
270 ASSERT(AM_IsSpeechOn() || AM_IsVoIPOn());
271
272 DSP_BGSnd.Ext_Hisr[BGSND_DL_PROCESS] = Ext_DLHisr;
273 DSP_BGSnd.Ext_Hisr[BGSND_UL_PROCESS] = Ext_ULHisr;
274
275#ifdef DSP_BGS_UP_DOWN_INT_SEPERATE
276 L1Audio_HookHisrHandler(D2C_SOUND_EFFECT_INT_ID_DL, DSP_BGSND_Hisr, (void *)BGSND_DL_PROCESS);
277 L1Audio_HookHisrHandler(D2C_SOUND_EFFECT_INT_ID_UL, DSP_BGSND_Hisr, (void *)BGSND_UL_PROCESS);
278#else
279 L1Audio_HookHisrHandler(D2C_SOUND_EFFECT_INT_ID_DL, DSP_BGSND_Shared_Hisr_DL_UL, 0);
280#endif
281
282 // gain setting and update
283 // Although these settings are allowed to modify during run time,
284 // extended bgsnd should be fixed because the changes of volume from
285 // each sources are calculated in MCU side.
286 DSP_BGSND_ConfigMixer(KAL_TRUE, 7, BGSND_UL_PROCESS);
287 DSP_BGSND_ConfigMixer(KAL_TRUE, 7, BGSND_DL_PROCESS);
288
289 DSP_BGSND_UpdateMixer();
290 { //turn on DSP BGSND
291 uint32 I;
292 AM_SND_PlaybackOn();
293 SAL_Bgsnd_SetInit();
294 for( I = 0; ; I++ ) {
295 if(SAL_Bgsnd_IsRunning())
296 break;
297 ASSERT_REBOOT( I < 20 );
298 kal_sleep_task( AUD_1TICK(2) );
299 }
300 }
301
302 DSP_BGSnd.state = DSP_BGSND_STATE_RUN;
303 MD_TRC_DSP_BGSND_START_LEAVE();
304}
305/*=============== Ext BGSND interface ========= */
306
307uint32 EXT_BGSND_init()
308{
309 MD_TRC_EXT_BGSND_INIT_ENTER();
310 DSP_BGSND_INIT();
311 memset((void *)&Ext_BGSnd, 0, sizeof(EXT_BGSND_T));
312 // get audio ID
313 Ext_BGSnd.aud_id = L1Audio_GetAudioID();
314 Ext_BGSnd.skip_hisr = 0;
315 Ext_BGSnd.bgs_spinlockID = kal_create_spinlock("bgs_spinlock");
316 MD_TRC_EXT_BGSND_INIT_LEAVE();
317// L1Audio_SetEventHandler( Ext_BGSnd.aud_id, (L1Audio_EventHandler) EXT_BGSND_EventHandler );
318 return 0;
319}
320
321void EXT_BGSND_DLHisr(void);
322void EXT_BGSND_ULHisr(void);
323
324
325uint32 EXT_BGSND_Start(void (*offHdr)(void),
326 void (*DLHisr)(void), //move data from src -> ext
327 void (*ULHisr)(void), //move data from src -> ext
328 kal_int8 DLSNDGain,
329 kal_int8 ULSNDGain /*,
330 void (*EventHandler)(void)*/)
331{
332 int i, j;
333
334 Ext_BGSnd.skip_hisr = 0;
335 MD_TRC_EXT_BGSND_START_ENTER();
336
337 ASSERT(!(NULL==DLHisr && NULL==ULHisr));
338 ASSERT(NULL!=offHdr); //without this, we cannot stop DSP BGSND
339
340 for(i=0; i<MAX_SIZE_EXT_BGSND_SRC; i++){
341 MD_TRC_EXT_BGSND_START_DEBUG1(i);
342 if(!Ext_BGSnd.is_used[i]){
343 MD_TRC_EXT_BGSND_START_DEBUG2(i);
344 EXT_BGSND_SRC_T *pSrc = &Ext_BGSnd.src[i];
345 memset(pSrc, 0, sizeof(EXT_BGSND_SRC_T));
346
347 pSrc->Hdr[BGSND_DL_PROCESS] = DLHisr;
348 pSrc->Hdr[BGSND_UL_PROCESS] = ULHisr;
349 pSrc->offHdr = offHdr;
350 for(j=0; j<MAX_NUM_BGSND_PROCESS; j++){//TODO temp solution
351
352 pSrc->state[j] = EXT_SRC_STATE_RUN;
353 //pSrc->fSph[j] = true; //TODO
354 //pSrc->gain[j] = 7; //TODO
355
356 // buffer reset
357 memset(pSrc->buffer[j], 0, sizeof(kal_uint16)*EXT_BGSND_SRC_BUF_SIZE);
358 pSrc->bufSize[j] = EXT_BGSND_SRC_BUF_SIZE;
359 pSrc->bufRead[j] = 0;
360 pSrc->bufWrite[j] = EXT_BGSND_BUF_PTR_DIFF;
361 pSrc->bufDataCount[j] = 0;
362 }
363 if(AM_IsSpeechOn() || AM_IsVoIPOn()){
364 EXT_BGSND_ConfigMixer(i, true, DLSNDGain, BGSND_DL_PROCESS);
365 EXT_BGSND_ConfigMixer(i, true, ULSNDGain, BGSND_UL_PROCESS);
366 }else{
367 EXT_BGSND_ConfigMixer(i, false, DLSNDGain, BGSND_DL_PROCESS);
368 EXT_BGSND_ConfigMixer(i, false, ULSNDGain, BGSND_UL_PROCESS);
369 }
370 Ext_BGSnd.is_used[i] = true;
371 if( 0 == Ext_BGSnd.num_src_used++){
372 MD_TRC_EXT_BGSND_START_SELECTED_SRC(i, Ext_BGSnd.num_src_used);
373 // lock DSP for sherif writing.
374 L1Audio_SetFlag( Ext_BGSnd.aud_id ); // REIMIND: Before Locking SleepMode, to access DSP sherrif tasks much time. So access DSP must be after SetFlag1
375 DSP_BGSND_Start(EXT_BGSND_DLHisr, EXT_BGSND_ULHisr);
376 }
377 MD_TRC_EXT_BGSND_START_DEBUG3(i);
378 break;
379 }
380 MD_TRC_EXT_BGSND_START_DEBUG4(i);
381 }
382 MD_TRC_EXT_BGSND_START_DEBUG5(i);
383 ASSERT(i < MAX_SIZE_EXT_BGSND_SRC);
384
385 MD_TRC_EXT_BGSND_START_LEAVE();
386 return i;
387}
388
389void EXT_BGSND_Flush(uint32 id) //under MED Task, triggered by the AP message, BGSND_OFF
390{ //flush buffer first, and then close it ; HISR will consume the buffer until it is empty.
391 int j;
392 MD_TRC_EXT_BGSND_FLUSH_ENTER();
393 ASSERT(Ext_BGSnd.is_used[id]);
394
395 EXT_BGSND_SRC_T *pSrc = &Ext_BGSnd.src[id];
396 MD_TRC_EXT_BGSND_FLUSH_ID(id);
397
398 for(j=0; j<MAX_NUM_BGSND_PROCESS; j++){
399 if(EXT_SRC_STATE_RUN == pSrc->state[j]){
400 pSrc->state[j] = EXT_SRC_STATE_FLUSHING;
401 }else{//prevent double entry to the procedure of flushing
402 MD_TRC_EXT_BGSND_FLUSH_STATE(pSrc->state[j]);
403 }
404 }
405 MD_TRC_EXT_BGSND_FLUSH_LEAVE();
406}
407
408// under MED Task, triggered by the EXT_HISR when UL/DL buffer flushes completely.
409// Even if many src would like to close DSP BGSND, we don't think about the race condition since the request of closing is processed by MED's queue.
410// Due to it may force close. so status check nees to remove.
411void EXT_BGSND_Close(uint32 id)
412{
413 MD_TRC_EXT_BGSND_CLOSE_ENTER();
414 ASSERT(Ext_BGSnd.is_used[id]);
415 EXT_BGSND_SRC_T *pSrc = &Ext_BGSnd.src[id];
416
417 // ASSERT(EXT_SRC_STATE_FLUSHING_OVER==pSrc->state[BGSND_DL_PROCESS]);
418 // ASSERT(EXT_SRC_STATE_FLUSHING_OVER==pSrc->state[BGSND_UL_PROCESS]);
419 MD_TRC_EXT_BGSND_CLOSE_SELECTED_SRC(id, Ext_BGSnd.num_src_used);
420
421 { //flush buffer first, and then close it // buffer reset
422 Ext_BGSnd.is_used[id] = false; // [IMPORTANT] HISR using the information to check BGS is under use or not. so put the line before clean all information.
423 Ext_BGSnd.num_src_used--;
424 }
425
426 pSrc->state[BGSND_DL_PROCESS] = pSrc->state[BGSND_UL_PROCESS] = EXT_SRC_STATE_STOPPING;
427
428 if( 0 == Ext_BGSnd.num_src_used){
429 DSP_BGSND_Stop();
430 L1Audio_ClearFlag( Ext_BGSnd.aud_id );
431
432 }
433 pSrc->state[BGSND_DL_PROCESS] = pSrc->state[BGSND_UL_PROCESS] = EXT_SRC_STATE_IDLE;
434 MD_TRC_EXT_BGSND_CLOSE_LEAVE();
435}
436
437void EXT_BGSND_DLHisr(void)
438{
439 MD_TRC_EXT_BGSND_DLHISR_ENTER();
440 EXT_BGSND_Hisr(BGSND_DL_PROCESS);
441 MD_TRC_EXT_BGSND_DLHISR_LEAVE();
442}
443
444void EXT_BGSND_ULHisr(void)
445{
446 MD_TRC_EXT_BGSND_ULHISR_ENTER();
447 EXT_BGSND_Hisr(BGSND_UL_PROCESS);
448 MD_TRC_EXT_BGSND_ULHISR_LEAVE();
449}
450
451/*static*/ int32 EXT_BGSND_GetDataCount(uint32 id, BGSND_PROCESS_TYPE type)
452{
453 int32 count = 0;
454 MD_TRC_EXT_BGSND_GETDATACOUNT_ENTER();
455
456 ASSERT( type == BGSND_DL_PROCESS || type == BGSND_UL_PROCESS );
457 EXT_BGSND_SRC_T *pSrc = &Ext_BGSnd.src[id];
458
459 count = pSrc->bufDataCount[type];
460/* for(j=0; j<MAX_BGSND_BUFFER_PROCESS_BIT; j++){
461 if(type & (1<<j)){
462 type = 1<<j;
463 if(pSrc->bufWrite[type]<pSrc->bufRead[type]){
464 count = (pSrc->bufSize[type] - EXT_BGSND_BUF_PTR_DIFF)+pSrc->bufWrite[type] - pSrc->bufRead[type];
465 } else {
466 count = pSrc->bufWrite[type] - pSrc->bufRead[type];
467 }
468 }
469 }
470
471 if( count > EXT_BGSND_BUF_PTR_DIFF) {
472 count -= EXT_BGSND_BUF_PTR_DIFF;
473 } else {
474 count = 0;
475 }
476
477 if(count&1){
478 count = count -1;
479 }*/
480 MD_TRC_EXT_BGSND_GETDATACOUNT_COUNT(count);
481 MD_TRC_EXT_BGSND_GETDATACOUNT_LEAVE();
482 return count;
483}
484
485void EXT_BGSND_Hisr(BGSND_PROCESS_TYPE type)
486{
487 int i;
488 if(Ext_BGSnd.skip_hisr){
489 return;
490 }
491
492 MD_TRC_EXT_BGSND_HISR_ENTER();
493 MD_TRC_EXT_BGSND_HISR_BGSND_PROCESS_TYPE(type);
494
495 //reset buffer data
496 if( BGSND_DL_PROCESS == type){// align DL timing
497 for(i=0; i<BGSND_BUFFER_LEN; i++){ // To do , reduce computation
498 Ext_BGSnd.buffer[BGSND_DL_PROCESS][i] = 0;
499 }
500 for(i=0; i<BGSND_BUFFER_LEN; i++){
501 Ext_BGSnd.buffer[BGSND_UL_PROCESS][i] = 0;
502 }
503 }
504 DSP_BGSND_UpdateMixer();
505 for(i=0; i<MAX_SIZE_EXT_BGSND_SRC; i++){
506 EXT_BGSND_SRC_T *pSrc = &Ext_BGSnd.src[i];
507 if(Ext_BGSnd.is_used[i]){
508 MD_TRC_EXT_BGSND_HISR_SELECTED_SRC(i, pSrc->state[type]);
509
510 //point 1
511 if(pSrc->Hdr[type]){ // Point1 must be before point2 since it is expected that in pSrc->Hdr[type](), len_WriteSrcBuffer_this_time will be updated by EXT_BGSND_WriteSrcBuffer
512 pSrc->Hdr[type](); // Each Hdr should update buffer[BGSND_ L_PROCESS] by EXT_BGSND_Buf_Add
513 }
514
515 //point 2
516 if(EXT_SRC_STATE_FLUSHING == pSrc->state[type]){ // FLUSHING --> FLUSHING_OVER
517 //if(EXT_BGSND_GetDataCount(i, type) <= EXT_BGSND_BUF_PTR_DIFF){
518 if( (0 == pSrc->len_WriteSrcBuffer_this_time) && (EXT_BGSND_GetDataCount(i, type) < BGSND_BUFFER_LEN) ){
519 MD_TRC_EXT_BGSND_HISR_EXT_SRC_STATE_FLUSHING_OVER(i, type);
520 pSrc->state[type] = EXT_SRC_STATE_FLUSHING_OVER;
521 if(EXT_SRC_STATE_FLUSHING_OVER == pSrc->state[1-type]){ // 1-type is just for the opposite. DL <-> UL
522 MD_TRC_EXT_BGSND_HISR_ENTER_SRC_OFFHDR(i);
523 Ext_BGSnd.skip_hisr = 1;
524 pSrc->offHdr(); //FLUSHING_OVER --> STOPPING
525 MD_TRC_EXT_BGSND_HISR_LEAVE_SRC_OFFHDR(i);
526 MD_TRC_EXT_BGSND_HISR_FLUSH_SRC_OFFHDR_COMPLETELY(i);
527 }else{//wait DL's flushing
528 MD_TRC_EXT_BGSND_HISR_WAIT_SRC_HDR_TO_FLUSH_COMPLETELY(i);
529 }
530 }else{
531 MD_TRC_EXT_BGSND_HISR_FLUSHING(i, type, EXT_BGSND_GetDataCount(i, type));
532 }
533 }else{
534 MD_TRC_EXT_BGSND_HISR_NOT_FLUSHING(i, type, pSrc->state[type]);
535 }
536
537
538
539 }else{
540 MD_TRC_EXT_BGSND_HISR_HDR_IS_NOT_USED(i);
541 }
542 pSrc->len_WriteSrcBuffer_this_time = 0;
543 }
544 MD_TRC_EXT_BGSND_HISR_LEAVE();
545}
546
547/*
548void EXT_BGSND_Buf_Add(uint32 id, uint16* src_buf, int src_len, BGSND_PROCESS_TYPE type) // write into ext buffer
549{
550 int i;
551 uint16 *dst_buf;
552 EXT_BGSND_SRC_T *pSrc;
553
554 MD_TRC_BGSND_DSP_BGSND_BUF_ADD(id, src_len, type);
555
556 ASSERT(Ext_BGSnd.is_used[id]);
557 pSrc = &Ext_BGSnd.src[id];
558
559 ASSERT( BGSND_BUFFER_LEN == src_len);//must be wb
560 ASSERT( type == BGSND_DL_PROCESS || type == BGSND_UL_PROCESS );
561
562 { // DL
563 dst_buf = Ext_BGSnd.buffer[type];
564
565 for(i=0; i<src_len; i++){//accumulate DSP_DLBuffer
566 if( src_buf[i] < (0x1111111111111111 - dst_buf[i])){ //limiter
567 dst_buf[i] += src_buf[i];
568 }else{
569 MD_TRC_BKGSND_DSP_BUF_ADD_BUF(i, src_buf[i], i, dst_buf[i]);
570 }
571 }
572 }
573}*/
574
575/*
576uint32 EXT_BGSND_SetEvent(uint32 id, void *data )
577{
578 ASSERT(Ext_BGSnd.is_used[id] && Ext_BGSnd.src[id].EventHandler);
579 is_send_event[id] = true;
580 Ext_BGSnd.src[i].event_data = data;
581 L1Audio_SetEvent(Ext_BGSnd.src.aud_id, NULL);
582}
583
584void EXT_BGSND_EventHandler(void)
585{
586 for(i=0; i<MAX_SIZE_EXT_BGSND_SRC; i++){//dispatch the event
587 if(Ext_BGSnd.is_send_event[i] && Ext_BGSnd.src[i].EventHandler){
588 Ext_BGSnd.src[i].EventHandler(Ext_BGSnd.src[i].event_data);
589 Ext_BGSnd.is_send_event[i] = false;
590 }
591 }
592}
593*/
594
595void EXT_BGSND_WriteSrcBuffer(uint32 id, kal_uint8 *srcBuf, kal_int32 bufLen, BGSND_PROCESS_TYPE type)
596{
597 int32 freeLen;
598 int32 srcBufLen = bufLen >> 1; // unit: 8bits -> 16bits
599 int32 currentRead;
600 EXT_BGSND_SRC_T *pSrc = &Ext_BGSnd.src[id];
601
602 MD_TRC_EXT_BGSND_WRITESRCBUFFER_ENTER();
603 kal_take_spinlock(Ext_BGSnd.bgs_spinlockID, KAL_INFINITE_WAIT);
604 currentRead = pSrc->bufRead[type];
605
606 pSrc->len_WriteSrcBuffer_this_time = bufLen;
607
608 if(currentRead > pSrc->bufWrite[type]) { // one segment
609
610 freeLen = pSrc->bufSize[type] - pSrc->bufDataCount[type] - EXT_BGSND_BUF_PTR_DIFF;
611
612 MD_TRC_L1SND_WRITE_DATA(1, id, type, srcBufLen, freeLen, pSrc->bufRead[type], pSrc->bufWrite[type]+srcBufLen); /* using write information which is after memory copy*/
613
614 ASSERT(srcBufLen <= freeLen); // unit is 2 byte
615 memcpy(pSrc->buffer[type]+pSrc->bufWrite[type], srcBuf, srcBufLen*sizeof(uint16));
616
617 pSrc->bufWrite[type] += srcBufLen;
618 pSrc->bufDataCount[type] += srcBufLen;
619 }else { // two segment
620 int32 segment;
621 kal_uint8 *p2SrcBuf;
622
623 freeLen = pSrc->bufSize[type] - pSrc->bufDataCount[type] - EXT_BGSND_BUF_PTR_DIFF;
624
625 MD_TRC_L1SND_WRITE_DATA(2, id, type, srcBufLen, freeLen, 0, 0);
626 ASSERT(srcBufLen <= freeLen);
627
628 p2SrcBuf = srcBuf;
629 segment = pSrc->bufSize[type] - pSrc->bufWrite[type]; // bug
630 if(segment > srcBufLen){
631 segment = srcBufLen;
632 }
633
634 if(segment>0) { //first segment
635 memcpy(pSrc->buffer[type]+pSrc->bufWrite[type], p2SrcBuf, segment*sizeof(kal_uint16));
636 //update pointer
637 p2SrcBuf = srcBuf + segment*sizeof(kal_uint16);
638 pSrc->bufWrite[type] += segment;
639 pSrc->bufDataCount[type] += segment;
640 if(pSrc->bufWrite[type]>=pSrc->bufSize[type]){
641 pSrc->bufWrite[type] = 0;
642 }
643 MD_TRC_L1SND_WRITE_DATA(3, id, type, 0, 0, pSrc->bufRead[type], pSrc->bufWrite[type]);
644
645 segment = srcBufLen - segment;
646 }
647
648 if(segment>0) { //second segement
649 memcpy(pSrc->buffer[type], p2SrcBuf, segment*sizeof(kal_uint16));
650 pSrc->bufWrite[type] = segment;
651 pSrc->bufDataCount[type] += segment;
652
653 MD_TRC_L1SND_WRITE_DATA(4, id, type, 0, 0, pSrc->bufRead[type], pSrc->bufWrite[type]);
654 }
655 }
656 kal_give_spinlock(Ext_BGSnd.bgs_spinlockID);
657 MD_TRC_EXT_BGSND_WRITESRCBUFFER_LEAVE();
658}
659
660//from DL Src buffer -> DL ext buffer, multiplied by gain
661//from UL Src buffer -> UL ext buffer
662void EXT_BGSND_WriteExtBuffer(uint32 id, int gain, BGSND_PROCESS_TYPE type) // ToDo
663{
664 volatile uint16 *toPtr;
665 int32 count, segment, i;
666 uint16 *dataPtr;
667 uint16 gainFactor;
668 MD_TRC_EXT_BGSND_WRITEEXTBUFFER_ENTER();
669 MD_TRC_EXT_BGSND_WRITEEXTBUFFER_SELECTED_SRC(id, type);
670 ASSERT( type == BGSND_DL_PROCESS || type == BGSND_UL_PROCESS );
671 kal_take_spinlock(Ext_BGSnd.bgs_spinlockID, KAL_INFINITE_WAIT);
672 EXT_BGSND_SRC_T *pSrc = &Ext_BGSnd.src[id];
673 MD_TRC_EXT_BGSND_WRITEEXTBUFFER_FSPH(pSrc->fSph[type], pSrc->gain[type]);
674
675 gainFactor = pSrc->gain[type];
676
677 count = EXT_BGSND_GetDataCount(id, type);
678 toPtr = Ext_BGSnd.buffer[type];
679
680 MD_TRC_EXT_BGSND_WRITEEXTBUFFER_COUNT(count);
681
682 if (count > BGSND_BUFFER_LEN)
683 count = BGSND_BUFFER_LEN;
684
685
686 if(count > 0) {
687 /* First Segemnt */
688 if(pSrc->bufWrite[type] < pSrc->bufRead[type]) {
689 segment = (pSrc->bufSize[type] - pSrc->bufRead[type]);
690 } else {
691 segment = (pSrc->bufWrite[type] - pSrc->bufRead[type]);
692 }
693
694 if(segment&1){ // keep two sample alight
695 segment =segment - 1;
696 }
697
698 if (segment > count)
699 segment = count;
700
701 if (segment > 0) {
702 dataPtr = &(pSrc->buffer[type][pSrc->bufRead[type]]);
703
704 if(pSrc->fSph[type] && MAX_LEVEL_EXT_BGSND_GAIN!=gainFactor){
705 for (i=0; i<segment; i++) {
706
707 kal_int16 x = (*dataPtr>>gainFactor);
708 kal_int16 y = (kal_int16)(*toPtr);
709 kal_int16 result = x + y;
710
711 if (((x ^ y) >= 0) && (x ^ result) < 0) {
712 if (x < 0)
713 result = 0x8000;
714 else
715 result = 0x7FFF;
716 kal_prompt_trace(MOD_L1SP, "[EXT_BGSND_WriteExtBuffer] Saturation1 %d %d", x, y);
717
718 }
719 *toPtr = result;
720 toPtr++;
721 dataPtr++;
722 }
723 pSrc->dspLastSample[type] = *(toPtr-1);
724 }else{
725 toPtr += segment;
726 dataPtr += segment;
727
728 pSrc->dspLastSample[type] = 0;
729 }
730
731 pSrc->bufRead[type] += segment;
732 pSrc->bufDataCount[type] -= segment;
733 if (pSrc->bufRead[type] >= pSrc->bufSize[type])
734 pSrc->bufRead[type] = (pSrc->bufRead[type]-pSrc->bufSize[type]);
735
736 MD_TRC_EXT_BGSND_WRITEEXTBUFFER_FILLED_TO_DSP(1, segment, pSrc->bufRead[type], pSrc->bufWrite[type]);
737 }
738
739 segment = count - segment;
740
741 if (segment > 0) {
742 dataPtr = &(pSrc->buffer[type][pSrc->bufRead[type]]);
743 if(pSrc->fSph[type] && MAX_LEVEL_EXT_BGSND_GAIN!=gainFactor){
744 for (i=0; i<segment; i++) {
745
746 kal_int16 x = (*dataPtr>>gainFactor);
747 kal_int16 y = (kal_int16)(*toPtr);
748 kal_int16 result = x + y;
749
750 if (((x ^ y) >= 0) && ((x ^ result) < 0)) {
751 if (x < 0)
752 result = 0x8000;
753 else
754 result = 0x7FFF;
755 kal_prompt_trace(MOD_L1SP, "[EXT_BGSND_WriteExtBuffer] Saturation2 %d, %d",x ,y);
756
757 }
758 *toPtr = result;
759 toPtr++;
760 dataPtr++;
761 }
762 pSrc->dspLastSample[type] = *(dataPtr-1);
763 }else{
764 toPtr += segment;
765 dataPtr += segment;
766
767 pSrc->dspLastSample[type] = 0;
768 }
769
770 pSrc->bufRead[type] += segment;
771 pSrc->bufDataCount[type] -= segment;
772 if (pSrc->bufRead[type] >= pSrc->bufSize[type])
773 pSrc->bufRead[type] = (pSrc->bufRead[type]-pSrc->bufSize[type]);
774
775 MD_TRC_EXT_BGSND_WRITEEXTBUFFER_FILLED_TO_DSP(2, segment, pSrc->bufRead[type], pSrc->bufWrite[type]);
776 }
777 }
778
779 /* Put silence (last sample) if MCU buffer is empty */
780 if (count > 0 && count < BGSND_BUFFER_LEN && EXT_SRC_STATE_RUN == pSrc->state[type]) {
781 kal_uint16 last_sample = pSrc->dspLastSample[type];
782 // segment = dsp_buf_len - count;
783 segment = BGSND_BUFFER_LEN - count;
784 //for (i=0; i<segment; i++)) {
785 // *toPtr++ = last_sample;
786 //}
787 MD_TRC_EXT_BGSND_WRITEEXTBUFFER_FILLED_TO_DSP_WITH_LAST_SAMPLE(segment, last_sample);
788 if(pSrc->fSph[type] && MAX_LEVEL_EXT_BGSND_GAIN!=gainFactor){
789 for (i=0; i<segment; i++) {
790 //*toPtr++ = *dataPtr++;
791 kal_int16 x = (last_sample>>gainFactor);
792 kal_int16 y = (kal_int16)(*toPtr);
793 kal_int16 result = x + y;
794
795 if (((x ^ y) >= 0) && ((x ^ result) < 0)) {
796 if (x < 0)
797 result = 0x8000;
798 else
799 result = 0x7FFF;
800 kal_prompt_trace(MOD_L1SP, "[EXT_BGSND_WriteExtBuffer] Saturation3 %d %d",x,y);
801
802 }
803
804 *toPtr = result;
805 toPtr++;
806 }
807 }else{
808 toPtr += segment;
809 }
810 }//else{ //it means no data should be played, so we don't append to the size of a frame any more
811 // kal_trace( TRACE_FUNC, EXT_BGSND_WRITEEXTBUFFER_SKIP_TO_DSP, count, pSrc->state[type]);
812 //}
813
814/* {
815 //just for debugging
816 int i;
817 for(i=0; i<10; i++){
818 MD_TRC_EXT_BGSND_WRITEEXTBUFFER(
819 Ext_BGSnd.buffer[type][0],Ext_BGSnd.buffer[type][1],
820 Ext_BGSnd.buffer[type][2],Ext_BGSnd.buffer[type][3],
821 Ext_BGSnd.buffer[type][4],Ext_BGSnd.buffer[type][5],
822 Ext_BGSnd.buffer[type][6],Ext_BGSnd.buffer[type][7],
823 Ext_BGSnd.buffer[type][8],Ext_BGSnd.buffer[type][9]
824);
825
826 }
827 }*/
828 kal_give_spinlock(Ext_BGSnd.bgs_spinlockID);
829 MD_TRC_EXT_BGSND_WRITEEXTBUFFER_LEAVE();
830}
831
832int32 EXT_BGSND_GetFreeSpace(uint32 id, BGSND_PROCESS_TYPE type)
833{
834
835 ASSERT( type == BGSND_DL_PROCESS || type == BGSND_UL_PROCESS );
836 EXT_BGSND_SRC_T *pSrc = &Ext_BGSnd.src[id];
837
838 MD_TRC_EXT_BGSND_GETFREESPACE_ENTER();
839 MD_TRC_EXT_BGSND_GETFREESPACE_INFO(pSrc->bufSize[type], pSrc->bufRead[type], pSrc->bufWrite[type]);
840
841
842
843 MD_TRC_EXT_BGSND_GETFREESPACE_LEAVE();
844 return (pSrc->bufSize[type] - EXT_BGSND_BUF_PTR_DIFF - pSrc->bufDataCount[type]);
845}
846
847
848void EXT_BGSND_ConfigMixer(int id, kal_bool bSPHFlag, kal_int8 SNDGain, BGSND_PROCESS_TYPE type)
849{
850 EXT_BGSND_SRC_T *pSrc = &Ext_BGSnd.src[id];
851 MD_TRC_EXT_BGSND_CONFIGMIXER_ENTER();
852 ASSERT(SNDGain>=0 && SNDGain<=MAX_LEVEL_EXT_BGSND_GAIN);
853 MD_TRC_EXT_BGSND_CONFIGMIXER_BSPHFLAG(bSPHFlag, SNDGain);
854 pSrc->fSph[type] = bSPHFlag;
855 pSrc->gain[type] = MAX_LEVEL_EXT_BGSND_GAIN-SNDGain;
856 MD_TRC_EXT_BGSND_CONFIGMIXER_LEAVE();
857 /*
858 SNDGain = 7 --> Volume >> 0
859 SNDGain = 6 --> Volume >> 1
860 SNDGain = 5 --> Volume >> 2
861
862 SNDGain = 0 --> Volume * 0 = 0
863 */
864}
865
866
867EXT_SRC_STATE_TYPE EXT_BGSND_GetStatus(int id, BGSND_PROCESS_TYPE enULDL)
868{
869 ASSERT( id < MAX_SIZE_EXT_BGSND_SRC );
870 ASSERT( enULDL < MAX_NUM_BGSND_PROCESS );
871 return(Ext_BGSnd.src[id].state[enULDL]);
872}
873
874
875//================= Extended SPC BGSND INTERFACE ====================
876
877
878
879
880