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.

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