i2s.cpp
上传用户:qiulin1960
上传日期:2013-10-16
资源大小:2844k
文件大小:9k
源码类别:

Windows CE

开发平台:

Windows_Unix

  1. //
  2. // Copyright (c) Microsoft Corporation.  All rights reserved.
  3. //
  4. //
  5. // Use of this source code is subject to the terms of the Microsoft end-user
  6. // license agreement (EULA) under which you licensed this SOFTWARE PRODUCT.
  7. // If you did not accept the terms of the EULA, you are not authorized to use
  8. // this source code. For a copy of the EULA, please see the LICENSE.RTF on your
  9. // install media.
  10. //
  11. /*++
  12. THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
  13. ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
  14. THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
  15. PARTICULAR PURPOSE.
  16.    
  17. Module Name: I2S.CPP
  18. Abstract: I2S Interface Routines for Samsung SC2410 CPU
  19.   
  20. Notes: This code assumes that the CPU acts as the master that is 
  21. connected to a CODEC chip configured in slave mode.
  22. Some platforms require the audio CODEC chip to act as the master
  23. while the CPU's IIS controller is put into slave mode.  For these
  24. environments, the IIS_MASTER_MODE flag (located in I2S_Init())
  25. should be replaced with the IIS_SLAVE_MODE flag.
  26. Environment: Samsung SC2410 CPU and Windows 3.0 (or later)
  27.     
  28. -*/
  29. #include <windows.h>
  30. #include "i2s.h"
  31. //------------------------------ GLOBALS -------------------------------------------
  32. extern volatile IISreg *v_pIISregs; // I2S control registers
  33. extern volatile IOPreg *v_pIOPregs; // GPIO registers (needed to enable SPI)
  34. extern volatile CLKPWRreg *g_pCLKPWRreg; // CLCKPWR (needed to enable SPI clocks)
  35. //----------------------------------------------------------------------------------
  36. //#define DEBUGMSG(a,b) RETAILMSG(0,b)
  37. #ifdef DEBUG
  38. #define ZONE_ERROR  1
  39. #endif
  40. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  41. Function: I2S_Init()
  42. Description: Initializes the IIS bus and controller.
  43. Notes: This routine assumes that the control registers (see 
  44. the globals section above) have already been initialized.
  45. Returns: Boolean indicating success.
  46. -------------------------------------------------------------------*/
  47. BOOL I2S_Init()
  48. {
  49. //----- 1. IMPORTANT: By default, the internal clock is disabled.  To configure the controller ------
  50. //   we must first enable it.
  51. // StartI2SClock();
  52. g_pCLKPWRreg->rCLKCON |= IIS_INTERNAL_CLOCK_ENABLE; // Enable the CPU clock to the IIS controller
  53. //----- 2. Configure the GPIO pins for I2S mode -----
  54. //    
  55. //    I2SSDO - GPE4
  56. //    I2SSDI - GPE3
  57. //    I2SCDCLK - GPE2
  58. //    I2SSCLK - GPE1
  59. //    I2SLRCLK - GPE0
  60. //
  61. // charlie
  62. // v_pIOPregs->rGPECON |= (ENABLE_I2SSDO | ENABLE_I2SSDI | ENABLE_I2SCDCLK | ENABLE_I2SSCLK | ENABLE_I2SLRCLK);
  63. // v_pIOPregs->rGPEUP  |= DISABLE_I2S_PULLUPS;
  64. // Port Init for IIS
  65. v_pIOPregs->rGPEUP  |= 0x1f;
  66. //PG[4:0]=I2SSDI:I2SSDO:CDCLK:I2SSCLK:I2SLRCK
  67. v_pIOPregs->rGPECON = ((v_pIOPregs->rGPECON & 0xfffffc00) | 0x2aa);
  68. //----- 3. Configure the I2S controller with reasonable default values -----
  69. // v_pIISregs->rIISCON  = (TRANSMIT_DMA_REQUEST_ENABLE | RECEIVE_DMA_REQUEST_ENABLE | IIS_PRESCALER_ENABLE);
  70. // charlie
  71. v_pIISregs->rIISCON  = (TRANSMIT_DMA_REQUEST_ENABLE | IIS_PRESCALER_ENABLE);
  72. //---------------------------------------------------------------------------------------------------------
  73. // On SMDK2410 board, Audio codec left/right outputs are mis-connected to a stereo headphone jack.
  74. // So, I define that active level of left/right channel is "HIGH for left channel" (ACTIVE_CHANNEL_RIGHT).
  75. //---------------------------------------------------------------------------------------------------------
  76. //v_pIISregs->rIISMOD  = (  IIS_MASTER_MODE | IIS_TRANSMIT_RECEIVE_MODE | ACTIVE_CHANNEL_LEFT
  77. v_pIISregs->rIISMOD  = (  IIS_MASTER_MODE | IIS_TRANSMIT_RECEIVE_MODE | ACTIVE_CHANNEL_RIGHT
  78.    | SERIAL_INTERFACE_IIS_COMPAT | DATA_16_BITS_PER_CHANNEL
  79.    | MASTER_CLOCK_FREQ_384fs | SERIAL_BIT_CLOCK_FREQ_32fs );
  80. //---------------------------------------------------------------------------------------------------------
  81. v_pIISregs->rIISFCON = (  TRANSMIT_FIFO_ACCESS_DMA | TRANSMIT_FIFO_ENABLE  );
  82. SetI2SClockRate(IS2LRCLK_44100);
  83. //----- 4. For power management purposes, shut the clocks off! -----
  84.     StopI2SClock();
  85. // charlie
  86. v_pIISregs->rIISCON |= IIS_INTERFACE_ENABLE; // Enable the I2S clock
  87. return TRUE;
  88. }
  89. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  90. Function: I2S_Deinit()
  91. Description: Deinitializes the I2S bus and controller.
  92. Notes: This routine DOES NOT unmap the control registers;
  93. the caller is responsible for freeing this memory.
  94. Returns: Boolean indicating success.
  95. -------------------------------------------------------------------*/
  96. BOOL I2S_Deinit()
  97. {
  98.     //----- 1. Stop the I2S clocks -----
  99.     StopI2SClock();
  100. return TRUE;
  101. }
  102. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  103. Function: I2S_WriteData()
  104. Description: Outputs the specified data onto the I2S bus.
  105. Notes: This routine expects that the I2S clock is already
  106. running when it is called.
  107. Returns: Boolean indicating success.
  108. -------------------------------------------------------------------*/
  109. BOOL I2S_WriteData(LPWORD lpBuff, DWORD dwLen)
  110. {
  111. static DWORD waitCount = 0;
  112. static DWORD i = 0;
  113. //----- 1. Check the parameters -----
  114. if(!lpBuff || (dwLen == 0))
  115. {
  116. DEBUGMSG(ZONE_ERROR, (TEXT("WAVEDEV.DLL:I2S_WriteData() - Invalid parameters!rn")));  
  117.         goto WRITE_ERROR;
  118. }
  119. // StartI2SClock();
  120. //----- 2. Enable the transmit FIFO -----
  121. v_pIISregs->rIISFCON |= TRANSMIT_FIFO_ENABLE;
  122. //----- 3. Write all of the bytes in the input buffer onto the I2S bus -----
  123. while(dwLen)
  124. {
  125. //----- 4. Write a FIFO's worth of data out onto the I2S bus ----- 
  126. if(dwLen > MAX_TRANSMIT_FIFO_ENTRIES)
  127. {
  128. i = MAX_TRANSMIT_FIFO_ENTRIES;
  129. }else
  130. {
  131. i = dwLen;
  132. }
  133. dwLen -= i;
  134. while(i--);
  135. {
  136. v_pIISregs->rIISFIF = *lpBuff++;
  137. }
  138. }
  139. StopI2SClock();
  140. return TRUE;
  141. WRITE_ERROR:
  142. StopI2SClock();
  143. return FALSE;
  144. }
  145. //------------------------------------ Helper Routines ------------------------------------
  146. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  147. Function: StartI2SClock()
  148. Description: Enables the I2S clock that drives the audio codec chip.
  149. Returns: N/A
  150. -------------------------------------------------------------------*/
  151. VOID StartI2SClock(VOID)
  152. {
  153. return;
  154. }
  155. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  156. Function: StopI2SClock()
  157. Description: Disables the I2S clock that drives the audio codec chip.
  158. Returns: N/A
  159. -------------------------------------------------------------------*/
  160. VOID StopI2SClock(VOID)
  161. {
  162. // v_pIISregs->rIISCON &= ~IIS_INTERFACE_ENABLE; // Disable the I2S clock
  163. // charlie
  164. // g_pCLKPWRreg->rCLKCON &= ~IIS_INTERNAL_CLOCK_ENABLE; // Disable the CPU clock to the SPI controller
  165. return;
  166. }
  167. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  168. Function: SetI2SClockRate()
  169. Description: Sets the I2S clock that drives the audio codec chip:
  170. Params: ClockRate IS2LRCLK_800 800   Khz
  171. IS2LRCLK_11025 11025 Khz
  172. IS2LRCLK_16000 16000 Khz
  173. IS2LRCLK_22050 22050 Khz
  174. IS2LRCLK_32000 32000 Khz
  175. IS2LRCLK_44100 44100 Khz
  176. IS2LRCLK_48000 48000 Khz
  177. IS2LRCLK_64000 64000 Khz
  178. IS2LRCLK_88200 88200 Khz
  179. IS2LRCLK_96000 96000 Khz
  180. Returns: N/A
  181. -------------------------------------------------------------------*/
  182. VOID SetI2SClockRate(DWORD ClockRate)
  183. {
  184. BYTE  prescaler;
  185. DWORD codeclock, i2scdclk;
  186.     //----- 1. Set the clock rate  -----
  187. // FORMAT: bits[9:5] - Prescaler Control A
  188. // bits[4:0] - Prescaler Control B
  189. //
  190. // Range: 0-31 and the division factor is N+1 (a.k.a. 1-32)
  191. //
  192. // The I2SLRCLK frequency is determined as follows:
  193. //
  194. // I2SLRCLK = CODECLK / I2SCDCLK and (prescaler+1) = PCLK / CODECLK
  195. //
  196. // Thus, rearranging the equations a bit we can see that:
  197. //
  198. // prescaler = (PCLK / CODECLK) - 1 
  199. // or
  200. // prescaler = ((PCLK / (IS2LRCLK * IS2CDCLK)) - 1
  201. //
  202. //     NOTE: The following formula is actually used in order to avoid floating point arithmetic:
  203. //
  204. // prescaler = ((PCLK + ((IS2LRCLK * IS2CDCLK) - 1)) / (IS2LRCLK * IS2CDCLK)) - 1
  205. //
  206. if(v_pIISregs->rIISMOD & MASTER_CLOCK_FREQ_384fs)
  207. {
  208. i2scdclk = 384; // Sampling frequency
  209. }else
  210. {
  211. i2scdclk = 256; // Sampling frequency
  212. }
  213. codeclock = ClockRate * i2scdclk;
  214. prescaler = (BYTE)((S2440PCLK + (codeclock - 1)) / codeclock) - 1;
  215. // RETAILMSG(1,(TEXT("Prescaler:%dn"),prescaler));
  216. //----- IMPORTANT: Make sure we set both channel prescalers to the same value (see datasheet for details) -----
  217. v_pIISregs->rIISPSR = ((prescaler << 5) + prescaler);
  218.     return;
  219. }