AudioDrv.c
上传用户:jankzhpno
上传日期:2022-08-03
资源大小:4763k
文件大小:21k
源码类别:

Windows CE

开发平台:

Visual C++

  1. #include "def.h"
  2. #include "2440addr.h"
  3. #include "2440lib.h"
  4. #include "AudioDrv.h"
  5. #include "dma.h"
  6. #define AUDIO_PLAY_DEV 0x100
  7. #define AUDIO_REC_DEV 0x101
  8. #define DEVICE_REC 2
  9. #define DEVICE_PLAY 1
  10. #define DEVICE_FREE 0
  11. #define PLAY 0
  12. #define RECORD 1
  13. #define PLAY_DMA_ATTR ((AUDIO_PLAY_DEV<<16)|SRC_LOC_AHB|SRC_ADDR_INC|DST_LOC_APB|DST_ADDR_FIXED|REQ_IISDO)
  14. #define PLAY_DMA_MODE (HANDSHAKE_MODE|SYNC_APB|DONE_GEN_INT|TSZ_UNIT|SINGLE_SVC|HW_TRIG|RELOAD_OFF|DSZ_16b)
  15. #define REC_DMA_ATTR ((AUDIO_REC_DEV<<16)|SRC_LOC_APB|SRC_ADDR_FIXED|DST_LOC_AHB|DST_ADDR_INC|REQ_IISDI)
  16. #define REC_DMA_MODE (HANDSHAKE_MODE|SYNC_APB|DONE_GEN_INT|TSZ_UNIT|SINGLE_SVC|HW_TRIG|RELOAD_OFF|DSZ_16b)
  17. static void IIS_PortSetting(void);
  18. static void _WrL3Addr(U8 data);
  19. static void _WrL3Data(U8 data,int halt);
  20. static void Init1341(char mode);
  21. static void AdjVolume(U16 volume);
  22. static void PlayPause(U8 mode);
  23. //static void Muting(void);
  24. static void StartPlay(void);
  25. static void __irq PlayDMA2Done(void);
  26. static LPWAVEHDR lpPlayFstBlk, lpRecFstBlk;
  27. static LPWAVEHDR lpPlayLstBlk, lpRecLstBlk;
  28. static LPWAVEHDR lpPlayCurBlk, lpRecCurBlk;
  29. static U32 PlayTotBlks, RecTotBlks;
  30. static U32 save_MPLLCON;
  31. static struct{
  32. U16 Freq;
  33. U32 MPLL;
  34. U16 PreScaler;
  35. U8 ofs;
  36. }CodecPara[7] = {{8000,(123<<12)|(6<<4)|0,(23<<5)|23,0},
  37. {11025,(229<<12)|(5<<4)|1,(11<<5)|11,1},
  38. {16000,(123<<12)|(6<<4)|0,(11<<5)|11,0},
  39. {22050,(229<<12)|(5<<4)|1,(5<<5)|5,1},
  40. //{22050,(0x96<<12)|(5<<4)|1,(5<<5)|5,0},
  41. {32000,(123<<12)|(6<<4)|0,(5<<5)|5,0},
  42. {44100,(229<<12)|(5<<4)|1,(2<<5)|2,1},
  43. {48000,(123<<12)|(6<<4)|0,(3<<5)|3,0}};
  44. static struct{
  45. HWAVEOUT handle;
  46. U16 wFormatTag;
  47. U16 nChannels;
  48. U16 wBitsPerSample;
  49. CallBackProc CallBack;
  50. U32 CallBackInst;
  51. U8 FsIdx;
  52. U32 DevReq;
  53. U8 Status;
  54. }PlayStatus, RecStatus;     
  55. static U16 PlayVolume = 0xffff;
  56. //static U8 inner_buf[32*1024];
  57. void DbgChgUartDiv(void)
  58. {
  59. Uart_Init(0, 115200);        
  60. }
  61. static void SetSysFclk( U32 MPLL )
  62. {
  63. U32 mdiv, pdiv, sdiv, val;
  64.     U32 mclk;
  65.     mdiv = (MPLL>>12)&0xff;
  66.     pdiv = (MPLL>>4)&0xff;
  67.     sdiv = MPLL&0xf;
  68.     
  69.     val = 1;
  70.     while(sdiv--)
  71.     {
  72.      val *= 2;
  73.     }
  74.     
  75.     mclk = ((mdiv+8)*12000000)/((pdiv+2)*val) ;     
  76.     Uart_Init(mclk>>2, 115200) ;
  77. }
  78. /************************* Play Function ***********************/
  79. MMRESULT waveOutOpen(
  80. LPHWAVEOUT phwo,
  81. UINT uDeviceID,
  82. LPWAVEFORMATEX pwfx,
  83. DWORD dwCallback,
  84. DWORD dwCallbackInstance,
  85. DWORD fdwOpen
  86. )
  87. {
  88. U8 i;
  89. U8 err = 0;
  90. if(pwfx->wFormatTag!=WAVE_FORMAT_PCM) //only support PCM
  91. err = 1;
  92. if(pwfx->nChannels!=2) //must be stero
  93. err = 1;
  94. if(pwfx->wBitsPerSample%8) //8 or 16 bits
  95. err = 1;
  96. for(i=0; i<7; i++)
  97. if(pwfx->nSamplesPerSec==CodecPara[i].Freq)
  98. break;
  99. if(i==7)
  100. err = 1;
  101. if((pwfx->nChannels*pwfx->wBitsPerSample)/8!=pwfx->nBlockAlign)
  102. err = 1;
  103. if(pwfx->nAvgBytesPerSec!=pwfx->nSamplesPerSec*pwfx->nBlockAlign)
  104. err = 1;
  105. if(err)
  106. return WAVERR_BADFORMAT; //check format parameters
  107. if(PlayStatus.Status!=DEVICE_FREE)
  108. return MMSYSERR_BADDEVICEID;
  109. PlayStatus.DevReq = RequestDMA(PLAY_DMA_ATTR, PLAY_DMA_MODE);
  110. if(PlayStatus.DevReq==REQUEST_DMA_FAIL)
  111. return MMSYSERR_BADDEVICEID;
  112. PlayStatus.handle   = *phwo; 
  113. PlayStatus.wFormatTag     = pwfx->wFormatTag;
  114. PlayStatus.nChannels      = pwfx->nChannels;
  115. PlayStatus.wBitsPerSample = pwfx->wBitsPerSample;
  116. PlayStatus.FsIdx          = i;
  117. PlayStatus.CallBack   = (CallBackProc)dwCallback;
  118. PlayStatus.CallBackInst   = dwCallbackInstance;
  119. PlayStatus.Status   = DEVICE_PLAY;
  120. save_MPLLCON = rMPLLCON; //save MPLLCON value
  121. //rMPLLCON = CodecPara[PlayStatus.FsIdx].MPLL;
  122. SetSysFclk(CodecPara[PlayStatus.FsIdx].MPLL);
  123. rCLKCON |= 0x20000; //enable IIS clock
  124. DbgChgUartDiv();
  125. // ChangeClockDivider(1,1);        //1:2:4
  126. // ChangeMPllValue(0x96,0x5,0x1);  //FCLK=135.428571MHz (PCLK=33.857142MHz)    
  127. // Uart_Init(33857142,115200); 
  128. IIS_PortSetting();     
  129.     pISR_DMA2 = (U32)PlayDMA2Done;
  130.     EnableIrq(BIT_DMA2);
  131. PlayTotBlks = 0;
  132. Init1341(PLAY);
  133. waveOutSetVolume(PlayStatus.handle, PlayVolume);
  134. return MMSYSERR_NOERROR;
  135. }
  136. MMRESULT waveOutClose(HWAVEOUT hwo)
  137. {
  138. if((PlayStatus.handle!=hwo)||(PlayStatus.Status!=DEVICE_PLAY))
  139. return MMSYSERR_INVALHANDLE;
  140. rIISCON      = 0x0; //IIS Interface stop    
  141.     rIISFCON     = 0x0;      //For FIFO flush
  142.     rCLKCON &= ~0x20000; //disable IIS colock
  143.     //rMPLLCON  = save_MPLLCON; //restore MPLLCON value
  144.     SetSysFclk(save_MPLLCON);
  145.     PlayStatus.Status = DEVICE_FREE;    
  146. ReleaseDMA(PlayStatus.DevReq);
  147. DisableIrq(BIT_DMA2);
  148. return MMSYSERR_NOERROR;
  149. }
  150. MMRESULT waveOutPrepareHeader(HWAVEOUT hwo, LPWAVEHDR pwh, UINT cbwh)
  151. {
  152. if((PlayStatus.handle!=hwo)||(PlayStatus.Status!=DEVICE_PLAY))
  153. return MMSYSERR_INVALHANDLE;
  154. pwh->lpNext = 0;
  155. pwh->dwBytesRecorded = 0;
  156. pwh->dwUser  = 0;
  157. pwh->dwFlags = 0;
  158. return MMSYSERR_NOERROR;
  159. }
  160. MMRESULT waveOutUnprepareHeader(HWAVEOUT hwo, LPWAVEHDR pwh, UINT cbwh)
  161. {
  162. if((PlayStatus.handle!=hwo)||(PlayStatus.Status!=DEVICE_PLAY))
  163. return MMSYSERR_INVALHANDLE;
  164. return MMSYSERR_NOERROR;
  165. }
  166. MMRESULT waveOutWrite(HWAVEOUT hwo, LPWAVEHDR pwh, UINT cbwh)
  167. {
  168. if((PlayStatus.handle!=hwo)||(PlayStatus.Status!=DEVICE_PLAY))
  169. return MMSYSERR_INVALHANDLE;
  170. if(!PlayTotBlks)
  171. {
  172. lpPlayFstBlk = pwh;
  173. lpPlayCurBlk = lpPlayFstBlk;
  174. StartPlay();
  175. }
  176. else
  177. {
  178. lpPlayLstBlk -> lpNext = pwh ;
  179. }
  180. lpPlayLstBlk = pwh;
  181. pwh->lpNext = 0;
  182. PlayTotBlks++;
  183. return MMSYSERR_NOERROR;
  184. }
  185. MMRESULT waveOutSetVolume(HWAVEOUT hwo, DWORD dwVolume)
  186. {
  187. if((PlayStatus.handle!=hwo)||(PlayStatus.Status!=DEVICE_PLAY))
  188. return MMSYSERR_INVALHANDLE;
  189. PlayVolume = dwVolume&0xffff;
  190. AdjVolume(PlayVolume);
  191. return MMSYSERR_NOERROR;
  192. }
  193. MMRESULT waveOutGetVolume(HWAVEOUT hwo, LPDWORD pdwVolume)
  194. {
  195. if((PlayStatus.handle!=hwo)||(PlayStatus.Status!=DEVICE_PLAY))
  196. return MMSYSERR_INVALHANDLE;
  197. *pdwVolume = PlayVolume; 
  198. return MMSYSERR_NOERROR;
  199. }
  200. MMRESULT waveOutPause (HWAVEOUT hwo)
  201. {
  202. if((PlayStatus.handle!=hwo)||(PlayStatus.Status!=DEVICE_PLAY))
  203. return MMSYSERR_INVALHANDLE;
  204. PlayPause(1);
  205. return MMSYSERR_NOERROR;
  206. }
  207. MMRESULT waveOutRestart(HWAVEOUT hwo)
  208. {
  209. if((PlayStatus.handle!=hwo)||(PlayStatus.Status!=DEVICE_PLAY))
  210. return MMSYSERR_INVALHANDLE;
  211. PlayPause(0);
  212. return MMSYSERR_NOERROR;
  213. }
  214. MMRESULT waveOutReset (HWAVEOUT hwo)
  215. {
  216. if((PlayStatus.handle!=hwo)||(PlayStatus.Status!=DEVICE_PLAY))
  217. return MMSYSERR_INVALHANDLE;
  218. return MMSYSERR_NOERROR;
  219. }
  220. //==========================================================
  221. static __inline void SetPlayDma(void)
  222. {
  223. // WrUTXH0('@');
  224. SetDMARun(PlayStatus.DevReq|DMA_START, (U32)lpPlayCurBlk->lpData, (U32)IISFIFO, lpPlayCurBlk->dwBufferLength/2);
  225. }
  226. static void StartPlay(void)
  227. {
  228. SetPlayDma();         
  229. rIISPSR  = CodecPara[PlayStatus.FsIdx].PreScaler;
  230. rIISCON  = (1<<5)+(0<<4)+(0<<3)+(1<<2)+(1<<1); //Tx DMA enable[5], Rx idle[2], Prescaler enable[1]
  231. rIISMOD  = (0<<8)+(2<<6)+(0<<5)+(1<<4)+((PlayStatus.wBitsPerSample>>4)<<3)+(CodecPara[PlayStatus.FsIdx].ofs<<2)+(1<<0);
  232. rIISFCON = (1<<15) + (1<<13);    
  233.     rIISCON |= 0x1;           
  234. }
  235. static void __irq PlayDMA2Done(void)
  236. {
  237.     ClearPending(BIT_DMA2);     //Clear pending bit
  238.     
  239.     lpPlayCurBlk->dwLoops--;     
  240. if(lpPlayCurBlk->lpNext)
  241.     {
  242.      lpPlayCurBlk = lpPlayCurBlk->lpNext;        
  243.     }
  244.     else
  245.     {
  246.      lpPlayCurBlk = lpPlayFstBlk;         
  247.     }    
  248.     SetPlayDma();
  249. }
  250. /************************* Record Function *********************/
  251. static __inline void SetRecDma(void)
  252. {
  253. // WrUTXH0('.');     
  254. SetDMARun(RecStatus.DevReq|DMA_START, (U32)IISFIFO, (U32)lpRecCurBlk->lpData, lpRecCurBlk->dwBufferLength/2);
  255. }
  256. static void __irq RecDMADone(void)
  257. {
  258. if((RecStatus.DevReq&0xff)==0x12)
  259.     ClearPending(BIT_DMA1);     //Clear pending bit
  260. if((RecStatus.DevReq&0xff)==0x21)
  261. ClearPending(BIT_DMA2);     
  262.     
  263.     lpRecCurBlk->dwBytesRecorded = lpRecCurBlk->dwBufferLength;
  264.     
  265.     if(lpRecCurBlk->lpNext)
  266.     {
  267.      lpRecCurBlk = lpRecCurBlk->lpNext;        
  268.     }
  269.     else
  270.     {
  271.         lpRecCurBlk = lpRecFstBlk;         
  272.     }
  273.     SetRecDma();
  274. }
  275. MMRESULT waveInOpen(
  276. LPHWAVEIN phwi,
  277. UINT uDeviceID,
  278. LPWAVEFORMATEX pwfx,
  279. DWORD dwCallback,
  280. DWORD dwCallbackInstance,
  281. DWORD fdwOpen
  282. )
  283. {
  284. U8 i;
  285. U8 err = 0;
  286. if(pwfx->wFormatTag!=WAVE_FORMAT_PCM) //only support PCM
  287. err = 1;
  288. if(pwfx->nChannels!=2) //must be stero
  289. err = 2;
  290. if(pwfx->wBitsPerSample%8) //8 or 16 bits
  291. err = 3;
  292. for(i=0; i<7; i++)
  293. if(pwfx->nSamplesPerSec==CodecPara[i].Freq)
  294. break;
  295. if(i==7)
  296. err = 4;
  297. if((pwfx->nChannels*pwfx->wBitsPerSample)/8!=pwfx->nBlockAlign)
  298. err = 5;
  299. if(pwfx->nAvgBytesPerSec!=pwfx->nSamplesPerSec*pwfx->nBlockAlign)
  300. err = 6;
  301. if(err)
  302. {
  303. //printf("check err = %dn", err);
  304. return WAVERR_BADFORMAT; //check format parameters
  305. }
  306. if(RecStatus.Status!=DEVICE_FREE)
  307. return MMSYSERR_BADDEVICEID;
  308. RecStatus.DevReq = RequestDMA(REC_DMA_ATTR, REC_DMA_MODE);
  309. if(RecStatus.DevReq==REQUEST_DMA_FAIL)
  310. return MMSYSERR_BADDEVICEID;
  311. RecStatus.handle   = *phwi; 
  312. RecStatus.wFormatTag     = pwfx->wFormatTag;
  313. RecStatus.nChannels      = pwfx->nChannels;
  314. RecStatus.wBitsPerSample = pwfx->wBitsPerSample;
  315. RecStatus.FsIdx          = i;
  316. RecStatus.CallBack  = (CallBackProc)dwCallback;
  317. RecStatus.CallBackInst  = dwCallbackInstance;
  318. RecStatus.Status  = DEVICE_REC;
  319. save_MPLLCON = rMPLLCON; //save MPLLCON value
  320. //rMPLLCON = CodecPara[RecStatus.FsIdx].MPLL;
  321. SetSysFclk(CodecPara[RecStatus.FsIdx].MPLL);
  322. rCLKCON |= 0x20000; //enable IIS clock
  323. DbgChgUartDiv();
  324. IIS_PortSetting();
  325. if((RecStatus.DevReq&0xff)==0x12)
  326. {
  327. pISR_DMA1 = (U32)RecDMADone;
  328. EnableIrq(BIT_DMA1);
  329. }
  330. if((RecStatus.DevReq&0xff)==0x21)     
  331. {
  332. pISR_DMA2 = (U32)RecDMADone;
  333. EnableIrq(BIT_DMA2);
  334. }
  335. RecTotBlks = 0;
  336. Init1341(RECORD);
  337. return MMSYSERR_NOERROR;
  338. }
  339. MMRESULT waveInClose(HWAVEOUT hwi)
  340. {
  341. if((RecStatus.handle!=hwi)||(RecStatus.Status!=DEVICE_REC))
  342. return MMSYSERR_INVALHANDLE;
  343. rIISCON      = 0x0; //IIS Interface stop    
  344.     rIISFCON     = 0x0;      //For FIFO flush
  345.     rCLKCON &= ~0x20000; //disable IIS colock
  346.     //rMPLLCON  = save_MPLLCON; //restore MPLLCON value
  347.     SetSysFclk(save_MPLLCON);
  348.     
  349.     RecStatus.Status = DEVICE_FREE;    
  350. ReleaseDMA(RecStatus.DevReq);
  351. if((RecStatus.DevReq&0xff)==0x12)
  352. DisableIrq(BIT_DMA1);
  353. if((RecStatus.DevReq&0xff)==0x21)
  354. DisableIrq(BIT_DMA2);
  355. return MMSYSERR_NOERROR;
  356. }
  357. MMRESULT waveInStart(HWAVEIN hwi)
  358. {
  359. if((RecStatus.handle!=hwi)||(RecStatus.Status!=DEVICE_REC))
  360. return MMSYSERR_INVALHANDLE;
  361. if(!RecTotBlks)
  362. return MMSYSERR_NOMEM;
  363. SetRecDma();
  364. rIISPSR  = CodecPara[RecStatus.FsIdx].PreScaler;
  365. rIISCON  = (0<<5)+(1<<4)+(1<<3)+(0<<2)+(1<<1); //Tx DMA disable,Rx DMA enable,Tx idle,Rx not idle,prescaler enable,stop
  366. rIISMOD  = (0<<8)+(1<<6)+(0<<5)+(1<<4)+((RecStatus.wBitsPerSample>>4)<<3)+(CodecPara[RecStatus.FsIdx].ofs<<2)+(1<<0);
  367. //Master mode[8],Rx mode[7:6],Low for Left Channel[5],IIS format[4],16/8bit [3],256/384fs [2],IISCLK 32fs[1:0]     
  368. rIISFCON = (1<<14)+(1<<12); //Rx DMA,Rx FIFO --> start piling....    
  369. rIISCON |= 0x1;     //start IIS 
  370. return MMSYSERR_NOERROR;
  371. }
  372. MMRESULT waveInStop(HWAVEIN hwi)
  373. {
  374. if((RecStatus.handle!=hwi)||(RecStatus.Status!=DEVICE_REC))
  375. return MMSYSERR_INVALHANDLE;
  376. rIISCON     = 0x0; //IIS Interface stop    
  377.     rIISFCON    = 0x0;      //For FIFO flush
  378.     StopDMA(RecStatus.DevReq);    
  379. return MMSYSERR_NOERROR;
  380. }
  381. MMRESULT waveInPrepareHeader(HWAVEIN hwi, LPWAVEHDR pwh, UINT cbwh)
  382. {
  383. if((RecStatus.handle!=hwi)||(RecStatus.Status!=DEVICE_REC))
  384. return MMSYSERR_INVALHANDLE;
  385. pwh->lpNext = 0;
  386. pwh->dwBytesRecorded = 0;
  387. pwh->dwUser  = 0;
  388. pwh->dwFlags = 0;
  389. return MMSYSERR_NOERROR;
  390. }
  391. MMRESULT waveInUnprepareHeader(HWAVEIN hwi, LPWAVEHDR pwh, UINT cbwh)
  392. {
  393. if((RecStatus.handle!=hwi)||(RecStatus.Status!=DEVICE_REC))
  394. return MMSYSERR_INVALHANDLE;
  395. return MMSYSERR_NOERROR;
  396. }
  397. MMRESULT waveInAddBuffer(HWAVEIN hwi, LPWAVEHDR pwh, UINT cbwh)
  398. {
  399. if((RecStatus.handle!=hwi)||(RecStatus.Status!=DEVICE_REC))
  400. return MMSYSERR_INVALHANDLE;
  401. if(!RecTotBlks)
  402. {
  403. lpRecFstBlk = pwh;
  404. lpRecCurBlk = lpRecFstBlk;
  405. }
  406. else
  407. {
  408. lpRecLstBlk->lpNext = pwh;
  409. }
  410. lpRecLstBlk = pwh;
  411. pwh->lpNext = 0;
  412. RecTotBlks++;
  413. return MMSYSERR_NOERROR;
  414. }
  415. MMRESULT waveInReset(HWAVEOUT hwi)
  416. {
  417. return MMSYSERR_NOERROR;
  418. }
  419. /************************* Control Function *********************/
  420. static void IIS_PortSetting(void)
  421. {
  422. //----------------------------------------------------------
  423. //   PORT B GROUP
  424. //Ports  :   GPB4    GPB3   GPB2  
  425. //Signal :  L3CLOCK L3DATA L3MODE
  426. //Setting:   OUTPUT OUTPUT OUTPUT 
  427. //           [9:8]   [7:6}  [5:4]
  428. //Binary :     01  ,   01    01 
  429. //----------------------------------------------------------    
  430.     rGPBUP  = rGPBUP  & ~(0x7<<2) | (0x7<<2);   //The pull up function is disabled GPB[4:2] 1 1100    
  431.     rGPBCON = rGPBCON & ~(0x3f<<4) | (0x15<<4); //GPB[4:2]=Output(L3CLOCK):Output(L3DATA):Output(L3MODE)
  432. //----------------------------------------------------------
  433. //   PORT E GROUP
  434. //Ports  :  GPE4    GPE3   GPE2  GPE1    GPE0 
  435. //Signal : I2SSDO  I2SSDI CDCLK I2SSCLK I2SLRCK 
  436. //Binary :   10  ,   10     10 ,  10      10    
  437. //----------------------------------------------------------
  438.     rGPEUP  = rGPEUP  & ~(0x1f)  | 0x1f;    //The pull up function is disabled GPE[4:0] 1 1111
  439.     rGPECON = rGPECON & ~(0x3ff) | 0x2aa;   //GPE[4:0]=I2SSDO:I2SSDI:CDCLK:I2SSCLK:I2SLRCK
  440. }    
  441. //==========================================================
  442. #define L3C (1<<4)              //GPB4 = L3CLOCK
  443. #define L3D (1<<3)              //GPB3 = L3DATA
  444. #define L3M (1<<2)              //GPB2 = L3MODE
  445. static void _WrL3Addr(U8 data)
  446. {       
  447.     S32 i,j;
  448.     rGPBDAT  = rGPBDAT & ~(L3D | L3M | L3C) | L3C;      //L3D=L, L3M=L(in address mode), L3C=H
  449.     for(j=0;j<4;j++);                   //tsu(L3) > 190ns
  450.       //GPB[4:2]=L3C:L3D:L3M
  451.     for(i=0;i<8;i++)                    //LSB first
  452.     {
  453.         if(data & 0x1)                  //If data's LSB is 'H'
  454.         {
  455.             rGPBDAT &= ~L3C;            //L3C=L
  456.             rGPBDAT |= L3D;             //L3D=H             
  457.             for(j=0;j<4;j++);           //tcy(L3) > 500ns
  458.             rGPBDAT |= L3C;             //L3C=H
  459.             rGPBDAT |= L3D;             //L3D=H
  460.             for(j=0;j<4;j++);           //tcy(L3) > 500ns
  461.         }
  462.         else                            //If data's LSB is 'L'
  463.         {
  464.             rGPBDAT &= ~L3C;            //L3C=L
  465.             rGPBDAT &= ~L3D;            //L3D=L
  466.             for(j=0;j<4;j++);           //tcy(L3) > 500ns
  467.             rGPBDAT |= L3C;             //L3C=H
  468.             rGPBDAT &= ~L3D;            //L3D=L
  469.             for(j=0;j<4;j++);           //tcy(L3) > 500ns            
  470.         }
  471.         data >>= 1;
  472.     }
  473.     rGPBDAT  = rGPBDAT & ~(L3D | L3M | L3C) | (L3C | L3M);       //L3M=H,L3C=H   
  474. }
  475. //==========================================================
  476. static void _WrL3Data(U8 data,int halt)
  477. {
  478.     S32 i,j;
  479.     if(halt)
  480.     {
  481.         rGPBDAT  = rGPBDAT & ~(L3D | L3M | L3C) | L3C;   //L3C=H(while tstp, L3 interface halt condition)        
  482.         for(j=0;j<4;j++);                                //tstp(L3) > 190ns
  483.     }
  484.     rGPBDAT  = rGPBDAT & ~(L3D | L3M | L3C) | (L3C | L3M);   //L3M=H(in data transfer mode)        
  485.     for(j=0;j<4;j++);                                        //tsu(L3)D > 190ns
  486.       //GPB[4:2]=L3C:L3D:L3M
  487.     for(i=0;i<8;i++)
  488.     {
  489.         if(data & 0x1)                   //if data's LSB is 'H'
  490.         {
  491.            rGPBDAT &= ~L3C;              //L3C=L
  492.            rGPBDAT |= L3D;               //L3D=H
  493.            for(j=0;j<4;j++);             //tcy(L3) > 500ns
  494.            rGPBDAT |= (L3C | L3D);       //L3C=H,L3D=H
  495.            for(j=0;j<4;j++);             //tcy(L3) > 500ns
  496.         }
  497.         else                             //If data's LSB is 'L'
  498.         {
  499.            rGPBDAT &= ~L3C;              //L3C=L
  500.            rGPBDAT &= ~L3D;              //L3D=L
  501.            for(j=0;j<4;j++);             //tcy(L3) > 500ns
  502.            rGPBDAT |= L3C;               //L3C=H
  503.            rGPBDAT &= ~L3D;              //L3D=L
  504.            for(j=0;j<4;j++);             //tcy(L3) > 500ns
  505.         }
  506.         data >>= 1;                      //For check next bit
  507.     }
  508.     rGPBDAT  = rGPBDAT & ~(L3D | L3M | L3C) | (L3C | L3M);    //L3M=H,L3C=H
  509. }
  510. //==========================================================
  511. static void Init1341(char mode)
  512. {
  513. U16 FsIdx;
  514. //Port Initialize
  515. //----------------------------------------------------------
  516. //   PORT B GROUP
  517. //Ports  :   GPB4    GPB3   GPB2  
  518. //Signal :  L3CLOCK L3DATA L3MODE
  519. //Setting:   OUTPUT OUTPUT OUTPUT 
  520. //           [9:8]   [7:6}  [5:4]
  521. //Binary :     01  ,   01    01 
  522. //----------------------------------------------------------    
  523. rGPBDAT = rGPBDAT & ~(L3M|L3C|L3D) |(L3M|L3C); //Start condition : L3M=H, L3C=H
  524. rGPBUP  = rGPBUP  & ~(0x7<<2) |(0x7<<2);       //The pull up function is disabled GPB[4:2] 1 1100    
  525. rGPBCON = rGPBCON & ~(0x3f<<4) |(0x15<<4);     //GPB[4:2]=Output(L3CLOCK):Output(L3DATA):Output(L3MODE)
  526. //L3 Interface
  527. _WrL3Addr(0x14 + 2); //STATUS (000101xx+10)
  528. _WrL3Data(0x60,0); //0,1,10, 000,0 : Status 0,Reset,256fs,IIS-bus,no DC-filtering
  529. _WrL3Addr(0x14 + 2); //STATUS (000101xx+10)
  530. FsIdx = mode?RecStatus.FsIdx:PlayStatus.FsIdx;        
  531. if(CodecPara[FsIdx].ofs)
  532. _WrL3Data(0x18,0); //0,0,01, 000,0 : Status 0,No reset,384fs,IIS-bus,no DC-filtering
  533. else
  534.  _WrL3Data(0x28,0); //0,0,10, 000,0 : Status 0,No reset,256fs,IIS-bus,no DC-filtering
  535. _WrL3Addr(0x14 + 2); //STATUS (000101xx+10)
  536. _WrL3Data(0xc1,0); //1,0,0,0, 0,0,01 
  537. //Status 1,Gain of DAC 6 dB,Gain of ADC 0dB,ADC non-inverting,DAC non-inverting
  538. //,Single speed playback,ADC-Off DAC-On
  539.     
  540. //Record
  541.     if(mode) {
  542. _WrL3Addr(0x14 + 2); //STATUS (000101xx+10)
  543. // _WrL3Data(0xa2,0); //1,0,1,0, 0,0,10 
  544. //Status 1,Gain of DAC 0 dB,Gain of ADC 6dB,ADC non-inverting,DAC non-inverting
  545. //,Single speed playback,ADC-On DAC-Off       
  546. _WrL3Data(0xe3,0); //1,1,1,0, 0,0,11 
  547. //Status 1,Gain of DAC 6 dB,Gain of ADC 6dB,ADC non-inverting,DAC non-inverting
  548. //,Single speed playback,ADC-On DAC-On,DAC打开使录音时可从耳机听到声音
  549. // _WrL3Addr(0x14 + 0); //DATA0 (000101xx+00)
  550. // _WrL3Data(0x3f,0); //00,11 1111  : Volume control (6 bits)  
  551. // _WrL3Data(0x00,0); //00,00 0000  : Volume control (6 bits) 0dB    
  552. _WrL3Addr(0x14 + 0); //DATA0 (000101xx+00)
  553. _WrL3Data(0x7b,0); //01,11 10,11 : Data0, Bass Boost 18~24dB, Treble 6dB
  554. // _WrL3Addr(0x14 + 0); //DATA0 (000101xx+00)
  555. _WrL3Data(0xc4,0); //1100 0,100  : Extended addr(3bits), 100
  556. // _WrL3Data(0x90,0); //100,1 00,00 : DATA0, Enable AGC, 00, input amplifier gain channel 2 (2bits)
  557. _WrL3Data(0xf0,0); //111,1 00,00 : DATA0, Enable AGC, 00, input amplifier gain channel 2 (2bits)
  558. // _WrL3Addr(0x14 + 0); //DATA0 (000101xx+00)
  559. _WrL3Data(0xc0,0); //1100 0,000  : Extended addr(3bits), 000
  560. _WrL3Data(0xe4,0); //111, 00000  : MA = 0dB
  561. _WrL3Data(0xc1,0); //1100 0,001  : Extended addr(3bits), 001 
  562. _WrL3Data(0xe4,0); //111, 00000  : MB = 0dB
  563. // _WrL3Addr(0x14 + 0); //DATA0 (000101xx+00)
  564. _WrL3Data(0xc2,0); //1100 0,010  : Extended addr(3bits), 010
  565. // _WrL3Data(0x59,0); //010,1 10,01 : DATA0, MIC Amplifier Gain 27dB, input channel 1 select(input channel 2 off)
  566. _WrL3Data(0xf9,0); //111,1 10,11 : DATA0, MIC Amplifier Gain 27dB, input 1 X MA + input 2 X MB
  567.     }
  568. }
  569. //==========================================================
  570. static void PlayPause(U8 mode)
  571. {
  572. if(mode) 
  573. rIISCON &= ~1; //stop iis
  574. else
  575. rIISCON |= 1; //start iis
  576. }
  577. #define MAX_VOLUME 61
  578. static void AdjVolume(U16 volume)
  579. {
  580. rGPBDAT = rGPBDAT & ~(L3M|L3C|L3D) |(L3M|L3C); //Start condition : L3M=H, L3C=H
  581.     rGPBUP  = rGPBUP  & ~(0x7<<2) |(0x7<<2);       //The pull up function is disabled GPB[4:2] 1 1100    
  582.     rGPBCON = rGPBCON & ~(0x3f<<4) |(0x15<<4);     //GPB[4:2]=Output(L3CLOCK):Output(L3DATA):Output(L3MODE)
  583. volume = (volume*MAX_VOLUME)/0xffff;     
  584.     
  585. _WrL3Addr(0x14 + 0); //DATA0 (000101xx+00)
  586.     _WrL3Data(MAX_VOLUME-volume, 0);
  587. }
  588. /*
  589. static void Muting(void)
  590. {
  591.     if(mute)    //Mute
  592.     {
  593.         _WrL3Addr(0x14 + 0);            //DATA0 (000101xx+00)
  594.         _WrL3Data(0xa4,0);              //10,1,00,1,00 : after, no de-emp, mute, flat 
  595.         mute = 0;
  596.     }
  597.     else        //No mute
  598.     {
  599.         _WrL3Addr(0x14 + 0);            //DATA0 (000101xx+00)
  600.         _WrL3Data(0xa0,0);              //10,1,00,0,00 : after, no de-emp, no mute, flat 
  601.         mute = 1;
  602.     }
  603. }
  604. */
  605. //==========================================================