You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

563 lines
19KB

  1. // Copyright 2014 Olivier Gillet.
  2. //
  3. // Author: Olivier Gillet (ol.gillet@gmail.com)
  4. //
  5. // Permission is hereby granted, free of charge, to any person obtaining a copy
  6. // of this software and associated documentation files (the "Software"), to deal
  7. // in the Software without restriction, including without limitation the rights
  8. // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  9. // copies of the Software, and to permit persons to whom the Software is
  10. // furnished to do so, subject to the following conditions:
  11. //
  12. // The above copyright notice and this permission notice shall be included in
  13. // all copies or substantial portions of the Software.
  14. //
  15. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  16. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  17. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  18. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  19. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  20. // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  21. // THE SOFTWARE.
  22. //
  23. // See http://creativecommons.org/licenses/MIT/ for more information.
  24. //
  25. // -----------------------------------------------------------------------------
  26. //
  27. // WM8371 Codec support.
  28. #include "rings/drivers/codec.h"
  29. #define CODEC_I2C I2C2
  30. #define CODEC_I2C_CLK RCC_APB1Periph_I2C2
  31. #define CODEC_I2C_GPIO_CLOCK RCC_AHB1Periph_GPIOB
  32. #define CODEC_I2C_GPIO_AF GPIO_AF_I2C2
  33. #define CODEC_I2C_GPIO GPIOB
  34. #define CODEC_I2C_SCL_PIN GPIO_Pin_10
  35. #define CODEC_I2C_SDA_PIN GPIO_Pin_11
  36. #define CODEC_I2C_SCL_PINSRC GPIO_PinSource10
  37. #define CODEC_I2C_SDA_PINSRC GPIO_PinSource11
  38. #define CODEC_TIMEOUT ((uint32_t)0x1000)
  39. #define CODEC_LONG_TIMEOUT ((uint32_t)(300 * CODEC_TIMEOUT))
  40. #define CODEC_I2C_SPEED 100000
  41. #define CODEC_I2S SPI2
  42. #define CODEC_I2S_EXT I2S2ext
  43. #define CODEC_I2S_CLK RCC_APB1Periph_SPI2
  44. #define CODEC_I2S_ADDRESS 0x4000380C
  45. #define CODEC_I2S_EXT_ADDRESS 0x4000340C
  46. #define CODEC_I2S_GPIO_AF GPIO_AF_SPI2
  47. #define CODEC_I2S_IRQ SPI2_IRQn
  48. #define CODEC_I2S_EXT_IRQ SPI2_IRQn
  49. #define CODEC_I2S_GPIO_CLOCK (RCC_AHB1Periph_GPIOC | RCC_AHB1Periph_GPIOB)
  50. #define CODEC_I2S_WS_PIN GPIO_Pin_12
  51. #define CODEC_I2S_SCK_PIN GPIO_Pin_13
  52. #define CODEC_I2S_SDI_PIN GPIO_Pin_14
  53. #define CODEC_I2S_SDO_PIN GPIO_Pin_15
  54. #define CODEC_I2S_MCK_PIN GPIO_Pin_6
  55. #define CODEC_I2S_WS_PINSRC GPIO_PinSource12
  56. #define CODEC_I2S_SCK_PINSRC GPIO_PinSource13
  57. #define CODEC_I2S_SDI_PINSRC GPIO_PinSource14
  58. #define CODEC_I2S_SDO_PINSRC GPIO_PinSource15
  59. #define CODEC_I2S_MCK_PINSRC GPIO_PinSource6
  60. #define CODEC_I2S_GPIO GPIOB
  61. #define CODEC_I2S_MCK_GPIO GPIOC
  62. #define AUDIO_I2S_IRQHandler SPI2_IRQHandler
  63. #define AUDIO_DMA_PERIPH_DATA_SIZE DMA_PeripheralDataSize_HalfWord
  64. #define AUDIO_DMA_MEM_DATA_SIZE DMA_MemoryDataSize_HalfWord
  65. #define AUDIO_I2S_DMA_CLOCK RCC_AHB1Periph_DMA1
  66. #define AUDIO_I2S_DMA_STREAM DMA1_Stream4
  67. #define AUDIO_I2S_DMA_DREG CODEC_I2S_ADDRESS
  68. #define AUDIO_I2S_DMA_CHANNEL DMA_Channel_0
  69. #define AUDIO_I2S_DMA_IRQ DMA1_Stream4_IRQn
  70. #define AUDIO_I2S_DMA_FLAG_TC DMA_FLAG_TCIF4
  71. #define AUDIO_I2S_DMA_FLAG_HT DMA_FLAG_HTIF4
  72. #define AUDIO_I2S_DMA_FLAG_FE DMA_FLAG_FEIF4
  73. #define AUDIO_I2S_DMA_FLAG_TE DMA_FLAG_TEIF4
  74. #define AUDIO_I2S_DMA_FLAG_DME DMA_FLAG_DMEIF4
  75. #define AUDIO_I2S_EXT_DMA_STREAM DMA1_Stream3
  76. #define AUDIO_I2S_EXT_DMA_DREG CODEC_I2S_EXT_ADDRESS
  77. #define AUDIO_I2S_EXT_DMA_CHANNEL DMA_Channel_3
  78. #define AUDIO_I2S_EXT_DMA_IRQ DMA1_Stream3_IRQn
  79. #define AUDIO_I2S_EXT_DMA_FLAG_TC DMA_FLAG_TCIF3
  80. #define AUDIO_I2S_EXT_DMA_FLAG_HT DMA_FLAG_HTIF3
  81. #define AUDIO_I2S_EXT_DMA_FLAG_FE DMA_FLAG_FEIF3
  82. #define AUDIO_I2S_EXT_DMA_FLAG_TE DMA_FLAG_TEIF3
  83. #define AUDIO_I2S_EXT_DMA_FLAG_DME DMA_FLAG_DMEIF3
  84. #define AUDIO_I2S_EXT_DMA_REG DMA1
  85. #define AUDIO_I2S_EXT_DMA_ISR LISR
  86. #define AUDIO_I2S_EXT_DMA_IFCR LIFCR
  87. #define W8731_ADDR_0 0x1A
  88. #define W8731_ADDR_1 0x1B
  89. #define W8731_NUM_REGS 10
  90. #define CODEC_ADDRESS (W8731_ADDR_0 << 1)
  91. #define WAIT_LONG(x) { \
  92. uint32_t timeout = CODEC_LONG_TIMEOUT; \
  93. while (x) { if ((timeout--) == 0) return false; } \
  94. }
  95. #define WAIT(x) { \
  96. uint32_t timeout = CODEC_TIMEOUT; \
  97. while (x) { if ((timeout--) == 0) return false; } \
  98. }
  99. namespace rings {
  100. /* static */
  101. Codec* Codec::instance_;
  102. enum CodecRegister {
  103. CODEC_REG_LEFT_LINE_IN = 0x00,
  104. CODEC_REG_RIGHT_LINE_IN = 0x01,
  105. CODEC_REG_LEFT_HEADPHONES_OUT = 0x02,
  106. CODEC_REG_RIGHT_HEADPHONES_OUT = 0x03,
  107. CODEC_REG_ANALOGUE_ROUTING = 0x04,
  108. CODEC_REG_DIGITAL_ROUTING = 0x05,
  109. CODEC_REG_POWER_MANAGEMENT = 0x06,
  110. CODEC_REG_DIGITAL_FORMAT = 0x07,
  111. CODEC_REG_SAMPLE_RATE = 0x08,
  112. CODEC_REG_ACTIVE = 0x09,
  113. CODEC_REG_RESET = 0x0f,
  114. };
  115. enum CodecSettings {
  116. CODEC_INPUT_0_DB = 0x17,
  117. CODEC_INPUT_UPDATE_BOTH = 0x40,
  118. CODEC_HEADPHONES_MUTE = 0x00,
  119. CODEC_MIC_BOOST = 0x1,
  120. CODEC_MIC_MUTE = 0x2,
  121. CODEC_ADC_MIC = 0x4,
  122. CODEC_ADC_LINE = 0x0,
  123. CODEC_OUTPUT_DAC_ENABLE = 0x10,
  124. CODEC_OUTPUT_MONITOR = 0x20,
  125. CODEC_DEEMPHASIS_NONE = 0x00,
  126. CODEC_DEEMPHASIS_32K = 0x01,
  127. CODEC_DEEMPHASIS_44K = 0x02,
  128. CODEC_DEEMPHASIS_48K = 0x03,
  129. CODEC_SOFT_MUTE = 0x01,
  130. CODEC_ADC_HPF = 0x00,
  131. CODEC_POWER_DOWN_LINE_IN = 0x01,
  132. CODEC_POWER_DOWN_MIC = 0x02,
  133. CODEC_POWER_DOWN_ADC = 0x04,
  134. CODEC_POWER_DOWN_DAC = 0x08,
  135. CODEC_POWER_DOWN_LINE_OUT = 0x10,
  136. CODEC_POWER_DOWN_OSCILLATOR = 0x20,
  137. CODEC_POWER_DOWN_CLOCK_OUTPUT = 0x40,
  138. CODEC_POWER_DOWN_EVERYTHING = 0x80,
  139. CODEC_PROTOCOL_MASK_MSB_FIRST = 0x00,
  140. CODEC_PROTOCOL_MASK_LSB_FIRST = 0x01,
  141. CODEC_PROTOCOL_MASK_PHILIPS = 0x02,
  142. CODEC_PROTOCOL_MASK_DSP = 0x03,
  143. CODEC_FORMAT_MASK_16_BIT = 0x00 << 2,
  144. CODEC_FORMAT_MASK_20_BIT = 0x01 << 2,
  145. CODEC_FORMAT_MASK_24_BIT = 0x02 << 2,
  146. CODEC_FORMAT_MASK_32_BIT = 0x03 << 2,
  147. CODEC_FORMAT_LR_SWAP = 0x20,
  148. CODEC_FORMAT_MASTER = 0x40,
  149. CODEC_FORMAT_SLAVE = 0x00,
  150. CODEC_FORMAT_INVERT_CLOCK = 0x80,
  151. CODEC_RATE_48K_48K = 0x00 << 2,
  152. CODEC_RATE_8K_8K = 0x03 << 2,
  153. CODEC_RATE_96K_96K = 0x07 << 2,
  154. CODEC_RATE_32K_32K = 0x06 << 2,
  155. CODEC_RATE_44K_44K = 0x08 << 2,
  156. };
  157. bool Codec::InitializeGPIO() {
  158. GPIO_InitTypeDef gpio_init;
  159. // Start GPIO peripheral clocks.
  160. RCC_AHB1PeriphClockCmd(CODEC_I2C_GPIO_CLOCK | CODEC_I2S_GPIO_CLOCK, ENABLE);
  161. // Initialize I2C pins
  162. gpio_init.GPIO_Pin = CODEC_I2C_SCL_PIN | CODEC_I2C_SDA_PIN;
  163. gpio_init.GPIO_Mode = GPIO_Mode_AF;
  164. gpio_init.GPIO_Speed = GPIO_Speed_50MHz;
  165. gpio_init.GPIO_OType = GPIO_OType_OD;
  166. gpio_init.GPIO_PuPd = GPIO_PuPd_NOPULL;
  167. GPIO_Init(CODEC_I2C_GPIO, &gpio_init);
  168. // Connect pins to I2C peripheral
  169. GPIO_PinAFConfig(CODEC_I2C_GPIO, CODEC_I2C_SCL_PINSRC, CODEC_I2C_GPIO_AF);
  170. GPIO_PinAFConfig(CODEC_I2C_GPIO, CODEC_I2C_SDA_PINSRC, CODEC_I2C_GPIO_AF);
  171. // Initialize I2S pins
  172. gpio_init.GPIO_Pin = CODEC_I2S_SCK_PIN | CODEC_I2S_SDO_PIN | \
  173. CODEC_I2S_SDI_PIN | CODEC_I2S_WS_PIN;
  174. gpio_init.GPIO_Mode = GPIO_Mode_AF;
  175. gpio_init.GPIO_Speed = GPIO_Speed_50MHz;
  176. gpio_init.GPIO_OType = GPIO_OType_PP;
  177. gpio_init.GPIO_PuPd = GPIO_PuPd_NOPULL;
  178. GPIO_Init(CODEC_I2S_GPIO, &gpio_init);
  179. gpio_init.GPIO_Pin = CODEC_I2S_MCK_PIN;
  180. GPIO_Init(CODEC_I2S_MCK_GPIO, &gpio_init);
  181. // Connect pins to I2S peripheral.
  182. GPIO_PinAFConfig(CODEC_I2S_GPIO, CODEC_I2S_WS_PINSRC, CODEC_I2S_GPIO_AF);
  183. GPIO_PinAFConfig(CODEC_I2S_GPIO, CODEC_I2S_SCK_PINSRC, CODEC_I2S_GPIO_AF);
  184. GPIO_PinAFConfig(CODEC_I2S_GPIO, CODEC_I2S_SDO_PINSRC, CODEC_I2S_GPIO_AF);
  185. GPIO_PinAFConfig(CODEC_I2S_GPIO, CODEC_I2S_SDI_PINSRC, CODEC_I2S_GPIO_AF);
  186. GPIO_PinAFConfig(CODEC_I2S_MCK_GPIO, CODEC_I2S_MCK_PINSRC, CODEC_I2S_GPIO_AF);
  187. return true;
  188. }
  189. bool Codec::InitializeControlInterface() {
  190. I2C_InitTypeDef i2c_init;
  191. // Initialize I2C
  192. RCC_APB1PeriphClockCmd(CODEC_I2C_CLK, ENABLE);
  193. I2C_DeInit(CODEC_I2C);
  194. i2c_init.I2C_Mode = I2C_Mode_I2C;
  195. i2c_init.I2C_DutyCycle = I2C_DutyCycle_2;
  196. i2c_init.I2C_OwnAddress1 = 0x33;
  197. i2c_init.I2C_Ack = I2C_Ack_Enable;
  198. i2c_init.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;
  199. i2c_init.I2C_ClockSpeed = CODEC_I2C_SPEED;
  200. I2C_Init(CODEC_I2C, &i2c_init);
  201. I2C_Cmd(CODEC_I2C, ENABLE);
  202. return true;
  203. }
  204. bool Codec::InitializeAudioInterface(
  205. bool mcu_is_master,
  206. int32_t sample_rate) {
  207. // Configure PLL and I2S master clock.
  208. RCC_I2SCLKConfig(RCC_I2S2CLKSource_PLLI2S);
  209. // The following values have been computed for a 8Mhz external crystal!
  210. RCC_PLLI2SCmd(DISABLE);
  211. if (sample_rate == 48000) {
  212. // 47.992kHz
  213. RCC_PLLI2SConfig(258, 3);
  214. } else if (sample_rate == 44100) {
  215. // 44.11kHz
  216. RCC_PLLI2SConfig(271, 6);
  217. } else if (sample_rate == 32000) {
  218. // 32.003kHz
  219. RCC_PLLI2SConfig(426, 4);
  220. } else if (sample_rate == 96000) {
  221. // 95.95 kHz
  222. RCC_PLLI2SConfig(393, 4);
  223. } else {
  224. // Unsupported sample rate!
  225. return false;
  226. }
  227. RCC_PLLI2SCmd(ENABLE);
  228. WAIT(RCC_GetFlagStatus(RCC_FLAG_PLLI2SRDY) == RESET);
  229. RCC_APB1PeriphClockCmd(CODEC_I2S_CLK, ENABLE);
  230. // Initialize I2S
  231. I2S_InitTypeDef i2s_init;
  232. SPI_I2S_DeInit(CODEC_I2S);
  233. i2s_init.I2S_AudioFreq = sample_rate;
  234. i2s_init.I2S_Standard = I2S_Standard_Phillips;
  235. i2s_init.I2S_DataFormat = I2S_DataFormat_16b;
  236. i2s_init.I2S_CPOL = I2S_CPOL_Low;
  237. i2s_init.I2S_Mode = mcu_is_master ? I2S_Mode_MasterTx : I2S_Mode_SlaveTx;
  238. i2s_init.I2S_MCLKOutput = mcu_is_master
  239. ? I2S_MCLKOutput_Enable
  240. : I2S_MCLKOutput_Disable;
  241. // Initialize the I2S main channel for TX
  242. I2S_Init(CODEC_I2S, &i2s_init);
  243. // Initialize the I2S extended channel for RX
  244. I2S_FullDuplexConfig(CODEC_I2S_EXT, &i2s_init);
  245. return true;
  246. }
  247. bool Codec::WriteControlRegister(uint8_t address, uint16_t data) {
  248. uint8_t byte_1 = ((address << 1) & 0xfe) | ((data >> 8) & 0x01);
  249. uint8_t byte_2 = data & 0xff;
  250. WAIT_LONG(I2C_GetFlagStatus(CODEC_I2C, I2C_FLAG_BUSY));
  251. I2C_GenerateSTART(CODEC_I2C, ENABLE);
  252. WAIT(!I2C_CheckEvent(CODEC_I2C, I2C_EVENT_MASTER_MODE_SELECT));
  253. I2C_Send7bitAddress(CODEC_I2C, CODEC_ADDRESS, I2C_Direction_Transmitter);
  254. WAIT(!I2C_CheckEvent(CODEC_I2C, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));
  255. I2C_SendData(CODEC_I2C, byte_1);
  256. WAIT(!I2C_CheckEvent(CODEC_I2C, I2C_EVENT_MASTER_BYTE_TRANSMITTING));
  257. I2C_SendData(CODEC_I2C, byte_2);
  258. WAIT(!I2C_CheckEvent(CODEC_I2C, I2C_EVENT_MASTER_BYTE_TRANSMITTING));
  259. WAIT_LONG(!I2C_GetFlagStatus(CODEC_I2C, I2C_FLAG_BTF));
  260. I2C_GenerateSTOP(CODEC_I2C, ENABLE);
  261. return true;
  262. }
  263. bool Codec::InitializeCodec(
  264. bool mcu_is_master,
  265. int32_t sample_rate) {
  266. bool s = true; // success;
  267. s = s && WriteControlRegister(CODEC_REG_RESET, 0);
  268. // Configure L&R inputs
  269. s = s && WriteControlRegister(CODEC_REG_LEFT_LINE_IN, CODEC_INPUT_0_DB);
  270. s = s && WriteControlRegister(CODEC_REG_RIGHT_LINE_IN, CODEC_INPUT_0_DB);
  271. // Configure L&R headphone outputs
  272. s = s && WriteControlRegister(CODEC_REG_LEFT_HEADPHONES_OUT, CODEC_HEADPHONES_MUTE);
  273. s = s && WriteControlRegister(CODEC_REG_RIGHT_HEADPHONES_OUT, CODEC_HEADPHONES_MUTE);
  274. // Configure analog routing
  275. s = s && WriteControlRegister(
  276. CODEC_REG_ANALOGUE_ROUTING,
  277. CODEC_MIC_MUTE | CODEC_ADC_LINE | CODEC_OUTPUT_DAC_ENABLE);
  278. // Configure digital routing
  279. s = s && WriteControlRegister(CODEC_REG_DIGITAL_ROUTING, CODEC_DEEMPHASIS_NONE);
  280. // Configure power management
  281. uint8_t power_down_reg = CODEC_POWER_DOWN_MIC | CODEC_POWER_DOWN_CLOCK_OUTPUT;
  282. if (mcu_is_master) {
  283. power_down_reg |= CODEC_POWER_DOWN_OSCILLATOR;
  284. }
  285. s = s && WriteControlRegister(CODEC_REG_POWER_MANAGEMENT, power_down_reg);
  286. uint8_t format_byte = CODEC_PROTOCOL_MASK_PHILIPS | CODEC_FORMAT_MASK_16_BIT;
  287. format_byte |= mcu_is_master ? CODEC_FORMAT_SLAVE : CODEC_FORMAT_MASTER;
  288. s = s && WriteControlRegister(CODEC_REG_DIGITAL_FORMAT, format_byte);
  289. uint8_t rate_byte = 0;
  290. if (mcu_is_master) {
  291. // According to the WM8731 datasheet, the 32kHz and 96kHz modes require the
  292. // master clock to be at 12.288 MHz (384 fs / 128 fs). The STM32F4 I2S clock
  293. // is always at 256 fs. So the 32kHz and 96kHz modes are achieved by
  294. // pretending that we are doing 48kHz, but with a slower or faster master
  295. // clock.
  296. rate_byte = sample_rate == 44100 ? CODEC_RATE_44K_44K : CODEC_RATE_48K_48K;
  297. } else {
  298. switch (sample_rate) {
  299. case 8000:
  300. rate_byte = CODEC_RATE_8K_8K;
  301. break;
  302. case 32000:
  303. rate_byte = CODEC_RATE_32K_32K;
  304. break;
  305. case 44100:
  306. rate_byte = CODEC_RATE_44K_44K;
  307. break;
  308. case 96000:
  309. rate_byte = CODEC_RATE_96K_96K;
  310. break;
  311. case 48000:
  312. default:
  313. rate_byte = CODEC_RATE_48K_48K;
  314. break;
  315. }
  316. }
  317. s = s && WriteControlRegister(CODEC_REG_SAMPLE_RATE, rate_byte);
  318. // For now codec is not active.
  319. s = s && WriteControlRegister(CODEC_REG_ACTIVE, 0x00);
  320. return s;
  321. }
  322. bool Codec::InitializeDMA() {
  323. RCC_AHB1PeriphClockCmd(AUDIO_I2S_DMA_CLOCK, ENABLE);
  324. // DMA setup for TX.
  325. DMA_Cmd(AUDIO_I2S_DMA_STREAM, DISABLE);
  326. DMA_DeInit(AUDIO_I2S_DMA_STREAM);
  327. dma_init_tx_.DMA_Channel = AUDIO_I2S_DMA_CHANNEL;
  328. dma_init_tx_.DMA_PeripheralBaseAddr = AUDIO_I2S_DMA_DREG;
  329. dma_init_tx_.DMA_Memory0BaseAddr = (uint32_t)0;
  330. dma_init_tx_.DMA_DIR = DMA_DIR_MemoryToPeripheral;
  331. dma_init_tx_.DMA_BufferSize = (uint32_t)0xFFFE;
  332. dma_init_tx_.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
  333. dma_init_tx_.DMA_MemoryInc = DMA_MemoryInc_Enable;
  334. dma_init_tx_.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
  335. dma_init_tx_.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
  336. dma_init_tx_.DMA_Mode = DMA_Mode_Circular;
  337. dma_init_tx_.DMA_Priority = DMA_Priority_High;
  338. dma_init_tx_.DMA_FIFOMode = DMA_FIFOMode_Disable;
  339. dma_init_tx_.DMA_FIFOThreshold = DMA_FIFOThreshold_1QuarterFull;
  340. dma_init_tx_.DMA_MemoryBurst = DMA_MemoryBurst_Single;
  341. dma_init_tx_.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
  342. DMA_Init(AUDIO_I2S_DMA_STREAM, &dma_init_tx_);
  343. // DMA setup for RX.
  344. DMA_Cmd(AUDIO_I2S_EXT_DMA_STREAM, DISABLE);
  345. DMA_DeInit(AUDIO_I2S_EXT_DMA_STREAM);
  346. dma_init_rx_.DMA_Channel = AUDIO_I2S_EXT_DMA_CHANNEL;
  347. dma_init_rx_.DMA_PeripheralBaseAddr = AUDIO_I2S_EXT_DMA_DREG;
  348. dma_init_rx_.DMA_Memory0BaseAddr = (uint32_t)0;
  349. dma_init_rx_.DMA_DIR = DMA_DIR_PeripheralToMemory;
  350. dma_init_rx_.DMA_BufferSize = (uint32_t)0xFFFE;
  351. dma_init_rx_.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
  352. dma_init_rx_.DMA_MemoryInc = DMA_MemoryInc_Enable;
  353. dma_init_rx_.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
  354. dma_init_rx_.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
  355. dma_init_rx_.DMA_Mode = DMA_Mode_Circular;
  356. dma_init_rx_.DMA_Priority = DMA_Priority_High;
  357. dma_init_rx_.DMA_FIFOMode = DMA_FIFOMode_Disable;
  358. dma_init_rx_.DMA_FIFOThreshold = DMA_FIFOThreshold_1QuarterFull;
  359. dma_init_rx_.DMA_MemoryBurst = DMA_MemoryBurst_Single;
  360. dma_init_rx_.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
  361. DMA_Init(AUDIO_I2S_EXT_DMA_STREAM, &dma_init_rx_);
  362. // Enable the interrupts.
  363. DMA_ITConfig(AUDIO_I2S_EXT_DMA_STREAM, DMA_IT_TC | DMA_IT_HT, ENABLE);
  364. // Enable the IRQ.
  365. NVIC_EnableIRQ(AUDIO_I2S_EXT_DMA_IRQ);
  366. // Start DMA from/to codec.
  367. SPI_I2S_DMACmd(CODEC_I2S, SPI_I2S_DMAReq_Tx, ENABLE);
  368. SPI_I2S_DMACmd(CODEC_I2S_EXT, SPI_I2S_DMAReq_Rx, ENABLE);
  369. return true;
  370. }
  371. bool Codec::Init(
  372. bool mcu_is_master,
  373. int32_t sample_rate) {
  374. instance_ = this;
  375. callback_ = NULL;
  376. sample_rate_ = sample_rate;
  377. mcu_is_master_ = mcu_is_master;
  378. return InitializeGPIO() && \
  379. InitializeControlInterface() && \
  380. InitializeAudioInterface(mcu_is_master, sample_rate) && \
  381. InitializeCodec(mcu_is_master, sample_rate) && \
  382. InitializeDMA();
  383. }
  384. bool Codec::Start(size_t block_size, FillBufferCallback callback) {
  385. // Start the codec.
  386. if (!WriteControlRegister(CODEC_REG_ACTIVE, 0x01)) {
  387. return false;
  388. }
  389. if (block_size > kMaxCodecBlockSize) {
  390. return false;
  391. }
  392. if (!mcu_is_master_) {
  393. while(GPIO_ReadInputDataBit(CODEC_I2S_GPIO, CODEC_I2S_WS_PIN));
  394. while(!GPIO_ReadInputDataBit(CODEC_I2S_GPIO, CODEC_I2S_WS_PIN));
  395. }
  396. callback_ = callback;
  397. // Enable the I2S TX and RX peripherals.
  398. if ((CODEC_I2S->I2SCFGR & 0x0400) == 0){
  399. I2S_Cmd(CODEC_I2S, ENABLE);
  400. }
  401. if ((CODEC_I2S_EXT->I2SCFGR & 0x0400) == 0){
  402. I2S_Cmd(CODEC_I2S_EXT, ENABLE);
  403. }
  404. dma_init_tx_.DMA_Memory0BaseAddr = (uint32_t)(tx_dma_buffer_);
  405. dma_init_rx_.DMA_Memory0BaseAddr = (uint32_t)(rx_dma_buffer_);
  406. size_t stride = 1;
  407. if (!mcu_is_master_) {
  408. // When the WM8731 is the master, the data is sent with padding.
  409. switch (sample_rate_) {
  410. case 32000:
  411. stride = 3;
  412. break;
  413. case 48000:
  414. stride = 2;
  415. break;
  416. case 96000:
  417. stride = 4;
  418. break;
  419. }
  420. }
  421. block_size_ = block_size;
  422. stride_ = stride;
  423. dma_init_tx_.DMA_BufferSize = 2 * stride * block_size * 2;
  424. dma_init_rx_.DMA_BufferSize = 2 * stride * block_size * 2;
  425. DMA_Init(AUDIO_I2S_DMA_STREAM, &dma_init_tx_);
  426. DMA_Init(AUDIO_I2S_EXT_DMA_STREAM, &dma_init_rx_);
  427. DMA_Cmd(AUDIO_I2S_DMA_STREAM, ENABLE);
  428. DMA_Cmd(AUDIO_I2S_EXT_DMA_STREAM, ENABLE);
  429. return true;
  430. }
  431. void Codec::Stop() {
  432. DMA_Cmd(AUDIO_I2S_DMA_STREAM, DISABLE);
  433. DMA_Cmd(AUDIO_I2S_EXT_DMA_STREAM, DISABLE);
  434. }
  435. bool Codec::set_line_input_gain(int32_t channel, int32_t gain) {
  436. return WriteControlRegister(CODEC_REG_LEFT_LINE_IN + channel, gain);
  437. }
  438. bool Codec::set_line_input_gain(int32_t gain) {
  439. return WriteControlRegister(0, gain) && WriteControlRegister(1, gain);
  440. }
  441. void Codec::Fill(size_t offset) {
  442. if (callback_) {
  443. offset *= block_size_ * stride_ * 2;
  444. short* in = &rx_dma_buffer_[offset];
  445. short* out = &tx_dma_buffer_[offset];
  446. if (stride_) {
  447. // Undo the padding from the WM8731.
  448. for (size_t i = 1; i < block_size_ * 2; ++i) {
  449. in[i] = in[i * stride_];
  450. }
  451. }
  452. (*callback_)((Frame*)(in), (Frame*)(out), block_size_);
  453. if (stride_) {
  454. // Pad for the WM8731.
  455. for (size_t i = block_size_ * 2 - 1; i > 0; --i) {
  456. out[i * stride_] = out[i];
  457. }
  458. }
  459. }
  460. }
  461. } // namespace rings
  462. extern "C" {
  463. // Do not call into the firmware library to save on calls/jumps.
  464. // if (DMA_GetFlagStatus(AUDIO_I2S_EXT_DMA_STREAM, AUDIO_I2S_EXT_DMA_FLAG_TC) != RESET) {
  465. // DMA_ClearFlag(AUDIO_I2S_EXT_DMA_STREAM, AUDIO_I2S_EXT_DMA_FLAG_TC);
  466. void DMA1_Stream3_IRQHandler(void) {
  467. if (AUDIO_I2S_EXT_DMA_REG->AUDIO_I2S_EXT_DMA_ISR & AUDIO_I2S_EXT_DMA_FLAG_TC) {
  468. AUDIO_I2S_EXT_DMA_REG->AUDIO_I2S_EXT_DMA_IFCR = AUDIO_I2S_EXT_DMA_FLAG_TC;
  469. rings::Codec::GetInstance()->Fill(1);
  470. }
  471. if (AUDIO_I2S_EXT_DMA_REG->AUDIO_I2S_EXT_DMA_ISR & AUDIO_I2S_EXT_DMA_FLAG_HT) {
  472. AUDIO_I2S_EXT_DMA_REG->AUDIO_I2S_EXT_DMA_IFCR = AUDIO_I2S_EXT_DMA_FLAG_HT;
  473. rings::Codec::GetInstance()->Fill(0);
  474. }
  475. }
  476. }