source: azure_iot_hub_f767zi/trunk/asp_baseplatform/gdic/staudio_wm8994/staudio_wm8994.c@ 457

Last change on this file since 457 was 457, checked in by coas-nagasima, 4 years ago

ファイルを追加

  • Property svn:eol-style set to native
  • Property svn:mime-type set to text/x-csrc;charset=UTF-8
File size: 89.6 KB
Line 
1/*
2 * TOPPERS BASE PLATFORM MIDDLEWARE
3 *
4 * Copyright (C) 2017-2018 by TOPPERS PROJECT
5 * Educational Working Group.
6 *
7 * 上記著作権者は,以下の(1)~(4)の条件を満たす場合に限り,本ソフトウェ
8 * ア(本ソフトウェアを改変したものを含む.以下同じ)を使用・複製・改
9 * 変・再配布(以下,利用と呼ぶ)することを無償で許諾する.
10 * (1) 本ソフトウェアをソースコードの形で利用する場合には,上記の著作
11 * 権表示,この利用条件および下記の無保証規定が,そのままの形でソー
12 * スコード中に含まれていること.
13 * (2) 本ソフトウェアを,ライブラリ形式など,他のソフトウェア開発に使
14 * 用できる形で再配布する場合には,再配布に伴うドキュメント(利用
15 * 者マニュアルなど)に,上記の著作権表示,この利用条件および下記
16 * の無保証規定を掲載すること.
17 * (3) 本ソフトウェアを,機器に組み込むなど,他のソフトウェア開発に使
18 * 用できない形で再配布する場合には,次のいずれかの条件を満たすこ
19 * と.
20 * (a) 再配布に伴うドキュメント(利用者マニュアルなど)に,上記の著
21 * 作権表示,この利用条件および下記の無保証規定を掲載すること.
22 * (b) 再配布の形態を,別に定める方法によって,TOPPERSプロジェクトに
23 * 報告すること.
24 * (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
25 * 害からも,上記著作権者およびTOPPERSプロジェクトを免責すること.
26 * また,本ソフトウェアのユーザまたはエンドユーザからのいかなる理
27 * 由に基づく請求からも,上記著作権者およびTOPPERSプロジェクトを
28 * 免責すること.
29 *
30 * 本ソフトウェアは,無保証で提供されているものである.上記著作権者お
31 * よびTOPPERSプロジェクトは,本ソフトウェアに関して,特定の使用目的
32 * に対する適合性も含めて,いかなる保証も行わない.また,本ソフトウェ
33 * アの利用により直接的または間接的に生じたいかなる損害に関しても,そ
34 * の責任を負わない.
35 *
36 * @(#) $Id$
37 */
38/**
39 ******************************************************************************
40 * @attention
41 *
42 * <h2><center>&copy; COPYRIGHT(c) 2016 STMicroelectronics</center></h2>
43 *
44 * Redistribution and use in source and binary forms, with or without modification,
45 * are permitted provided that the following conditions are met:
46 * 1. Redistributions of source code must retain the above copyright notice,
47 * this list of conditions and the following disclaimer.
48 * 2. Redistributions in binary form must reproduce the above copyright notice,
49 * this list of conditions and the following disclaimer in the documentation
50 * and/or other materials provided with the distribution.
51 * 3. Neither the name of STMicroelectronics nor the names of its contributors
52 * may be used to endorse or promote products derived from this software
53 * without specific prior written permission.
54 *
55 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
56 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
57 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
58 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
59 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
60 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
61 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
62 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
63 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
64 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
65 *
66 ******************************************************************************
67 */
68
69#include "staudio_wm8994.h"
70#include <sil.h>
71#include <target_syssvc.h>
72#include <stdlib.h>
73
74/*
75 * SIL関数のマクロ定義
76 */
77#define sil_orw_mem(a, b) sil_wrw_mem((a), sil_rew_mem(a) | (b))
78#define sil_andw_mem(a, b) sil_wrw_mem((a), sil_rew_mem(a) & ~(b))
79#define sil_modw_mem(a, b, c) sil_wrw_mem((a), (sil_rew_mem(a) & (~b)) | (c))
80
81/* Uncomment this line to enable verifying data sent to codec after each write
82 operation (for debug purpose) */
83#if !defined (VERIFY_WRITTENDATA)
84/* #define VERIFY_WRITTENDATA */
85#endif /* VERIFY_WRITTENDATA */
86
87typedef struct
88{
89 uint16_t *pRecBuf; /* Pointer to record user buffer */
90 uint32_t RecSize; /* Size to record in mono, double size to record in stereo */
91}AUDIOIN_TypeDef;
92
93#define AUDIO_FREQUENCY_192K ((uint32_t)192000)
94#define AUDIO_FREQUENCY_96K ((uint32_t)96000)
95#define AUDIO_FREQUENCY_48K ((uint32_t)48000)
96#define AUDIO_FREQUENCY_44K ((uint32_t)44100)
97#define AUDIO_FREQUENCY_32K ((uint32_t)32000)
98#define AUDIO_FREQUENCY_22K ((uint32_t)22050)
99#define AUDIO_FREQUENCY_16K ((uint32_t)16000)
100#define AUDIO_FREQUENCY_11K ((uint32_t)11025)
101#define AUDIO_FREQUENCY_8K ((uint32_t)8000)
102
103/*### RECORD ###*/
104#define DFSDM_OVER_SAMPLING(__FREQUENCY__) \
105 (__FREQUENCY__ == AUDIO_FREQUENCY_8K) ? 256 \
106 : (__FREQUENCY__ == AUDIO_FREQUENCY_11K) ? 256 \
107 : (__FREQUENCY__ == AUDIO_FREQUENCY_16K) ? 128 \
108 : (__FREQUENCY__ == AUDIO_FREQUENCY_22K) ? 128 \
109 : (__FREQUENCY__ == AUDIO_FREQUENCY_32K) ? 64 \
110 : (__FREQUENCY__ == AUDIO_FREQUENCY_44K) ? 64 \
111 : (__FREQUENCY__ == AUDIO_FREQUENCY_48K) ? 40 : 20 \
112
113#define DFSDM_CLOCK_DIVIDER(__FREQUENCY__) \
114 (__FREQUENCY__ == AUDIO_FREQUENCY_8K) ? 24 \
115 : (__FREQUENCY__ == AUDIO_FREQUENCY_11K) ? 4 \
116 : (__FREQUENCY__ == AUDIO_FREQUENCY_16K) ? 24 \
117 : (__FREQUENCY__ == AUDIO_FREQUENCY_22K) ? 4 \
118 : (__FREQUENCY__ == AUDIO_FREQUENCY_32K) ? 24 \
119 : (__FREQUENCY__ == AUDIO_FREQUENCY_44K) ? 4 \
120 : (__FREQUENCY__ == AUDIO_FREQUENCY_48K) ? 25 : 25 \
121
122#define DFSDM_FILTER_ORDER(__FREQUENCY__) \
123 (__FREQUENCY__ == AUDIO_FREQUENCY_8K) ? DFSDM_FILTER_SINC3_ORDER \
124 : (__FREQUENCY__ == AUDIO_FREQUENCY_11K) ? DFSDM_FILTER_SINC3_ORDER \
125 : (__FREQUENCY__ == AUDIO_FREQUENCY_16K) ? DFSDM_FILTER_SINC3_ORDER \
126 : (__FREQUENCY__ == AUDIO_FREQUENCY_22K) ? DFSDM_FILTER_SINC3_ORDER \
127 : (__FREQUENCY__ == AUDIO_FREQUENCY_32K) ? DFSDM_FILTER_SINC4_ORDER \
128 : (__FREQUENCY__ == AUDIO_FREQUENCY_44K) ? DFSDM_FILTER_SINC3_ORDER \
129 : (__FREQUENCY__ == AUDIO_FREQUENCY_48K) ? DFSDM_FILTER_SINC3_ORDER : DFSDM_FILTER_SINC5_ORDER \
130
131#define DFSDM_RIGHT_BIT_SHIFT(__FREQUENCY__) \
132 (__FREQUENCY__ == AUDIO_FREQUENCY_8K) ? 8 \
133 : (__FREQUENCY__ == AUDIO_FREQUENCY_11K) ? 8 \
134 : (__FREQUENCY__ == AUDIO_FREQUENCY_16K) ? 3 \
135 : (__FREQUENCY__ == AUDIO_FREQUENCY_22K) ? 4 \
136 : (__FREQUENCY__ == AUDIO_FREQUENCY_32K) ? 7 \
137 : (__FREQUENCY__ == AUDIO_FREQUENCY_44K) ? 0 \
138 : (__FREQUENCY__ == AUDIO_FREQUENCY_48K) ? 0 : 4 \
139
140/* Saturate the record PCM sample */
141#define SaturaLH(N, L, H) (((N)<(L))?(L):(((N)>(H))?(H):(N)))
142
143
144#ifdef TOPPERS_STM32F769_DISCOVERY
145
146#define GPIO_AF3_DFSDM1 ((uint8_t)0x03U) /* DFSDM1 Alternate Function mapping */
147
148#define AUDIO_DFSDMx_DMIC_DATIN_GPIO_CLK_ENABLE() sil_orw_mem((uint32_t *)(TADR_RCC_BASE+TOFF_RCC_AHB1ENR), RCC_AHB1ENR_GPIOCEN)
149#define AUDIO_DFSDMx_CKOUT_DMIC_GPIO_CLK_ENABLE() sil_orw_mem((uint32_t *)(TADR_RCC_BASE+TOFF_RCC_AHB1ENR), RCC_AHB1ENR_GPIODEN)
150
151#define AUDIO_DFSDMx_TOP_RIGHT_CHANNEL DFSDM_CHANNEL_0
152#define AUDIO_DFSDMx_TOP_LEFT_CHANNEL DFSDM_CHANNEL_1
153#define AUDIO_DFSDMx_BUTTOM_RIGHT_CHANNEL DFSDM_CHANNEL_4
154#define AUDIO_DFSDMx_BUTTOM_LEFT_CHANNEL DFSDM_CHANNEL_5
155
156#define AUDIO_DFSDMx_TOP_LEFT_FILTER TADR_DFSDM1_FILTER0_BASE
157#define AUDIO_DFSDMx_TOP_RIGHT_FILTER TADR_DFSDM1_FILTER1_BASE
158#define AUDIO_DFSDMx_BUTTOM_LEFT_FILTER TADR_DFSDM1_FILTER2_BASE
159#define AUDIO_DFSDMx_BUTTOM_RIGHT_FILTER TADR_DFSDM1_FILTER3_BASE
160
161#define AUDIO_DFSDMx_CKOUT_DMIC_GPIO_PORT TADR_GPIOD_BASE
162#define AUDIO_DFSDMx_CKOUT_PINNO 3
163#define AUDIO_DFSDMx_DMIC_DATIN_GPIO_PORT TADR_GPIOC_BASE
164#define AUDIO_DFSDMx_DMIC_DATIN1_PINNO 3
165#define AUDIO_DFSDMx_DMIC_DATIN5_PINNO 11
166#define AUDIO_DFSDMx_DMIC_DATIN_AF GPIO_AF3_DFSDM1
167#define AUDIO_DFSDMx_CKOUT_AF GPIO_AF3_DFSDM1
168
169#define AUDIO_DFSDMx_DMAx_BUTTOM_LEFT_STREAM TADR_DMA2_STM6_BASE
170#define AUDIO_DFSDMx_DMAx_BUTTOM_RIGHT_STREAM TADR_DMA2_STM7_BASE
171
172#define AUDIO_DFSDMx_DMAx_PERIPH_DATA_SIZE DMA_PDATAALIGN_WORD
173#define AUDIO_DFSDMx_DMAx_MEM_DATA_SIZE DMA_MDATAALIGN_WORD
174
175#define AUDIO_DFSDMx_DMAx_CHANNEL DMA_CHANNEL_8
176
177
178/* RECORD */
179static STAUDIO_Handle_t *hstaudio;
180AUDIOIN_TypeDef hAudioIn;
181
182DFSDM_Channel_Handle_t hAudioInTopLeftChannel;
183DFSDM_Channel_Handle_t hAudioInTopRightChannel;
184DFSDM_Filter_Handle_t hAudioInTopLeftFilter;
185DFSDM_Filter_Handle_t hAudioInTopRightFilter;
186DMA_Handle_t hDmaTopLeft;
187DMA_Handle_t hDmaTopRight;
188
189DFSDM_Channel_Handle_t hAudioInButtomLeftChannel;
190DFSDM_Channel_Handle_t hAudioInButtomRightChannel;
191DFSDM_Filter_Handle_t hAudioInButtomLeftFilter;
192DFSDM_Filter_Handle_t hAudioInButtomRightFilter;
193DMA_Handle_t hDmaButtomLeft;
194DMA_Handle_t hDmaButtomRight;
195
196/* Buffers for right and left samples */
197static int32_t *pScratchBuff[2*DEFAULT_AUDIO_IN_CHANNEL_NBR];
198static volatile int32_t ScratchSize;
199/* Cannel number to be used: 2 channels by default */
200static uint8_t AudioIn_ChannelNumber = DEFAULT_AUDIO_IN_CHANNEL_NBR;
201
202/* Buffers status flags */
203static uint32_t DmaTopLeftRecHalfCplt = 0;
204static uint32_t DmaTopLeftRecCplt = 0;
205static uint32_t DmaTopRightRecHalfCplt = 0;
206static uint32_t DmaTopRightRecCplt = 0;
207static uint32_t DmaButtomLeftRecHalfCplt = 0;
208static uint32_t DmaButtomLeftRecCplt = 0;
209static uint32_t DmaButtomRightRecHalfCplt = 0;
210static uint32_t DmaButtomRightRecCplt = 0;
211
212/* Application Buffer Trigger */
213static volatile uint32_t AppBuffTrigger = 0;
214static volatile uint32_t AppBuffHalf = 0;
215#endif
216
217
218/** @defgroup WM8994_Function_Prototypes
219 * @{
220 */
221static uint32_t wm8994_SetVolume(STAUDIO_Handle_t *haudio, uint8_t Volume);
222static uint32_t wm8994_SetMute(STAUDIO_Handle_t *haudio, uint32_t Cmd);
223
224
225/**
226 * @brief Writes/Read a single data.
227 * @param Addr: I2C address
228 * @param Reg: Reg address
229 * @param Value: Data to be written
230 * @retval None
231 */
232static uint8_t
233CODEC_IO_Write(STAUDIO_Handle_t *haudio, uint16_t Reg, uint16_t Value)
234{
235 ER ercd;
236 uint8_t buffer[4];
237 uint32_t result = 0;
238
239 buffer[0] = (uint8_t)(Value >> 8);
240 buffer[1] = (uint8_t)Value;
241 ercd = i2c_memwrite(haudio->hi2c, haudio->i2caddress, (uint16_t)Reg, I2C_MEMADD_SIZE_16BIT, buffer, 2, 1000);
242
243 /* Check the communication status */
244 if(ercd != E_OK){
245#if 1 /* ROI DEBUG */
246 syslog_2(LOG_NOTICE, "## I2Cx_Error(%08x, %02x) ##", haudio->hi2c, haudio->i2caddress);
247#endif /* ROI DEBUG */
248 /* De-initialize the I2C communication bus */
249 i2c_deinit(haudio->hi2c);
250
251 /* Re-Initialize the I2C communication bus */
252 i2c_init(haudio->hi2c->i2cid, &haudio->hi2c->Init);
253 }
254
255#ifdef VERIFY_WRITTENDATA
256 {
257 uint16_t value;
258 ercd = i2c_memread(haudio->hi2c, haudio->i2caddress, (uint16_t)Reg, I2C_MEMADD_SIZE_16BIT, buffer, 2, 1000);
259 value = (buffer[0] << 8) | buffer[1];
260 /* Verify that the data has been correctly written */
261 result = (value == Value)? 0:1;
262 }
263#endif /* VERIFY_WRITTENDATA */
264 return result;
265}
266
267/**
268 * @brief Initializes the audio codec and the control interface.
269 * @param DeviceAddr: Device address on communication Bus.
270 * @param OutputInputDevice: can be OUTPUT_DEVICE_SPEAKER, OUTPUT_DEVICE_HEADPHONE,
271 * OUTPUT_DEVICE_BOTH, OUTPUT_DEVICE_AUTO, INPUT_DEVICE_DIGITAL_MICROPHONE_1,
272 * INPUT_DEVICE_DIGITAL_MICROPHONE_2, INPUT_DEVICE_DIGITAL_MIC1_MIC2,
273 * INPUT_DEVICE_INPUT_LINE_1 or INPUT_DEVICE_INPUT_LINE_2.
274 * @param Volume: Initial volume level (from 0 (Mute) to 100 (Max))
275 * @param AudioFreq: Audio Frequency
276 * @retval 0 if correct communication, else wrong communication
277 */
278static uint32_t
279wm8994_Init(STAUDIO_Handle_t *haudio, uint16_t OutputInputDevice, uint8_t Volume, uint32_t AudioFreq)
280{
281 uint32_t counter = 0;
282 uint16_t output_device = OutputInputDevice & 0xFF;
283 uint16_t input_device = OutputInputDevice & 0xFF00;
284 uint16_t power_mgnt_reg_1 = 0;
285
286 /* wm8994 Errata Work-Arounds */
287 counter += CODEC_IO_Write(haudio, 0x102, 0x0003);
288 counter += CODEC_IO_Write(haudio, 0x817, 0x0000);
289 counter += CODEC_IO_Write(haudio, 0x102, 0x0000);
290
291 /* Enable VMID soft start (fast), Start-up Bias Current Enabled */
292 counter += CODEC_IO_Write(haudio, 0x39, 0x006C);
293
294 /* Enable bias generator, Enable VMID */
295 if(input_device > 0){
296 counter += CODEC_IO_Write(haudio, 0x01, 0x0013);
297 }
298 else{
299 counter += CODEC_IO_Write(haudio, 0x01, 0x0003);
300 }
301
302 /* Add Delay */
303 dly_tsk(50);
304
305 /* Path Configurations for output */
306 if(output_device > 0){
307 haudio->outputEnabled = 1;
308
309 switch(output_device){
310 case OUTPUT_DEVICE_SPEAKER:
311 /* Enable DAC1 (Left), Enable DAC1 (Right),
312 Disable DAC2 (Left), Disable DAC2 (Right)*/
313 counter += CODEC_IO_Write(haudio, 0x05, 0x0C0C);
314
315 /* Enable the AIF1 Timeslot 0 (Left) to DAC 1 (Left) mixer path */
316 counter += CODEC_IO_Write(haudio, 0x601, 0x0000);
317
318 /* Enable the AIF1 Timeslot 0 (Right) to DAC 1 (Right) mixer path */
319 counter += CODEC_IO_Write(haudio, 0x602, 0x0000);
320
321 /* Disable the AIF1 Timeslot 1 (Left) to DAC 2 (Left) mixer path */
322 counter += CODEC_IO_Write(haudio, 0x604, 0x0002);
323
324 /* Disable the AIF1 Timeslot 1 (Right) to DAC 2 (Right) mixer path */
325 counter += CODEC_IO_Write(haudio, 0x605, 0x0002);
326 break;
327
328 case OUTPUT_DEVICE_HEADPHONE:
329 /* Disable DAC1 (Left), Disable DAC1 (Right),
330 Enable DAC2 (Left), Enable DAC2 (Right)*/
331 counter += CODEC_IO_Write(haudio, 0x05, 0x0303);
332
333 /* Enable the AIF1 Timeslot 0 (Left) to DAC 1 (Left) mixer path */
334 counter += CODEC_IO_Write(haudio, 0x601, 0x0001);
335
336 /* Enable the AIF1 Timeslot 0 (Right) to DAC 1 (Right) mixer path */
337 counter += CODEC_IO_Write(haudio, 0x602, 0x0001);
338
339 /* Disable the AIF1 Timeslot 1 (Left) to DAC 2 (Left) mixer path */
340 counter += CODEC_IO_Write(haudio, 0x604, 0x0000);
341
342 /* Disable the AIF1 Timeslot 1 (Right) to DAC 2 (Right) mixer path */
343 counter += CODEC_IO_Write(haudio, 0x605, 0x0000);
344 break;
345
346 case OUTPUT_DEVICE_BOTH:
347 if(input_device == INPUT_DEVICE_DIGITAL_MIC1_MIC2){
348 /* Enable DAC1 (Left), Enable DAC1 (Right),
349 also Enable DAC2 (Left), Enable DAC2 (Right)*/
350 counter += CODEC_IO_Write(haudio, 0x05, 0x0303 | 0x0C0C);
351
352 /* Enable the AIF1 Timeslot 0 (Left) to DAC 1 (Left) mixer path
353 Enable the AIF1 Timeslot 1 (Left) to DAC 1 (Left) mixer path */
354 counter += CODEC_IO_Write(haudio, 0x601, 0x0003);
355
356 /* Enable the AIF1 Timeslot 0 (Right) to DAC 1 (Right) mixer path
357 Enable the AIF1 Timeslot 1 (Right) to DAC 1 (Right) mixer path */
358 counter += CODEC_IO_Write(haudio, 0x602, 0x0003);
359
360 /* Enable the AIF1 Timeslot 0 (Left) to DAC 2 (Left) mixer path
361 Enable the AIF1 Timeslot 1 (Left) to DAC 2 (Left) mixer path */
362 counter += CODEC_IO_Write(haudio, 0x604, 0x0003);
363
364 /* Enable the AIF1 Timeslot 0 (Right) to DAC 2 (Right) mixer path
365 Enable the AIF1 Timeslot 1 (Right) to DAC 2 (Right) mixer path */
366 counter += CODEC_IO_Write(haudio, 0x605, 0x0003);
367 }
368 else{
369 /* Enable DAC1 (Left), Enable DAC1 (Right),
370 also Enable DAC2 (Left), Enable DAC2 (Right)*/
371 counter += CODEC_IO_Write(haudio, 0x05, 0x0303 | 0x0C0C);
372
373 /* Enable the AIF1 Timeslot 0 (Left) to DAC 1 (Left) mixer path */
374 counter += CODEC_IO_Write(haudio, 0x601, 0x0001);
375
376 /* Enable the AIF1 Timeslot 0 (Right) to DAC 1 (Right) mixer path */
377 counter += CODEC_IO_Write(haudio, 0x602, 0x0001);
378
379 /* Enable the AIF1 Timeslot 1 (Left) to DAC 2 (Left) mixer path */
380 counter += CODEC_IO_Write(haudio, 0x604, 0x0002);
381
382 /* Enable the AIF1 Timeslot 1 (Right) to DAC 2 (Right) mixer path */
383 counter += CODEC_IO_Write(haudio, 0x605, 0x0002);
384 }
385 break;
386
387 case OUTPUT_DEVICE_AUTO :
388 default:
389 /* Disable DAC1 (Left), Disable DAC1 (Right),
390 Enable DAC2 (Left), Enable DAC2 (Right)*/
391 counter += CODEC_IO_Write(haudio, 0x05, 0x0303);
392
393 /* Enable the AIF1 Timeslot 0 (Left) to DAC 1 (Left) mixer path */
394 counter += CODEC_IO_Write(haudio, 0x601, 0x0001);
395
396 /* Enable the AIF1 Timeslot 0 (Right) to DAC 1 (Right) mixer path */
397 counter += CODEC_IO_Write(haudio, 0x602, 0x0001);
398
399 /* Disable the AIF1 Timeslot 1 (Left) to DAC 2 (Left) mixer path */
400 counter += CODEC_IO_Write(haudio, 0x604, 0x0000);
401
402 /* Disable the AIF1 Timeslot 1 (Right) to DAC 2 (Right) mixer path */
403 counter += CODEC_IO_Write(haudio, 0x605, 0x0000);
404 break;
405 }
406 }
407 else{
408 haudio->outputEnabled = 0;
409 }
410
411 /* Path Configurations for input */
412 if(input_device > 0){
413 haudio->inputEnabled = 1;
414 switch(input_device){
415 case INPUT_DEVICE_DIGITAL_MICROPHONE_2 :
416 /* Enable AIF1ADC2 (Left), Enable AIF1ADC2 (Right)
417 * Enable DMICDAT2 (Left), Enable DMICDAT2 (Right)
418 * Enable Left ADC, Enable Right ADC */
419 counter += CODEC_IO_Write(haudio, 0x04, 0x0C30);
420
421 /* Enable AIF1 DRC2 Signal Detect & DRC in AIF1ADC2 Left/Right Timeslot 1 */
422 counter += CODEC_IO_Write(haudio, 0x450, 0x00DB);
423
424 /* Disable IN1L, IN1R, IN2L, IN2R, Enable Thermal sensor & shutdown */
425 counter += CODEC_IO_Write(haudio, 0x02, 0x6000);
426
427 /* Enable the DMIC2(Left) to AIF1 Timeslot 1 (Left) mixer path */
428 counter += CODEC_IO_Write(haudio, 0x608, 0x0002);
429
430 /* Enable the DMIC2(Right) to AIF1 Timeslot 1 (Right) mixer path */
431 counter += CODEC_IO_Write(haudio, 0x609, 0x0002);
432
433 /* GPIO1 pin configuration GP1_DIR = output, GP1_FN = AIF1 DRC2 signal detect */
434 counter += CODEC_IO_Write(haudio, 0x700, 0x000E);
435 break;
436
437 case INPUT_DEVICE_INPUT_LINE_1 :
438 /* IN1LN_TO_IN1L, IN1LP_TO_VMID, IN1RN_TO_IN1R, IN1RP_TO_VMID */
439 counter += CODEC_IO_Write(haudio, 0x28, 0x0011);
440
441 /* Disable mute on IN1L_TO_MIXINL and +30dB on IN1L PGA output */
442 counter += CODEC_IO_Write(haudio, 0x29, 0x0035);
443
444 /* Disable mute on IN1R_TO_MIXINL, Gain = +30dB */
445 counter += CODEC_IO_Write(haudio, 0x2A, 0x0035);
446
447 /* Enable AIF1ADC1 (Left), Enable AIF1ADC1 (Right)
448 * Enable Left ADC, Enable Right ADC */
449 counter += CODEC_IO_Write(haudio, 0x04, 0x0303);
450
451 /* Enable AIF1 DRC1 Signal Detect & DRC in AIF1ADC1 Left/Right Timeslot 0 */
452 counter += CODEC_IO_Write(haudio, 0x440, 0x00DB);
453
454 /* Enable IN1L and IN1R, Disable IN2L and IN2R, Enable Thermal sensor & shutdown */
455 counter += CODEC_IO_Write(haudio, 0x02, 0x6350);
456
457 /* Enable the ADCL(Left) to AIF1 Timeslot 0 (Left) mixer path */
458 counter += CODEC_IO_Write(haudio, 0x606, 0x0002);
459
460 /* Enable the ADCR(Right) to AIF1 Timeslot 0 (Right) mixer path */
461 counter += CODEC_IO_Write(haudio, 0x607, 0x0002);
462
463 /* GPIO1 pin configuration GP1_DIR = output, GP1_FN = AIF1 DRC1 signal detect */
464 counter += CODEC_IO_Write(haudio, 0x700, 0x000D);
465 break;
466
467 case INPUT_DEVICE_DIGITAL_MICROPHONE_1 :
468 /* Enable AIF1ADC1 (Left), Enable AIF1ADC1 (Right)
469 * Enable DMICDAT1 (Left), Enable DMICDAT1 (Right)
470 * Enable Left ADC, Enable Right ADC */
471 counter += CODEC_IO_Write(haudio, 0x04, 0x030C);
472
473 /* Enable AIF1 DRC2 Signal Detect & DRC in AIF1ADC1 Left/Right Timeslot 0 */
474 counter += CODEC_IO_Write(haudio, 0x440, 0x00DB);
475
476 /* Disable IN1L, IN1R, IN2L, IN2R, Enable Thermal sensor & shutdown */
477 counter += CODEC_IO_Write(haudio, 0x02, 0x6350);
478
479 /* Enable the DMIC2(Left) to AIF1 Timeslot 0 (Left) mixer path */
480 counter += CODEC_IO_Write(haudio, 0x606, 0x0002);
481
482 /* Enable the DMIC2(Right) to AIF1 Timeslot 0 (Right) mixer path */
483 counter += CODEC_IO_Write(haudio, 0x607, 0x0002);
484
485 /* GPIO1 pin configuration GP1_DIR = output, GP1_FN = AIF1 DRC1 signal detect */
486 counter += CODEC_IO_Write(haudio, 0x700, 0x000D);
487 break;
488 case INPUT_DEVICE_DIGITAL_MIC1_MIC2 :
489 /* Enable AIF1ADC1 (Left), Enable AIF1ADC1 (Right)
490 * Enable DMICDAT1 (Left), Enable DMICDAT1 (Right)
491 * Enable Left ADC, Enable Right ADC */
492 counter += CODEC_IO_Write(haudio, 0x04, 0x0F3C);
493
494 /* Enable AIF1 DRC2 Signal Detect & DRC in AIF1ADC2 Left/Right Timeslot 1 */
495 counter += CODEC_IO_Write(haudio, 0x450, 0x00DB);
496
497 /* Enable AIF1 DRC2 Signal Detect & DRC in AIF1ADC1 Left/Right Timeslot 0 */
498 counter += CODEC_IO_Write(haudio, 0x440, 0x00DB);
499
500 /* Disable IN1L, IN1R, Enable IN2L, IN2R, Thermal sensor & shutdown */
501 counter += CODEC_IO_Write(haudio, 0x02, 0x63A0);
502
503 /* Enable the DMIC2(Left) to AIF1 Timeslot 0 (Left) mixer path */
504 counter += CODEC_IO_Write(haudio, 0x606, 0x0002);
505
506 /* Enable the DMIC2(Right) to AIF1 Timeslot 0 (Right) mixer path */
507 counter += CODEC_IO_Write(haudio, 0x607, 0x0002);
508
509 /* Enable the DMIC2(Left) to AIF1 Timeslot 1 (Left) mixer path */
510 counter += CODEC_IO_Write(haudio, 0x608, 0x0002);
511
512 /* Enable the DMIC2(Right) to AIF1 Timeslot 1 (Right) mixer path */
513 counter += CODEC_IO_Write(haudio, 0x609, 0x0002);
514
515 /* GPIO1 pin configuration GP1_DIR = output, GP1_FN = AIF1 DRC1 signal detect */
516 counter += CODEC_IO_Write(haudio, 0x700, 0x000D);
517 break;
518 case INPUT_DEVICE_INPUT_LINE_2 :
519 default:
520 /* Actually, no other input devices supported */
521 counter++;
522 break;
523 }
524 }
525 else{
526 haudio->inputEnabled = 0;
527 }
528
529 /* Clock Configurations */
530 switch (AudioFreq){
531 case AUDIO_FREQUENCY_8K:
532 /* AIF1 Sample Rate = 8 (KHz), ratio=256 */
533 counter += CODEC_IO_Write(haudio, 0x210, 0x0003);
534 break;
535
536 case AUDIO_FREQUENCY_16K:
537 /* AIF1 Sample Rate = 16 (KHz), ratio=256 */
538 counter += CODEC_IO_Write(haudio, 0x210, 0x0033);
539 break;
540
541 case AUDIO_FREQUENCY_32K:
542 /* AIF1 Sample Rate = 32 (KHz), ratio=256 */
543 counter += CODEC_IO_Write(haudio, 0x210, 0x0063);
544 break;
545
546 case AUDIO_FREQUENCY_48K:
547 /* AIF1 Sample Rate = 48 (KHz), ratio=256 */
548 counter += CODEC_IO_Write(haudio, 0x210, 0x0083);
549 break;
550
551 case AUDIO_FREQUENCY_96K:
552 /* AIF1 Sample Rate = 96 (KHz), ratio=256 */
553 counter += CODEC_IO_Write(haudio, 0x210, 0x00A3);
554 break;
555
556 case AUDIO_FREQUENCY_11K:
557 /* AIF1 Sample Rate = 11.025 (KHz), ratio=256 */
558 counter += CODEC_IO_Write(haudio, 0x210, 0x0013);
559 break;
560
561 case AUDIO_FREQUENCY_22K:
562 /* AIF1 Sample Rate = 22.050 (KHz), ratio=256 */
563 counter += CODEC_IO_Write(haudio, 0x210, 0x0043);
564 break;
565
566 case AUDIO_FREQUENCY_44K:
567 /* AIF1 Sample Rate = 44.1 (KHz), ratio=256 */
568 counter += CODEC_IO_Write(haudio, 0x210, 0x0073);
569 break;
570
571 default:
572 /* AIF1 Sample Rate = 48 (KHz), ratio=256 */
573 counter += CODEC_IO_Write(haudio, 0x210, 0x0083);
574 break;
575 }
576
577 if(input_device == INPUT_DEVICE_DIGITAL_MIC1_MIC2){
578 /* AIF1 Word Length = 16-bits, AIF1 Format = DSP mode */
579 counter += CODEC_IO_Write(haudio, 0x300, 0x4018);
580 }
581 else{
582 /* AIF1 Word Length = 16-bits, AIF1 Format = I2S (Default Register Value) */
583 counter += CODEC_IO_Write(haudio, 0x300, 0x4010);
584 }
585
586 /* slave mode */
587 counter += CODEC_IO_Write(haudio, 0x302, 0x0000);
588
589 /* Enable the DSP processing clock for AIF1, Enable the core clock */
590 counter += CODEC_IO_Write(haudio, 0x208, 0x000A);
591
592 /* Enable AIF1 Clock, AIF1 Clock Source = MCLK1 pin */
593 counter += CODEC_IO_Write(haudio, 0x200, 0x0001);
594
595 if(output_device > 0){ /* Audio output selected */
596 if(output_device == OUTPUT_DEVICE_HEADPHONE){
597 /* Select DAC1 (Left) to Left Headphone Output PGA (HPOUT1LVOL) path */
598 counter += CODEC_IO_Write(haudio, 0x2D, 0x0100);
599
600 /* Select DAC1 (Right) to Right Headphone Output PGA (HPOUT1RVOL) path */
601 counter += CODEC_IO_Write(haudio, 0x2E, 0x0100);
602
603 /* Startup sequence for Headphone */
604 if(haudio->ColdStartup){
605 counter += CODEC_IO_Write(haudio,0x110,0x8100);
606
607 haudio->ColdStartup = 0;
608 /* Add Delay */
609 dly_tsk(300);
610 }
611 else{ /* Headphone Warm Start-Up */
612 counter += CODEC_IO_Write(haudio,0x110,0x8108);
613 /* Add Delay */
614 dly_tsk(50);
615 }
616
617 /* Soft un-Mute the AIF1 Timeslot 0 DAC1 path L&R */
618 counter += CODEC_IO_Write(haudio, 0x420, 0x0000);
619 }
620 /* Analog Output Configuration */
621
622 /* Enable SPKRVOL PGA, Enable SPKMIXR, Enable SPKLVOL PGA, Enable SPKMIXL */
623 counter += CODEC_IO_Write(haudio, 0x03, 0x0300);
624
625 /* Left Speaker Mixer Volume = 0dB */
626 counter += CODEC_IO_Write(haudio, 0x22, 0x0000);
627
628 /* Speaker output mode = Class D, Right Speaker Mixer Volume = 0dB ((0x23, 0x0100) = class AB)*/
629 counter += CODEC_IO_Write(haudio, 0x23, 0x0000);
630
631 /* Unmute DAC2 (Left) to Left Speaker Mixer (SPKMIXL) path,
632 Unmute DAC2 (Right) to Right Speaker Mixer (SPKMIXR) path */
633 counter += CODEC_IO_Write(haudio, 0x36, 0x0300);
634
635 /* Enable bias generator, Enable VMID, Enable SPKOUTL, Enable SPKOUTR */
636 counter += CODEC_IO_Write(haudio, 0x01, 0x3003);
637
638 /* Headphone/Speaker Enable */
639 if(input_device == INPUT_DEVICE_DIGITAL_MIC1_MIC2){
640 /* Enable Class W, Class W Envelope Tracking = AIF1 Timeslots 0 and 1 */
641 counter += CODEC_IO_Write(haudio, 0x51, 0x0205);
642 }
643 else{
644 /* Enable Class W, Class W Envelope Tracking = AIF1 Timeslot 0 */
645 counter += CODEC_IO_Write(haudio, 0x51, 0x0005);
646 }
647
648 /* Enable bias generator, Enable VMID, Enable HPOUT1 (Left) and Enable HPOUT1 (Right) input stages */
649 /* idem for Speaker */
650 power_mgnt_reg_1 |= 0x0303 | 0x3003;
651 counter += CODEC_IO_Write(haudio, 0x01, power_mgnt_reg_1);
652
653 /* Enable HPOUT1 (Left) and HPOUT1 (Right) intermediate stages */
654 counter += CODEC_IO_Write(haudio, 0x60, 0x0022);
655
656 /* Enable Charge Pump */
657 counter += CODEC_IO_Write(haudio, 0x4C, 0x9F25);
658
659 /* Add Delay */
660 dly_tsk(15);
661
662 /* Select DAC1 (Left) to Left Headphone Output PGA (HPOUT1LVOL) path */
663 counter += CODEC_IO_Write(haudio, 0x2D, 0x0001);
664
665 /* Select DAC1 (Right) to Right Headphone Output PGA (HPOUT1RVOL) path */
666 counter += CODEC_IO_Write(haudio, 0x2E, 0x0001);
667
668 /* Enable Left Output Mixer (MIXOUTL), Enable Right Output Mixer (MIXOUTR) */
669 /* idem for SPKOUTL and SPKOUTR */
670 counter += CODEC_IO_Write(haudio, 0x03, 0x0030 | 0x0300);
671
672 /* Enable DC Servo and trigger start-up mode on left and right channels */
673 counter += CODEC_IO_Write(haudio, 0x54, 0x0033);
674
675 /* Add Delay */
676 dly_tsk(257);
677
678 /* Enable HPOUT1 (Left) and HPOUT1 (Right) intermediate and output stages. Remove clamps */
679 counter += CODEC_IO_Write(haudio, 0x60, 0x00EE);
680
681 /* Unmutes */
682
683 /* Unmute DAC 1 (Left) */
684 counter += CODEC_IO_Write(haudio, 0x610, 0x00C0);
685
686 /* Unmute DAC 1 (Right) */
687 counter += CODEC_IO_Write(haudio, 0x611, 0x00C0);
688
689 /* Unmute the AIF1 Timeslot 0 DAC path */
690 counter += CODEC_IO_Write(haudio, 0x420, 0x0010);
691
692 /* Unmute DAC 2 (Left) */
693 counter += CODEC_IO_Write(haudio, 0x612, 0x00C0);
694
695 /* Unmute DAC 2 (Right) */
696 counter += CODEC_IO_Write(haudio, 0x613, 0x00C0);
697
698 /* Unmute the AIF1 Timeslot 1 DAC2 path */
699 counter += CODEC_IO_Write(haudio, 0x422, 0x0010);
700
701 /* Volume Control */
702 wm8994_SetVolume(haudio, Volume);
703 }
704
705 if(input_device > 0){ /* Audio input selected */
706 if((input_device == INPUT_DEVICE_DIGITAL_MICROPHONE_1) || (input_device == INPUT_DEVICE_DIGITAL_MICROPHONE_2)){
707 /* Enable Microphone bias 1 generator, Enable VMID */
708 power_mgnt_reg_1 |= 0x0013;
709 counter += CODEC_IO_Write(haudio, 0x01, power_mgnt_reg_1);
710
711 /* ADC oversample enable */
712 counter += CODEC_IO_Write(haudio, 0x620, 0x0002);
713
714 /* AIF ADC2 HPF enable, HPF cut = voice mode 1 fc=127Hz at fs=8kHz */
715 counter += CODEC_IO_Write(haudio, 0x411, 0x3800);
716 }
717 else if(input_device == INPUT_DEVICE_DIGITAL_MIC1_MIC2){
718 /* Enable Microphone bias 1 generator, Enable VMID */
719 power_mgnt_reg_1 |= 0x0013;
720 counter += CODEC_IO_Write(haudio, 0x01, power_mgnt_reg_1);
721
722 /* ADC oversample enable */
723 counter += CODEC_IO_Write(haudio, 0x620, 0x0002);
724
725 /* AIF ADC1 HPF enable, HPF cut = voice mode 1 fc=127Hz at fs=8kHz */
726 counter += CODEC_IO_Write(haudio, 0x410, 0x1800);
727
728 /* AIF ADC2 HPF enable, HPF cut = voice mode 1 fc=127Hz at fs=8kHz */
729 counter += CODEC_IO_Write(haudio, 0x411, 0x1800);
730 }
731 else if((input_device == INPUT_DEVICE_INPUT_LINE_1) || (input_device == INPUT_DEVICE_INPUT_LINE_2)){
732 /* Disable mute on IN1L, IN1L Volume = +0dB */
733 counter += CODEC_IO_Write(haudio, 0x18, 0x000B);
734
735 /* Disable mute on IN1R, IN1R Volume = +0dB */
736 counter += CODEC_IO_Write(haudio, 0x1A, 0x000B);
737
738 /* AIF ADC1 HPF enable, HPF cut = hifi mode fc=4Hz at fs=48kHz */
739 counter += CODEC_IO_Write(haudio, 0x410, 0x1800);
740 }
741 /* Volume Control */
742 wm8994_SetVolume(haudio, Volume);
743 }
744 /* Return communication control value */
745 return counter;
746}
747
748/**
749 * @brief Pauses playing on the audio codec.
750 * @param DeviceAddr: Device address on communication Bus.
751 * @retval 0 if correct communication, else wrong communication
752 */
753static uint32_t
754wm8994_Pause(STAUDIO_Handle_t *haudio)
755{
756 uint32_t counter = 0;
757
758 /* Pause the audio file playing */
759 /* Mute the output first */
760 counter += wm8994_SetMute(haudio, AUDIO_MUTE_ON);
761
762 /* Put the Codec in Power save mode */
763 counter += CODEC_IO_Write(haudio, 0x02, 0x01);
764 return counter;
765}
766
767/**
768 * @brief Stops audio Codec playing. It powers down the codec.
769 * @param DeviceAddr: Device address on communication Bus.
770 * @param CodecPdwnMode: selects the power down mode.
771 * - CODEC_PDWN_SW: only mutes the audio codec. When resuming from this
772 * mode the codec keeps the previous initialization
773 * (no need to re-Initialize the codec registers).
774 * - CODEC_PDWN_HW: Physically power down the codec. When resuming from this
775 * mode, the codec is set to default configuration
776 * (user should re-Initialize the codec in order to
777 * play again the audio stream).
778 * @retval 0 if correct communication, else wrong communication
779 */
780static uint32_t
781wm8994_Stop(STAUDIO_Handle_t *haudio, uint32_t CodecPdwnMode)
782{
783 uint32_t counter = 0;
784
785 if(haudio->outputEnabled != 0){
786 /* Mute the output first */
787 counter += wm8994_SetMute(haudio, AUDIO_MUTE_ON);
788
789 if(CodecPdwnMode == CODEC_PDWN_SW){
790 /* Only output mute required*/
791 }
792 else{ /* CODEC_PDWN_HW */
793 /* Mute the AIF1 Timeslot 0 DAC1 path */
794 counter += CODEC_IO_Write(haudio, 0x420, 0x0200);
795
796 /* Mute the AIF1 Timeslot 1 DAC2 path */
797 counter += CODEC_IO_Write(haudio, 0x422, 0x0200);
798
799 /* Disable DAC1L_TO_HPOUT1L */
800 counter += CODEC_IO_Write(haudio, 0x2D, 0x0000);
801
802 /* Disable DAC1R_TO_HPOUT1R */
803 counter += CODEC_IO_Write(haudio, 0x2E, 0x0000);
804
805 /* Disable DAC1 and DAC2 */
806 counter += CODEC_IO_Write(haudio, 0x05, 0x0000);
807
808 /* Reset Codec by writing in 0x0000 address register */
809 counter += CODEC_IO_Write(haudio, 0x0000, 0x0000);
810 haudio->outputEnabled = 0;
811 }
812 }
813 return counter;
814}
815
816/**
817 * @brief Sets higher or lower the codec volume level.
818 * @param DeviceAddr: Device address on communication Bus.
819 * @param Volume: a byte value from 0 to 255 (refer to codec registers
820 * description for more details).
821 * @retval 0 if correct communication, else wrong communication
822 */
823static uint32_t
824wm8994_SetVolume(STAUDIO_Handle_t *haudio, uint8_t Volume)
825{
826 uint32_t counter = 0;
827 uint8_t convertedvol = VOLUME_CONVERT(Volume);
828
829 /* Output volume */
830 if(haudio->outputEnabled != 0){
831 if(convertedvol > 0x3E){
832 /* Unmute audio codec */
833 counter += wm8994_SetMute(haudio, AUDIO_MUTE_OFF);
834
835 /* Left Headphone Volume */
836 counter += CODEC_IO_Write(haudio, 0x1C, 0x3F | 0x140);
837
838 /* Right Headphone Volume */
839 counter += CODEC_IO_Write(haudio, 0x1D, 0x3F | 0x140);
840
841 /* Left Speaker Volume */
842 counter += CODEC_IO_Write(haudio, 0x26, 0x3F | 0x140);
843
844 /* Right Speaker Volume */
845 counter += CODEC_IO_Write(haudio, 0x27, 0x3F | 0x140);
846 }
847 else if(Volume == 0){
848 /* Mute audio codec */
849 counter += wm8994_SetMute(haudio, AUDIO_MUTE_ON);
850 }
851 else{
852 /* Unmute audio codec */
853 counter += wm8994_SetMute(haudio, AUDIO_MUTE_OFF);
854
855 /* Left Headphone Volume */
856 counter += CODEC_IO_Write(haudio, 0x1C, convertedvol | 0x140);
857
858 /* Right Headphone Volume */
859 counter += CODEC_IO_Write(haudio, 0x1D, convertedvol | 0x140);
860
861 /* Left Speaker Volume */
862 counter += CODEC_IO_Write(haudio, 0x26, convertedvol | 0x140);
863
864 /* Right Speaker Volume */
865 counter += CODEC_IO_Write(haudio, 0x27, convertedvol | 0x140);
866 }
867 }
868
869 /* Input volume */
870 if(haudio->inputEnabled != 0){
871 convertedvol = VOLUME_IN_CONVERT(Volume);
872
873 /* Left AIF1 ADC1 volume */
874 counter += CODEC_IO_Write(haudio, 0x400, convertedvol | 0x100);
875
876 /* Right AIF1 ADC1 volume */
877 counter += CODEC_IO_Write(haudio, 0x401, convertedvol | 0x100);
878
879 /* Left AIF1 ADC2 volume */
880 counter += CODEC_IO_Write(haudio, 0x404, convertedvol | 0x100);
881
882 /* Right AIF1 ADC2 volume */
883 counter += CODEC_IO_Write(haudio, 0x405, convertedvol | 0x100);
884 }
885 return counter;
886}
887
888/**
889 * @brief Enables or disables the mute feature on the audio codec.
890 * @param DeviceAddr: Device address on communication Bus.
891 * @param Cmd: AUDIO_MUTE_ON to enable the mute or AUDIO_MUTE_OFF to disable the
892 * mute mode.
893 * @retval 0 if correct communication, else wrong communication
894 */
895static uint32_t
896wm8994_SetMute(STAUDIO_Handle_t *haudio, uint32_t Cmd)
897{
898 uint32_t counter = 0;
899
900 if(haudio->outputEnabled != 0){
901 /* Set the Mute mode */
902 if(Cmd == AUDIO_MUTE_ON){
903 /* Soft Mute the AIF1 Timeslot 0 DAC1 path L&R */
904 counter += CODEC_IO_Write(haudio, 0x420, 0x0200);
905
906 /* Soft Mute the AIF1 Timeslot 1 DAC2 path L&R */
907 counter += CODEC_IO_Write(haudio, 0x422, 0x0200);
908 }
909 else{ /* AUDIO_MUTE_OFF Disable the Mute */
910 /* Unmute the AIF1 Timeslot 0 DAC1 path L&R */
911 counter += CODEC_IO_Write(haudio, 0x420, 0x0010);
912
913 /* Unmute the AIF1 Timeslot 1 DAC2 path L&R */
914 counter += CODEC_IO_Write(haudio, 0x422, 0x0010);
915 }
916 }
917 return counter;
918}
919
920/**
921 * @brief Switch dynamically (while audio file is played) the output target
922 * (speaker or headphone).
923 * @param DeviceAddr: Device address on communication Bus.
924 * @param Output: specifies the audio output target: OUTPUT_DEVICE_SPEAKER,
925 * OUTPUT_DEVICE_HEADPHONE, OUTPUT_DEVICE_BOTH or OUTPUT_DEVICE_AUTO
926 * @retval 0 if correct communication, else wrong communication
927 */
928static uint32_t
929wm8994_SetOutputMode(STAUDIO_Handle_t *haudio, uint8_t Output)
930{
931 uint32_t counter = 0;
932
933 switch(Output){
934 case OUTPUT_DEVICE_SPEAKER:
935 /* Enable DAC1 (Left), Enable DAC1 (Right),
936 Disable DAC2 (Left), Disable DAC2 (Right)*/
937 counter += CODEC_IO_Write(haudio, 0x05, 0x0C0C);
938
939 /* Enable the AIF1 Timeslot 0 (Left) to DAC 1 (Left) mixer path */
940 counter += CODEC_IO_Write(haudio, 0x601, 0x0000);
941
942 /* Enable the AIF1 Timeslot 0 (Right) to DAC 1 (Right) mixer path */
943 counter += CODEC_IO_Write(haudio, 0x602, 0x0000);
944
945 /* Disable the AIF1 Timeslot 1 (Left) to DAC 2 (Left) mixer path */
946 counter += CODEC_IO_Write(haudio, 0x604, 0x0002);
947
948 /* Disable the AIF1 Timeslot 1 (Right) to DAC 2 (Right) mixer path */
949 counter += CODEC_IO_Write(haudio, 0x605, 0x0002);
950 break;
951
952 case OUTPUT_DEVICE_HEADPHONE:
953 /* Disable DAC1 (Left), Disable DAC1 (Right),
954 Enable DAC2 (Left), Enable DAC2 (Right)*/
955 counter += CODEC_IO_Write(haudio, 0x05, 0x0303);
956
957 /* Enable the AIF1 Timeslot 0 (Left) to DAC 1 (Left) mixer path */
958 counter += CODEC_IO_Write(haudio, 0x601, 0x0001);
959
960 /* Enable the AIF1 Timeslot 0 (Right) to DAC 1 (Right) mixer path */
961 counter += CODEC_IO_Write(haudio, 0x602, 0x0001);
962
963 /* Disable the AIF1 Timeslot 1 (Left) to DAC 2 (Left) mixer path */
964 counter += CODEC_IO_Write(haudio, 0x604, 0x0000);
965
966 /* Disable the AIF1 Timeslot 1 (Right) to DAC 2 (Right) mixer path */
967 counter += CODEC_IO_Write(haudio, 0x605, 0x0000);
968 break;
969
970 case OUTPUT_DEVICE_BOTH:
971 /* Enable DAC1 (Left), Enable DAC1 (Right),
972 also Enable DAC2 (Left), Enable DAC2 (Right)*/
973 counter += CODEC_IO_Write(haudio, 0x05, 0x0303 | 0x0C0C);
974
975 /* Enable the AIF1 Timeslot 0 (Left) to DAC 1 (Left) mixer path */
976 counter += CODEC_IO_Write(haudio, 0x601, 0x0001);
977
978 /* Enable the AIF1 Timeslot 0 (Right) to DAC 1 (Right) mixer path */
979 counter += CODEC_IO_Write(haudio, 0x602, 0x0001);
980
981 /* Enable the AIF1 Timeslot 1 (Left) to DAC 2 (Left) mixer path */
982 counter += CODEC_IO_Write(haudio, 0x604, 0x0002);
983
984 /* Enable the AIF1 Timeslot 1 (Right) to DAC 2 (Right) mixer path */
985 counter += CODEC_IO_Write(haudio, 0x605, 0x0002);
986 break;
987
988 default:
989 /* Disable DAC1 (Left), Disable DAC1 (Right),
990 Enable DAC2 (Left), Enable DAC2 (Right)*/
991 counter += CODEC_IO_Write(haudio, 0x05, 0x0303);
992
993 /* Enable the AIF1 Timeslot 0 (Left) to DAC 1 (Left) mixer path */
994 counter += CODEC_IO_Write(haudio, 0x601, 0x0001);
995
996 /* Enable the AIF1 Timeslot 0 (Right) to DAC 1 (Right) mixer path */
997 counter += CODEC_IO_Write(haudio, 0x602, 0x0001);
998
999 /* Disable the AIF1 Timeslot 1 (Left) to DAC 2 (Left) mixer path */
1000 counter += CODEC_IO_Write(haudio, 0x604, 0x0000);
1001
1002 /* Disable the AIF1 Timeslot 1 (Right) to DAC 2 (Right) mixer path */
1003 counter += CODEC_IO_Write(haudio, 0x605, 0x0000);
1004 break;
1005 }
1006 return counter;
1007}
1008
1009/**
1010 * @brief Resets wm8994 registers.
1011 * @param DeviceAddr: Device address on communication Bus.
1012 * @retval 0 if correct communication, else wrong communication
1013 */
1014static ER
1015wm8994_Reset(STAUDIO_Handle_t *haudio)
1016{
1017 uint32_t deviceid = 0;
1018 ER ercd;
1019 uint8_t buffer[4];
1020
1021 /* Get the WM8994 ID. */
1022 ercd = i2c_memread(haudio->hi2c, haudio->i2caddress, (uint16_t)WM8994_CHIPID_ADDR, I2C_MEMADD_SIZE_16BIT, buffer, 2, 1000);
1023 if(ercd != E_OK)
1024 return ercd;
1025 deviceid = (buffer[0] << 8) | buffer[1];
1026
1027 /* wm8994 codec initialization */
1028#if 1 /* ROI DEBUG */
1029 syslog_2(LOG_NOTICE, "## wm8994_Reset deviceid[%08x][%08x] ##", deviceid, WM8994_ID);
1030#endif /* ROI DEBUG */
1031
1032 if(deviceid != WM8994_ID)
1033 return E_SYS;
1034
1035 /* Reset Codec by writing in 0x0000 address register */
1036 CODEC_IO_Write(haudio, 0x0000, 0x0000);
1037 haudio->outputEnabled = 0;
1038 haudio->inputEnabled = 0;
1039 haudio->ColdStartup = 1;
1040 return E_OK;
1041}
1042
1043
1044static void SAIx_Out_Init(STAUDIO_Handle_t *haudio, uint32_t AudioFreq, uint16_t framesize)
1045{
1046 AUDIO_Handle_t *hsai = haudio->hsai;
1047
1048 /* Configure SAI_Block_x
1049 LSBFirst: Disabled
1050 DataSize: 16 */
1051 hsai->OutInit.MonoStereoMode = SAI_STEREOMODE;
1052 hsai->OutInit.AudioFrequency = AudioFreq;
1053 hsai->OutInit.AudioMode = SAI_MODEMASTER_TX;
1054 hsai->OutInit.NoDivider = SAI_MASTERDIVIDER_ENABLE;
1055 hsai->OutInit.Protocol = SAI_FREE_PROTOCOL;
1056 hsai->OutInit.DataSize = SAI_DATASIZE_16;
1057 hsai->OutInit.FirstBit = SAI_FIRSTBIT_MSB;
1058 hsai->OutInit.Synchro = SAI_ASYNCHRONOUS;
1059#if defined(TOPPERS_STM32F769_DISCOVERY) || defined(TOPPERS_STM32F7_DISCOVERY)
1060 hsai->OutInit.ClockStrobing = SAI_CLOCKSTROBING_RISINGEDGE;
1061 hsai->OutInit.OutputDrive = SAI_OUTPUTDRIVE_ENABLE;
1062#else
1063 hsai->OutInit.ClockStrobing = SAI_CLOCKSTROBING_FALLINGEDGE;
1064 hsai->OutInit.OutputDrive = SAI_OUTPUTDRIVE_DISABLE;
1065#endif
1066 hsai->OutInit.FIFOThreshold = SAI_FIFOTHRESHOLD_1QF;
1067 hsai->OutInit.SynchroExt = SAI_SYNCEXT_DISABLE;
1068 hsai->OutInit.CompandingMode= SAI_NOCOMPANDING;
1069 hsai->OutInit.TriState = SAI_OUTPUT_NOTRELEASED;
1070 hsai->OutInit.Mckdiv = 0;
1071
1072 /* Configure SAI_Block_x Frame
1073 Frame Length: 64
1074 Frame active Length: 32
1075 FS Definition: Start frame + Channel Side identification
1076 FS Polarity: FS active Low
1077 FS Offset: FS asserted one bit before the first bit of slot 0 */
1078 hsai->OutInit.FrameLength = framesize;
1079 hsai->OutInit.ActiveFrameLength = framesize / 2;
1080 hsai->OutInit.FSDefinition = SAI_FS_CHANNEL_IDENTIFICATION;
1081 hsai->OutInit.FSPolarity = SAI_FS_ACTIVE_LOW;
1082 hsai->OutInit.FSOffset = SAI_FS_BEFOREFIRSTBIT;
1083
1084 /* Configure SAI Block_x Slot
1085 Slot First Bit Offset: 0
1086 Slot Size : 16
1087 Slot Number: 4
1088 Slot Active: All slot actives */
1089 hsai->OutInit.FirstBitOffset = 0;
1090 hsai->OutInit.SlotSize = SAI_SLOTSIZE_DATASIZE;
1091 hsai->OutInit.SlotNumber = 4;
1092 hsai->OutInit.SlotActive = CODEC_AUDIOFRAME_SLOT_0123;
1093}
1094
1095
1096/*
1097 * オーディオ出力初期化設定
1098 * param1: STAUDIOハンドラ
1099 * param2: 出力デバイス設定
1100 * param3: ボリューム設定値
1101 * param4: オーディオ周波数値
1102 * param5: フレームサイズ(バイト)
1103 * return: E_OKで正常設定
1104 */
1105ER
1106staudio_out_init(STAUDIO_Handle_t *haudio, uint16_t OutputDevice, uint8_t Volume, uint32_t AudioFreq, uint16_t framesize)
1107{
1108 AUDIO_Handle_t *hsai;
1109 ER ercd = E_OK;
1110
1111 /* PLL clock is set depending by the AudioFreq (44.1khz vs 48khz groups) */
1112 if(haudio->hsai == NULL){
1113 haudio->hsai = audio_init(haudio->saiid);
1114 }
1115 else{
1116 /* Disable SAI peripheral */
1117 audio_disable(haudio->hsai, AUDIO_OUT_BLOCK);
1118 audio_end(haudio->hsai, AUDIO_OUT_BLOCK);
1119 }
1120 hsai = haudio->hsai;
1121 audio_clockconfig(hsai, AudioFreq, NULL);
1122
1123 /* SAI data transfer preparation:
1124 Prepare the Media to be used for the audio transfer from memory to SAI peripheral */
1125 /* Disable SAI peripheral to allow access to SAI internal registers */
1126 audio_disable(hsai, AUDIO_OUT_BLOCK);
1127
1128 SAIx_Out_Init(haudio, AudioFreq, framesize);
1129
1130 audio_start(hsai, AUDIO_OUT_BLOCK);
1131
1132 /* Enable SAI peripheral to generate MCLK */
1133 audio_enable(hsai, AUDIO_OUT_BLOCK);
1134
1135 /* wm8994 codec initialization */
1136 /* Reset the Codec Registers */
1137 ercd = wm8994_Reset(haudio);
1138 if(ercd == E_OK){
1139 /* Initialize the codec internal registers */
1140 wm8994_Init(haudio, OutputDevice, Volume, AudioFreq);
1141 }
1142 return ercd;
1143}
1144
1145/*
1146 * オーディオ出力演奏
1147 * param1: STAUDIOハンドラ
1148 * param2: 出力バッファポインタ
1149 * param3: 出力バッファサイズ
1150 * return: E_OKで正常設定
1151 */
1152ER
1153staudio_out_play(STAUDIO_Handle_t *haudio, uint16_t* pBuffer, uint32_t Size)
1154{
1155 AUDIO_Handle_t *hsai = haudio->hsai;
1156
1157 /* Call the audio Codec Play function */
1158 if(wm8994_SetMute(haudio, AUDIO_MUTE_OFF) != 0){
1159 return E_SYS;
1160 }
1161 else{
1162 /* Update the Media layer and enable it for play */
1163 hsai->transcallback = haudio->audio_fullout_func;
1164 hsai->transhalfcallback = haudio->audio_halfout_func;
1165 hsai->errorcallback = haudio->audio_error_func;
1166 audio_transmit(hsai, (uint8_t*) pBuffer, DMA_MAX(Size / AUDIODATA_SIZE));
1167 return E_OK;
1168 }
1169}
1170
1171/*
1172 * オーディオPAUSE設定
1173 * param1: STAUDIOハンドラ
1174 * return: E_OKで正常設定
1175 */
1176ER
1177staudio_out_pause(STAUDIO_Handle_t *haudio)
1178{
1179 /* Call the Audio Codec Pause/Resume function */
1180 if(wm8994_Pause(haudio) != 0){
1181 return E_SYS;
1182 }
1183 else{
1184 /* Call the Media layer pause function */
1185 audio_dmapause(haudio->hsai, AUDIO_OUT_BLOCK);
1186 return E_OK;
1187 }
1188}
1189
1190/*
1191 * オーディオRESUME設定
1192 * param1: STAUDIOハンドラ
1193 * return: E_OKで正常設定
1194 */
1195ER
1196staudio_out_resume(STAUDIO_Handle_t *haudio)
1197{
1198 /* Call the Audio Codec Pause/Resume function */
1199 if(wm8994_SetMute(haudio, AUDIO_MUTE_OFF) != 0){
1200 return E_SYS;
1201 }
1202 else{
1203 /* Call the Media layer pause/resume function */
1204 audio_dmaresume(haudio->hsai, AUDIO_OUT_BLOCK);
1205 return E_OK;
1206 }
1207}
1208
1209/*
1210 * オーディオ出力停止設定
1211 * param1: STAUDIOハンドラ
1212 * param2: 停止設定条件
1213 * return: E_OKで正常設定
1214 */
1215ER
1216staudio_out_stop(STAUDIO_Handle_t *haudio, uint32_t Option)
1217{
1218 /* Call the Media layer stop function */
1219 audio_dmastop(haudio->hsai, AUDIO_OUT_BLOCK);
1220
1221 /* Call Audio Codec Stop function */
1222 if(wm8994_Stop(haudio, Option) != 0){
1223 return E_SYS;
1224 }
1225 else{
1226 if(Option == CODEC_PDWN_HW){
1227 /* Wait at least 100us */
1228 dly_tsk(1);
1229 }
1230 return E_OK;
1231 }
1232}
1233
1234/*
1235 * オーディオボリューム設定
1236 * param1: STAUDIOハンドラ
1237 * param2: volumeパセンテージ(0%-100%)
1238 * return: E_OKで正常設定
1239 */
1240ER
1241staudio_out_setvolume(STAUDIO_Handle_t *haudio, uint8_t Volume)
1242{
1243 /* Call the codec volume control function with converted volume value */
1244 if(wm8994_SetVolume(haudio, Volume) != 0)
1245 return E_SYS;
1246 else
1247 return E_OK;
1248}
1249
1250/*
1251 * オーディオMUTE設定
1252 * param1: STAUDIOハンドラ
1253 * param2: MUTE設定コマンド(AUDIO_MUTE_ONまたはAUDIO_MUTE_OFF)
1254 * return: E_OKで正常設定
1255 */
1256ER
1257staudio_out_setmute(STAUDIO_Handle_t *haudio, uint32_t Cmd)
1258{
1259 /* Call the Codec Mute function */
1260 if(wm8994_SetMute(haudio, Cmd) != 0)
1261 return E_SYS;
1262 else
1263 return E_OK;
1264}
1265
1266/*
1267 * オーディオ出力モード設定
1268 * param1: STAUDIOハンドラ
1269 * param2: 出力モード(OUTPUT_DEVICE_SPEAKER,UTPUT_DEVICE_HEADPHONEまたはOUTPUT_DEVICE_BOTH)
1270 * return: E_OKで正常設定
1271 */
1272ER
1273staudio_out_setoutputmode(STAUDIO_Handle_t *haudio, uint8_t Output)
1274{
1275 /* Call the Codec output device function */
1276 if(wm8994_SetOutputMode(haudio, Output) != 0)
1277 return E_SYS;
1278 else
1279 return E_OK;
1280}
1281
1282/*
1283 * オーディオ周波数設定
1284 * param1: STAUDIOハンドラ
1285 * param2: 周波数値
1286 * return: E_OKで正常設定
1287 */
1288void
1289staudio_out_setfrequency(STAUDIO_Handle_t *haudio, uint32_t AudioFreq)
1290{
1291 /* PLL clock is set depending by the AudioFreq (44.1khz vs 48khz groups) */
1292 audio_clockconfig(haudio->hsai, AudioFreq, NULL);
1293
1294 /* Disable SAI peripheral to allow access to SAI internal registers */
1295 audio_disable(haudio->hsai, AUDIO_OUT_BLOCK);
1296
1297 /* Update the SAI audio frequency configuration */
1298 haudio->hsai->OutInit.AudioFrequency = AudioFreq;
1299 audio_start(haudio->hsai, AUDIO_OUT_BLOCK);
1300
1301 /* Enable SAI peripheral to generate MCLK */
1302 audio_enable(haudio->hsai, AUDIO_OUT_BLOCK);
1303}
1304
1305/*
1306 * オーディオフレームスロット設定
1307 * param1: STAUDIOハンドラ
1308 * param2: フレームスロット値
1309 */
1310void
1311staudio_out_setframeslot(STAUDIO_Handle_t *haudio, uint32_t AudioFrameSlot)
1312{
1313 /* Disable SAI peripheral to allow access to SAI internal registers */
1314 audio_disable(haudio->hsai, AUDIO_OUT_BLOCK);
1315
1316 /* Update the SAI audio frame slot configuration */
1317 haudio->hsai->OutInit.SlotActive = AudioFrameSlot;
1318 audio_start(haudio->hsai, AUDIO_OUT_BLOCK);
1319
1320 /* Enable SAI peripheral to generate MCLK */
1321 audio_enable(haudio->hsai, AUDIO_OUT_BLOCK);
1322}
1323
1324/*
1325 * オーディオ出力バッファ変更
1326 * param1: STAUDIOハンドラ
1327 * param2: 出力バッファポインタ
1328 * param3: バッファサイズ
1329 */
1330void
1331staudio_out_changebuffer(STAUDIO_Handle_t *haudio, uint16_t *pData, uint16_t Size)
1332{
1333 haudio->hsai->transcallback = haudio->audio_fullout_func;
1334 haudio->hsai->transhalfcallback = haudio->audio_halfout_func;
1335 haudio->hsai->errorcallback = haudio->audio_error_func;
1336 audio_transmit(haudio->hsai, (uint8_t*)pData, Size);
1337}
1338
1339/*
1340 * オーディオ出力処理終了
1341 * param1: STAUDIOハンドラ
1342 */
1343void
1344staudio_out_deinit(STAUDIO_Handle_t *haudio)
1345{
1346 if(haudio->hsai != NULL){
1347 /* Disable SAI peripheral */
1348 audio_disable(haudio->hsai, AUDIO_OUT_BLOCK);
1349 audio_end(haudio->hsai, AUDIO_OUT_BLOCK);
1350 if(audio_status(haudio->hsai, AUDIO_IN_BLOCK) == AUDIO_STATUS_RESET){
1351 /* DeInit the SAI MSP : this __weak function can be rewritten by the application */
1352 audio_deinit(haudio->hsai, AUDIO_OUT_BLOCK);
1353 haudio->hsai = NULL;
1354 }
1355 }
1356}
1357
1358/*******************************************************************************
1359 Static Functions
1360*******************************************************************************/
1361/**
1362 * @brief Initializes the input Audio Codec audio interface (SAI).
1363 * @param SaiOutMode: SAI_MODEMASTER_TX (for record and playback in parallel)
1364 * or SAI_MODEMASTER_RX (for record only).
1365 * @param SlotActive: CODEC_AUDIOFRAME_SLOT_02, CODEC_AUDIOFRAME_SLOT_13 or
1366 * CODEC_AUDIOFRAME_SLOT_0123
1367 * @param AudioFreq: Audio frequency to be configured for the SAI peripheral.
1368 * @retval None
1369 */
1370static void SAIx_In_Init(STAUDIO_Handle_t *haudio, uint32_t SaiOutMode, uint32_t SlotActive, uint32_t AudioFreq)
1371{
1372 /* Initialize the haudio_out_sai instance parameters */
1373 AUDIO_Handle_t *hsai = haudio->hsai;
1374
1375 /* Disable SAI peripheral to allow access to SAI internal registers */
1376 audio_disable(hsai, AUDIO_OUT_BLOCK);
1377
1378 /* Configure SAI_Block_x
1379 LSBFirst: Disabled
1380 DataSize: 16 */
1381 hsai->OutInit.AudioFrequency = AudioFreq;
1382#ifdef TOPPERS_STM32F769_DISCOVERY
1383 hsai->OutInit.AudioMode = SAI_MODEMASTER_RX;
1384#else
1385 hsai->OutInit.AudioMode = SaiOutMode;
1386#endif
1387 hsai->OutInit.MonoStereoMode = SAI_STEREOMODE;
1388 hsai->OutInit.NoDivider = SAI_MASTERDIVIDER_ENABLE;
1389 hsai->OutInit.Protocol = SAI_FREE_PROTOCOL;
1390 hsai->OutInit.DataSize = SAI_DATASIZE_16;
1391 hsai->OutInit.FirstBit = SAI_FIRSTBIT_MSB;
1392#if defined(TOPPERS_STM32F769_DISCOVERY) || defined(TOPPERS_STM32F7_DISCOVERY)
1393 hsai->OutInit.ClockStrobing = SAI_CLOCKSTROBING_RISINGEDGE;
1394 hsai->OutInit.OutputDrive = SAI_OUTPUTDRIVE_ENABLE;
1395#else
1396 hsai->OutInit.ClockStrobing = SAI_CLOCKSTROBING_FALLINGEDGE;
1397 hsai->OutInit.OutputDrive = SAI_OUTPUTDRIVE_DISABLE;
1398#endif
1399 hsai->OutInit.Synchro = SAI_ASYNCHRONOUS;
1400 hsai->OutInit.FIFOThreshold = SAI_FIFOTHRESHOLD_1QF;
1401#if defined(TOPPERS_STM32F769_DISCOVERY)
1402 hsai->OutInit.SynchroExt = SAI_SYNCEXT_DISABLE;
1403#endif
1404#ifndef TOPPERS_STM32F7_DISCOVERY
1405 hsai->OutInit.CompandingMode= SAI_NOCOMPANDING;
1406 hsai->OutInit.TriState = SAI_OUTPUT_NOTRELEASED;
1407 hsai->OutInit.Mckdiv = 0;
1408#endif
1409
1410 /* Configure SAI_Block_x Frame
1411 Frame Length: 64
1412 Frame active Length: 32
1413 FS Definition: Start frame + Channel Side identification
1414 FS Polarity: FS active Low
1415 FS Offset: FS asserted one bit before the first bit of slot 0 */
1416 hsai->OutInit.FrameLength = 64;
1417 hsai->OutInit.ActiveFrameLength = 32;
1418 hsai->OutInit.FSDefinition = SAI_FS_CHANNEL_IDENTIFICATION;
1419 hsai->OutInit.FSPolarity = SAI_FS_ACTIVE_LOW;
1420 hsai->OutInit.FSOffset = SAI_FS_BEFOREFIRSTBIT;
1421
1422 /* Configure SAI Block_x Slot
1423 Slot First Bit Offset: 0
1424 Slot Size : 16
1425 Slot Number: 4
1426 Slot Active: All slot actives */
1427 hsai->OutInit.FirstBitOffset = 0;
1428 hsai->OutInit.SlotSize = SAI_SLOTSIZE_DATASIZE;
1429 hsai->OutInit.SlotNumber = 4;
1430 hsai->OutInit.SlotActive = SlotActive;
1431
1432 audio_start(hsai, AUDIO_OUT_BLOCK);
1433
1434 /* Initialize SAI2 block B in SLAVE RX synchronous from SAI2 block A */
1435 /* Initialize the haudio_in_sai Instance parameter */
1436
1437 /* Disable SAI peripheral to allow access to SAI internal registers */
1438 audio_disable(hsai, AUDIO_IN_BLOCK);
1439
1440 /* Configure SAI_Block_x
1441 LSBFirst: Disabled
1442 DataSize: 16 */
1443 hsai->InInit.AudioFrequency = AudioFreq;
1444 hsai->InInit.AudioMode = SAI_MODESLAVE_RX;
1445 hsai->InInit.NoDivider = SAI_MASTERDIVIDER_ENABLE;
1446 hsai->InInit.Protocol = SAI_FREE_PROTOCOL;
1447 hsai->InInit.DataSize = SAI_DATASIZE_16;
1448 hsai->InInit.FirstBit = SAI_FIRSTBIT_MSB;
1449 hsai->InInit.ClockStrobing = SAI_CLOCKSTROBING_RISINGEDGE;
1450 hsai->InInit.Synchro = SAI_SYNCHRONOUS;
1451 hsai->InInit.OutputDrive = SAI_OUTPUTDRIVE_DISABLE;
1452 hsai->InInit.FIFOThreshold = SAI_FIFOTHRESHOLD_1QF;
1453#ifdef TOPPERS_STM32F7_DISCOVERY
1454 hsai->InInit.SynchroExt = SAI_SYNCEXT_DISABLE;
1455#endif
1456#ifndef TOPPERS_STM32F7_DISCOVERY
1457 hsai->InInit.CompandingMode= SAI_NOCOMPANDING;
1458 hsai->InInit.TriState = SAI_OUTPUT_NOTRELEASED;
1459 hsai->InInit.Mckdiv = 0;
1460#endif
1461
1462 /* Configure SAI_Block_x Frame
1463 Frame Length: 64
1464 Frame active Length: 32
1465 FS Definition: Start frame + Channel Side identification
1466 FS Polarity: FS active Low
1467 FS Offset: FS asserted one bit before the first bit of slot 0 */
1468 hsai->InInit.FrameLength = 64;
1469 hsai->InInit.ActiveFrameLength = 32;
1470 hsai->InInit.FSDefinition = SAI_FS_CHANNEL_IDENTIFICATION;
1471 hsai->InInit.FSPolarity = SAI_FS_ACTIVE_LOW;
1472 hsai->InInit.FSOffset = SAI_FS_BEFOREFIRSTBIT;
1473
1474 /* Configure SAI Block_x Slot
1475 Slot First Bit Offset: 0
1476 Slot Size : 16
1477 Slot Number: 4
1478 Slot Active: All slot active */
1479 hsai->InInit.FirstBitOffset = 0;
1480 hsai->InInit.SlotSize = SAI_SLOTSIZE_DATASIZE;
1481 hsai->InInit.SlotNumber = 4;
1482 hsai->InInit.SlotActive = SlotActive;
1483
1484 audio_start(hsai, AUDIO_IN_BLOCK);
1485
1486 /* Enable SAI peripheral to generate MCLK */
1487 audio_enable(hsai, AUDIO_OUT_BLOCK);
1488
1489 /* Enable SAI peripheral */
1490 audio_enable(hsai, AUDIO_IN_BLOCK);
1491}
1492
1493
1494/**
1495 * @brief Deinitializes the output Audio Codec audio interface (SAI).
1496 * @retval None
1497 */
1498static void SAIx_In_DeInit(STAUDIO_Handle_t *haudio)
1499{
1500 if(haudio->hsai != NULL){
1501 /* Disable SAI peripheral */
1502 audio_disable(haudio->hsai, AUDIO_IN_BLOCK);
1503 audio_end(haudio->hsai, AUDIO_IN_BLOCK);
1504 if(audio_status(haudio->hsai, AUDIO_OUT_BLOCK) == AUDIO_STATUS_RESET){
1505 /* DeInit the SAI MSP : this __weak function can be rewritten by the application */
1506 audio_deinit(haudio->hsai, AUDIO_IN_BLOCK);
1507 haudio->hsai = NULL;
1508 }
1509 }
1510}
1511
1512
1513#ifdef TOPPERS_STM32F769_DISCOVERY
1514/**
1515 * @brief Regular conversion complete callback.
1516 * @note In interrupt mode, user has to read conversion value in this function
1517 using HAL_DFSDM_FilterGetRegularValue.
1518 * @param hdfsdm_filter : DFSDM filter handle.
1519 * @retval None
1520 */
1521static void HAL_DFSDM_FilterRegConvCpltCallback(DFSDM_Filter_Handle_t *hdfsdm_filter)
1522{
1523 uint32_t index = 0;
1524
1525 if(hdfsdm_filter == &hAudioInTopLeftFilter){
1526 DmaTopLeftRecCplt = 1;
1527 }
1528 else if(hdfsdm_filter == &hAudioInTopRightFilter){
1529 DmaTopRightRecCplt = 1;
1530 }
1531 else if(hdfsdm_filter == &hAudioInButtomLeftFilter){
1532 DmaButtomLeftRecCplt = 1;
1533 }
1534 else{
1535 DmaButtomRightRecCplt = 1;
1536 }
1537
1538 if(AudioIn_ChannelNumber > 2){
1539 if((DmaTopLeftRecCplt == 1) && (DmaTopRightRecCplt == 1) && (DmaButtomLeftRecCplt == 1) && (DmaButtomRightRecCplt == 1)){
1540 for(index = (ScratchSize/2) ; index < ScratchSize; index++){
1541 hAudioIn.pRecBuf[AppBuffTrigger] = (uint16_t)(SaturaLH((pScratchBuff[1][index] >> 8), -32760, 32760));
1542 hAudioIn.pRecBuf[AppBuffTrigger + 1] = (uint16_t)(SaturaLH((pScratchBuff[0][index] >> 8), -32760, 32760));
1543 hAudioIn.pRecBuf[AppBuffTrigger + 2] = (uint16_t)(SaturaLH((pScratchBuff[3][index] >> 8), -32760, 32760));
1544 hAudioIn.pRecBuf[AppBuffTrigger + 3] = (uint16_t)(SaturaLH((pScratchBuff[2][index] >> 8), -32760, 32760));
1545 AppBuffTrigger +=4;
1546 }
1547 DmaTopLeftRecCplt = 0;
1548 DmaTopRightRecCplt = 0;
1549 DmaButtomLeftRecCplt = 0;
1550 DmaButtomRightRecCplt = 0;
1551 }
1552 }
1553 else{
1554 if((DmaTopLeftRecCplt == 1) && (DmaTopRightRecCplt == 1)){
1555 for(index = (ScratchSize/2) ; index < ScratchSize; index++){
1556 hAudioIn.pRecBuf[AppBuffTrigger] = (uint16_t)(SaturaLH((pScratchBuff[1][index] >> 8), -32760, 32760));
1557 hAudioIn.pRecBuf[AppBuffTrigger + 1] = (uint16_t)(SaturaLH((pScratchBuff[0][index] >> 8), -32760, 32760));
1558 AppBuffTrigger +=2;
1559 }
1560 DmaTopLeftRecCplt = 0;
1561 DmaTopRightRecCplt = 0;
1562 }
1563 }
1564
1565 /* Call Half Transfer Complete callback */
1566 if((AppBuffTrigger == hAudioIn.RecSize/2) && (AppBuffHalf == 0)){
1567 AppBuffHalf = 1;
1568 if(hstaudio != NULL && hstaudio->audio_halfin_func)
1569 hstaudio->audio_halfin_func(hdfsdm_filter);
1570 }
1571 /* Call Transfer Complete callback */
1572 if(AppBuffTrigger == hAudioIn.RecSize){
1573 /* Reset Application Buffer Trigger */
1574 AppBuffTrigger = 0;
1575 AppBuffHalf = 0;
1576 /* Call the record update function to get the next buffer to fill and its size (size is ignored) */
1577 if(hstaudio != NULL && hstaudio->audio_fullin_func)
1578 hstaudio->audio_fullin_func(hdfsdm_filter);
1579 }
1580}
1581
1582/**
1583 * @brief Half regular conversion complete callback.
1584 * @param hdfsdm_filter : DFSDM filter handle.
1585 * @retval None
1586 */
1587static void HAL_DFSDM_FilterRegConvHalfCpltCallback(DFSDM_Filter_Handle_t *hdfsdm_filter)
1588{
1589 uint32_t index = 0;
1590
1591 if(hdfsdm_filter == &hAudioInTopLeftFilter){
1592 DmaTopLeftRecHalfCplt = 1;
1593 }
1594 else if(hdfsdm_filter == &hAudioInTopRightFilter){
1595 DmaTopRightRecHalfCplt = 1;
1596 }
1597 else if(hdfsdm_filter == &hAudioInButtomLeftFilter){
1598 DmaButtomLeftRecHalfCplt = 1;
1599 }
1600 else{
1601 DmaButtomRightRecHalfCplt = 1;
1602 }
1603
1604 if(AudioIn_ChannelNumber > 2){
1605 if((DmaTopLeftRecHalfCplt == 1) && (DmaTopRightRecHalfCplt == 1) && (DmaButtomLeftRecHalfCplt == 1) && (DmaButtomRightRecHalfCplt == 1)){
1606 for(index = 0 ; index < ScratchSize/2; index++){
1607 hAudioIn.pRecBuf[AppBuffTrigger] = (uint16_t)(SaturaLH((pScratchBuff[1][index] >> 8), -32760, 32760));
1608 hAudioIn.pRecBuf[AppBuffTrigger + 1] = (uint16_t)(SaturaLH((pScratchBuff[0][index] >> 8), -32760, 32760));
1609 hAudioIn.pRecBuf[AppBuffTrigger + 2] = (uint16_t)(SaturaLH((pScratchBuff[3][index] >> 8), -32760, 32760));
1610 hAudioIn.pRecBuf[AppBuffTrigger + 3] = (uint16_t)(SaturaLH((pScratchBuff[2][index] >> 8), -32760, 32760));
1611 AppBuffTrigger +=4;
1612 }
1613 DmaTopLeftRecHalfCplt = 0;
1614 DmaTopRightRecHalfCplt = 0;
1615 DmaButtomLeftRecHalfCplt = 0;
1616 DmaButtomRightRecHalfCplt = 0;
1617 }
1618 }
1619 else{
1620 if((DmaTopLeftRecHalfCplt == 1) && (DmaTopRightRecHalfCplt == 1)){
1621 for(index = 0 ; index < ScratchSize/2; index++){
1622 hAudioIn.pRecBuf[AppBuffTrigger] = (uint16_t)(SaturaLH((pScratchBuff[1][index] >> 8), -32760, 32760));
1623 hAudioIn.pRecBuf[AppBuffTrigger + 1] = (uint16_t)(SaturaLH((pScratchBuff[0][index] >> 8), -32760, 32760));
1624 AppBuffTrigger +=2;
1625 }
1626 DmaTopLeftRecHalfCplt = 0;
1627 DmaTopRightRecHalfCplt = 0;
1628 }
1629 }
1630
1631 /* Call Half Transfer Complete callback */
1632 if((AppBuffTrigger == hAudioIn.RecSize/2) && (AppBuffHalf == 0)){
1633 AppBuffHalf = 1;
1634 if(hstaudio != NULL && hstaudio->audio_halfin_func)
1635 hstaudio->audio_halfin_func(hdfsdm_filter);
1636 }
1637 /* Call Transfer Complete callback */
1638 if(AppBuffTrigger == hAudioIn.RecSize){
1639 /* Reset Application Buffer Trigger */
1640 AppBuffTrigger = 0;
1641 AppBuffHalf = 0;
1642 /* Call the record update function to get the next buffer to fill and its size (size is ignored) */
1643 if(hstaudio != NULL && hstaudio->audio_fullin_func)
1644 hstaudio->audio_fullin_func(hdfsdm_filter);
1645 }
1646}
1647
1648/*******************************************************************************
1649 Static Functions
1650*******************************************************************************/
1651/**
1652 * @brief Initialize the Digital Filter for Sigma-Delta Modulators interface (DFSDM).
1653 * @param AudioFreq: Audio frequency to be used to set correctly the DFSDM peripheral.
1654 * @note Channel output Clock Divider and Filter Oversampling are calculated as follow:
1655 * - Clock_Divider = CLK(input DFSDM)/CLK(micro) with
1656 * 1MHZ < CLK(micro) < 3.2MHZ (TYP 2.4MHZ for MP34DT01TR)
1657 * - Oversampling = CLK(input DFSDM)/(Clock_Divider * AudioFreq)
1658 * @retval AUDIO_OK if correct communication, else wrong communication
1659 */
1660static ER DFSDMx_Init(uint32_t AudioFreq)
1661{
1662 ER ercd = E_OK;
1663
1664 /****************************************************************************/
1665 /********************** Channels configuration *****************************/
1666 /****************************************************************************/
1667 /* CHANNEL 1 configuration */
1668 hAudioInTopLeftChannel.state = DFSDM_CHANNEL_STATE_RESET;
1669 hAudioInTopLeftChannel.base = (uint32_t)TADR_DFSDM1_CHANNEL1_BASE;
1670 hAudioInTopLeftChannel.Init.OutClockActivation = 1 /* ENABLE */;
1671 hAudioInTopLeftChannel.Init.OutClockSelection = DFSDM_CHANNEL_OUTPUT_CLOCK_AUDIO;
1672 /* Set the DFSDM clock OUT audio frequency configuration */
1673 hAudioInTopLeftChannel.Init.OutClockDivider = DFSDM_CLOCK_DIVIDER(AudioFreq);
1674 hAudioInTopLeftChannel.Init.InputMultiplexer = DFSDM_CHANNEL_EXTERNAL_INPUTS;
1675 hAudioInTopLeftChannel.Init.InputDataPacking = DFSDM_CHANNEL_STANDARD_MODE;
1676 hAudioInTopLeftChannel.Init.InputPins = DFSDM_CHANNEL_SAME_CHANNEL_PINS;
1677 /* Request to sample stable data for LEFT micro on Rising edge */
1678 hAudioInTopLeftChannel.Init.SerialType = DFSDM_CHANNEL_SPI_RISING;
1679 hAudioInTopLeftChannel.Init.SerialSpiClock = DFSDM_CHANNEL_SPI_CLOCK_INTERNAL;
1680 hAudioInTopLeftChannel.Init.AwdFilterOrder = DFSDM_CHANNEL_FASTSINC_ORDER;
1681 hAudioInTopLeftChannel.Init.AwdOversampling = 10;
1682 hAudioInTopLeftChannel.Init.Offset = 0;
1683 hAudioInTopLeftChannel.Init.RightBitShift = DFSDM_RIGHT_BIT_SHIFT(AudioFreq);
1684 if(E_OK != (ercd = dfsdm_channel_init(&hAudioInTopLeftChannel))){
1685 return ercd;
1686 }
1687
1688 /* CHANNEL 0 configuration */
1689 hAudioInTopRightChannel.state = DFSDM_CHANNEL_STATE_RESET;
1690 hAudioInTopRightChannel.base = (uint32_t)TADR_DFSDM1_CHANNEL0_BASE;
1691 hAudioInTopRightChannel.Init.OutClockActivation = 1 /* ENABLE*/;
1692 hAudioInTopRightChannel.Init.OutClockSelection = DFSDM_CHANNEL_OUTPUT_CLOCK_AUDIO;
1693 /* Set the DFSDM clock OUT audio frequency configuration */
1694 hAudioInTopRightChannel.Init.OutClockDivider = DFSDM_CLOCK_DIVIDER(AudioFreq);
1695 hAudioInTopRightChannel.Init.InputMultiplexer = DFSDM_CHANNEL_EXTERNAL_INPUTS;
1696 hAudioInTopRightChannel.Init.InputDataPacking = DFSDM_CHANNEL_STANDARD_MODE;
1697 hAudioInTopRightChannel.Init.InputPins = DFSDM_CHANNEL_FOLLOWING_CHANNEL_PINS;
1698 /* Request to sample stable data for RIGHT micro on Falling edge */
1699 hAudioInTopRightChannel.Init.SerialType = DFSDM_CHANNEL_SPI_FALLING;
1700 hAudioInTopRightChannel.Init.SerialSpiClock = DFSDM_CHANNEL_SPI_CLOCK_INTERNAL;
1701 hAudioInTopRightChannel.Init.AwdFilterOrder = DFSDM_CHANNEL_FASTSINC_ORDER;
1702 hAudioInTopRightChannel.Init.AwdOversampling = 10;
1703 hAudioInTopRightChannel.Init.Offset = 0;
1704 hAudioInTopRightChannel.Init.RightBitShift = DFSDM_RIGHT_BIT_SHIFT(AudioFreq);
1705 if(E_OK != (ercd = dfsdm_channel_init(&hAudioInTopRightChannel))){
1706 return ercd;
1707 }
1708
1709 if(AudioIn_ChannelNumber > 2){
1710 /* CHANNEL 5 configuration */
1711 hAudioInButtomLeftChannel.state = DFSDM_CHANNEL_STATE_RESET;
1712 hAudioInButtomLeftChannel.base = (uint32_t)TADR_DFSDM1_CHANNEL5_BASE;
1713 hAudioInButtomLeftChannel.Init.OutClockActivation = 1 /* ENABLE */;
1714 hAudioInButtomLeftChannel.Init.OutClockSelection = DFSDM_CHANNEL_OUTPUT_CLOCK_AUDIO;
1715 /* Set the DFSDM clock OUT audio frequency configuration */
1716 hAudioInButtomLeftChannel.Init.OutClockDivider = DFSDM_CLOCK_DIVIDER(AudioFreq);
1717 hAudioInButtomLeftChannel.Init.InputMultiplexer = DFSDM_CHANNEL_EXTERNAL_INPUTS;
1718 hAudioInButtomLeftChannel.Init.InputDataPacking = DFSDM_CHANNEL_STANDARD_MODE;
1719 hAudioInButtomLeftChannel.Init.InputPins = DFSDM_CHANNEL_SAME_CHANNEL_PINS;
1720 /* Request to sample stable data for LEFT micro on Rising edge */
1721 hAudioInButtomLeftChannel.Init.SerialType = DFSDM_CHANNEL_SPI_RISING;
1722 hAudioInButtomLeftChannel.Init.SerialSpiClock = DFSDM_CHANNEL_SPI_CLOCK_INTERNAL;
1723 hAudioInButtomLeftChannel.Init.AwdFilterOrder = DFSDM_CHANNEL_FASTSINC_ORDER;
1724 hAudioInButtomLeftChannel.Init.AwdOversampling = 10;
1725 hAudioInButtomLeftChannel.Init.Offset = 0;
1726 hAudioInButtomLeftChannel.Init.RightBitShift = DFSDM_RIGHT_BIT_SHIFT(AudioFreq);
1727 if(E_OK != (ercd = dfsdm_channel_init(&hAudioInButtomLeftChannel))){
1728 return ercd;
1729 }
1730
1731 /* CHANNEL 4 configuration */
1732 hAudioInButtomRightChannel.state = DFSDM_CHANNEL_STATE_RESET;
1733 hAudioInButtomRightChannel.base = (uint32_t)TADR_DFSDM1_CHANNEL4_BASE;
1734 hAudioInButtomRightChannel.Init.OutClockActivation = 1 /* ENABLE */;
1735 hAudioInButtomRightChannel.Init.OutClockSelection = DFSDM_CHANNEL_OUTPUT_CLOCK_AUDIO;
1736 /* Set the DFSDM clock OUT audio frequency configuration */
1737 hAudioInButtomRightChannel.Init.OutClockDivider = DFSDM_CLOCK_DIVIDER(AudioFreq);
1738 hAudioInButtomRightChannel.Init.InputMultiplexer = DFSDM_CHANNEL_EXTERNAL_INPUTS;
1739 hAudioInButtomRightChannel.Init.InputDataPacking = DFSDM_CHANNEL_STANDARD_MODE;
1740 hAudioInButtomRightChannel.Init.InputPins = DFSDM_CHANNEL_FOLLOWING_CHANNEL_PINS;
1741 /* Request to sample stable data for RIGHT micro on Falling edge */
1742 hAudioInButtomRightChannel.Init.SerialType = DFSDM_CHANNEL_SPI_FALLING;
1743 hAudioInButtomRightChannel.Init.SerialSpiClock = DFSDM_CHANNEL_SPI_CLOCK_INTERNAL;
1744 hAudioInButtomRightChannel.Init.AwdFilterOrder = DFSDM_CHANNEL_FASTSINC_ORDER;
1745 hAudioInButtomRightChannel.Init.AwdOversampling = 10;
1746 hAudioInButtomRightChannel.Init.Offset = 0;
1747 hAudioInButtomRightChannel.Init.RightBitShift = DFSDM_RIGHT_BIT_SHIFT(AudioFreq);
1748 if(E_OK != (ercd = dfsdm_channel_init(&hAudioInButtomRightChannel))){
1749 return ercd;
1750 }
1751 }
1752 /****************************************************************************/
1753 /********************** Filters configuration ******************************/
1754 /****************************************************************************/
1755 /* FILTER 0 configuration */
1756 hAudioInTopLeftFilter.state = DFSDM_FILTER_STATE_RESET;
1757 hAudioInTopLeftFilter.base = (uint32_t)AUDIO_DFSDMx_TOP_LEFT_FILTER;
1758 hAudioInTopLeftFilter.regconvhalfcallback = HAL_DFSDM_FilterRegConvHalfCpltCallback;
1759 hAudioInTopLeftFilter.regconvcallback = HAL_DFSDM_FilterRegConvCpltCallback;
1760 hAudioInTopLeftFilter.Init.RegTrigger = DFSDM_FILTER_SW_TRIGGER;
1761 hAudioInTopLeftFilter.Init.RegFastMode = 1 /* ENABLE */;
1762 hAudioInTopLeftFilter.Init.RegDmaMode = 1 /* ENABLE */;
1763 hAudioInTopLeftFilter.Init.InjTrigger = DFSDM_FILTER_SW_TRIGGER;
1764 hAudioInTopLeftFilter.Init.InjScanMode = 1 /* ENABLE */;
1765 hAudioInTopLeftFilter.Init.InjDmaMode = 0 /* DISABLE */;
1766 hAudioInTopLeftFilter.Init.InjExtTrigger = DFSDM_FILTER_EXT_TRIG_TIM1_TRGO;
1767 hAudioInTopLeftFilter.Init.InjExtTriggerEdge = DFSDM_FILTER_EXT_TRIG_RISING_EDGE;
1768 hAudioInTopLeftFilter.Init.FilterSincOrder = DFSDM_FILTER_ORDER(AudioFreq);
1769 /* Set the DFSDM Filters Oversampling to have correct sample rate */
1770 hAudioInTopLeftFilter.Init.FilterOversampling = DFSDM_OVER_SAMPLING(AudioFreq);
1771 hAudioInTopLeftFilter.Init.FilterIntOversampling = 1;
1772 if(E_OK != (ercd = dfsdm_filter_init(&hAudioInTopLeftFilter))){
1773 return ercd;
1774 }
1775
1776 /* Configure injected channel */
1777 if(E_OK != (ercd = dfsdm_filter_config_reg(&hAudioInTopLeftFilter, AUDIO_DFSDMx_TOP_LEFT_CHANNEL, DFSDM_CONTINUOUS_CONV_ON))){
1778 return ercd;
1779 }
1780
1781 /* FILTER 1 configuration */
1782 hAudioInTopRightFilter.state = DFSDM_FILTER_STATE_RESET;
1783 hAudioInTopRightFilter.base = (uint32_t)AUDIO_DFSDMx_TOP_RIGHT_FILTER;
1784 hAudioInTopRightFilter.regconvhalfcallback = HAL_DFSDM_FilterRegConvHalfCpltCallback;
1785 hAudioInTopRightFilter.regconvcallback = HAL_DFSDM_FilterRegConvCpltCallback;
1786 hAudioInTopRightFilter.Init.RegTrigger = DFSDM_FILTER_SYNC_TRIGGER;
1787 hAudioInTopRightFilter.Init.RegFastMode = 1 /* ENABLE */;
1788 hAudioInTopRightFilter.Init.RegDmaMode = 1 /* ENABLE */;
1789 hAudioInTopRightFilter.Init.InjTrigger = DFSDM_FILTER_SW_TRIGGER;
1790 hAudioInTopRightFilter.Init.InjScanMode = 0 /* DISABLE */;
1791 hAudioInTopRightFilter.Init.InjDmaMode = 0 /* DISABLE */;
1792 hAudioInTopRightFilter.Init.InjExtTrigger = DFSDM_FILTER_EXT_TRIG_TIM1_TRGO;
1793 hAudioInTopRightFilter.Init.InjExtTriggerEdge = DFSDM_FILTER_EXT_TRIG_RISING_EDGE;
1794 hAudioInTopRightFilter.Init.FilterSincOrder = DFSDM_FILTER_ORDER(AudioFreq);
1795 /* Set the DFSDM Filters Oversampling to have correct sample rate */
1796 hAudioInTopRightFilter.Init.FilterOversampling = DFSDM_OVER_SAMPLING(AudioFreq);
1797 hAudioInTopRightFilter.Init.FilterIntOversampling = 1;
1798 if(E_OK != (ercd = dfsdm_filter_init(&hAudioInTopRightFilter))){
1799 return ercd;
1800 }
1801 /* Configure injected channel */
1802 if(E_OK != (ercd = dfsdm_filter_config_reg(&hAudioInTopRightFilter, AUDIO_DFSDMx_TOP_RIGHT_CHANNEL, DFSDM_CONTINUOUS_CONV_ON))){
1803 return ercd;
1804 }
1805
1806 if(AudioIn_ChannelNumber > 2){
1807 /* FILTER 2 configuration */
1808 hAudioInButtomLeftFilter.state = DFSDM_FILTER_STATE_RESET;
1809 hAudioInButtomLeftFilter.base = (uint32_t)AUDIO_DFSDMx_BUTTOM_LEFT_FILTER;
1810 hAudioInButtomLeftFilter.regconvhalfcallback = HAL_DFSDM_FilterRegConvHalfCpltCallback;
1811 hAudioInButtomLeftFilter.regconvcallback = HAL_DFSDM_FilterRegConvCpltCallback;
1812 hAudioInButtomLeftFilter.Init.RegTrigger = DFSDM_FILTER_SYNC_TRIGGER;
1813 hAudioInButtomLeftFilter.Init.RegFastMode = 1 /* ENABLE */;
1814 hAudioInButtomLeftFilter.Init.RegDmaMode = 1 /* ENABLE */;
1815 hAudioInButtomLeftFilter.Init.InjTrigger = DFSDM_FILTER_SW_TRIGGER;
1816 hAudioInButtomLeftFilter.Init.InjScanMode = 1 /* ENABLE */;
1817 hAudioInButtomLeftFilter.Init.InjDmaMode = 0 /* DISABLE */;
1818 hAudioInButtomLeftFilter.Init.InjExtTrigger = DFSDM_FILTER_EXT_TRIG_TIM1_TRGO;
1819 hAudioInButtomLeftFilter.Init.InjExtTriggerEdge = DFSDM_FILTER_EXT_TRIG_RISING_EDGE;
1820 hAudioInButtomLeftFilter.Init.FilterSincOrder = DFSDM_FILTER_ORDER(AudioFreq);
1821 /* Set the DFSDM Filters Oversampling to have correct sample rate */
1822 hAudioInButtomLeftFilter.Init.FilterOversampling = DFSDM_OVER_SAMPLING(AudioFreq);
1823 hAudioInButtomLeftFilter.Init.FilterIntOversampling = 1;
1824 if(E_OK != (ercd = dfsdm_filter_init(&hAudioInButtomLeftFilter))){
1825 return ercd;
1826 }
1827
1828 /* Configure injected channel */
1829 if(E_OK != (ercd = dfsdm_filter_config_reg(&hAudioInButtomLeftFilter, AUDIO_DFSDMx_BUTTOM_LEFT_CHANNEL, DFSDM_CONTINUOUS_CONV_ON))){
1830 return ercd;
1831 }
1832
1833 /* FILTER 3 configuration */
1834 hAudioInButtomRightFilter.state = DFSDM_FILTER_STATE_RESET;
1835 hAudioInButtomRightFilter.base = (uint32_t)AUDIO_DFSDMx_BUTTOM_RIGHT_FILTER;
1836 hAudioInButtomRightFilter.regconvhalfcallback = HAL_DFSDM_FilterRegConvHalfCpltCallback;
1837 hAudioInButtomRightFilter.regconvcallback = HAL_DFSDM_FilterRegConvCpltCallback;
1838 hAudioInButtomRightFilter.Init.RegTrigger = DFSDM_FILTER_SYNC_TRIGGER;
1839 hAudioInButtomRightFilter.Init.RegFastMode = 1 /* ENABLE */;
1840 hAudioInButtomRightFilter.Init.RegDmaMode = 1 /* ENABLE */;
1841 hAudioInButtomRightFilter.Init.InjTrigger = DFSDM_FILTER_SW_TRIGGER;
1842 hAudioInButtomRightFilter.Init.InjScanMode = 0 /* DISABLE */;
1843 hAudioInButtomRightFilter.Init.InjDmaMode = 0 /* DISABLE */;
1844 hAudioInButtomRightFilter.Init.InjExtTrigger = DFSDM_FILTER_EXT_TRIG_TIM1_TRGO;
1845 hAudioInButtomRightFilter.Init.InjExtTriggerEdge = DFSDM_FILTER_EXT_TRIG_RISING_EDGE;
1846 hAudioInButtomRightFilter.Init.FilterSincOrder = DFSDM_FILTER_ORDER(AudioFreq);
1847 /* Set the DFSDM Filters Oversampling to have correct sample rate */
1848 hAudioInButtomRightFilter.Init.FilterOversampling = DFSDM_OVER_SAMPLING(AudioFreq);
1849 hAudioInButtomRightFilter.Init.FilterIntOversampling = 1;
1850 if(E_OK != (ercd = dfsdm_filter_init(&hAudioInButtomRightFilter))){
1851 return ercd;
1852 }
1853 /* Configure injected channel */
1854 if(E_OK != (ercd = dfsdm_filter_config_reg(&hAudioInButtomRightFilter, AUDIO_DFSDMx_BUTTOM_RIGHT_CHANNEL, DFSDM_CONTINUOUS_CONV_ON))){
1855 return ercd;
1856 }
1857 }
1858 return ercd;
1859}
1860
1861/**
1862 * @brief De-initialize the Digital Filter for Sigma-Delta Modulators interface (DFSDM).
1863 * @retval AUDIO_OK if correct communication, else wrong communication
1864 */
1865static ER DFSDMx_DeInit(void)
1866{
1867 ER ercd = E_OK;
1868
1869 /* De-initializes the DFSDM filters to allow access to DFSDM internal registers */
1870 if(E_OK != (ercd = dfsdm_filter_deinit(&hAudioInTopLeftFilter))){
1871 return ercd;
1872 }
1873 if(E_OK != (ercd = dfsdm_filter_deinit(&hAudioInTopRightFilter))){
1874 return ercd;
1875 }
1876
1877 /* De-initializes the DFSDM channels to allow access to DFSDM internal registers */
1878 if(E_OK != (ercd = dfsdm_channel_deinit(&hAudioInTopLeftChannel))){
1879 return ercd;
1880 }
1881 if(E_OK != (ercd = dfsdm_channel_deinit(&hAudioInTopRightChannel))){
1882 return ercd;
1883 }
1884
1885 if(AudioIn_ChannelNumber > 2){
1886 /* De-initializes the DFSDM filters to allow access to DFSDM internal registers */
1887 if(E_OK != (ercd = dfsdm_filter_deinit(&hAudioInButtomLeftFilter))){
1888 return ercd;
1889 }
1890 if(E_OK != (ercd = dfsdm_filter_deinit(&hAudioInButtomRightFilter))){
1891 return ercd;
1892 }
1893
1894 /* De-initializes the DFSDM channels to allow access to DFSDM internal registers */
1895 if(E_OK != (ercd = dfsdm_channel_deinit(&hAudioInButtomLeftChannel))){
1896 return ercd;
1897 }
1898 if(E_OK != (ercd = dfsdm_channel_deinit(&hAudioInButtomRightChannel))){
1899 return ercd;
1900 }
1901 }
1902 return ercd;
1903}
1904
1905/**
1906 * @brief Initialize the DFSDM channel MSP.
1907 * @param hdfsdm_channel : DFSDM channel handle.
1908 * @retval None
1909 */
1910static void DFSDMx_ChannelMspInit(void)
1911{
1912 GPIO_Init_t GPIO_InitStruct;
1913
1914 /* Enable DFSDM clock */
1915 sil_orw_mem((uint32_t *)(TADR_RCC_BASE+TOFF_RCC_APB2ENR), RCC_APB2ENR_DFSDM1EN);
1916
1917 /* Enable GPIO clock */
1918 AUDIO_DFSDMx_DMIC_DATIN_GPIO_CLK_ENABLE();
1919 AUDIO_DFSDMx_CKOUT_DMIC_GPIO_CLK_ENABLE();
1920
1921 /* DFSDM pins configuration: DFSDM_CKOUT, DMIC_DATIN1 pins ------------------*/
1922 GPIO_InitStruct.mode = GPIO_MODE_AF;
1923 GPIO_InitStruct.pull = GPIO_NOPULL;
1924 GPIO_InitStruct.otype = GPIO_OTYPE_PP;
1925 GPIO_InitStruct.speed = GPIO_SPEED_HIGH;
1926 GPIO_InitStruct.alternate = AUDIO_DFSDMx_CKOUT_AF;
1927 gpio_setup((uint32_t)AUDIO_DFSDMx_CKOUT_DMIC_GPIO_PORT, &GPIO_InitStruct, AUDIO_DFSDMx_CKOUT_PINNO);
1928
1929 /* DFSDM pin configuration: DMIC_DATIN1 pin --------------------------------*/
1930 GPIO_InitStruct.alternate = AUDIO_DFSDMx_DMIC_DATIN_AF;
1931 gpio_setup((uint32_t)AUDIO_DFSDMx_DMIC_DATIN_GPIO_PORT, &GPIO_InitStruct, AUDIO_DFSDMx_DMIC_DATIN1_PINNO);
1932
1933 if(AudioIn_ChannelNumber > 2){
1934 /* DFSDM pin configuration: DMIC_DATIN5 pin --------------------------------*/
1935 GPIO_InitStruct.alternate = AUDIO_DFSDMx_DMIC_DATIN_AF;
1936 gpio_setup((uint32_t)AUDIO_DFSDMx_DMIC_DATIN_GPIO_PORT, &GPIO_InitStruct, AUDIO_DFSDMx_DMIC_DATIN5_PINNO);
1937 }
1938}
1939
1940/**
1941 * @brief Initialize the DFSDM filter MSP.
1942 * @param hdfsdm_filter : DFSDM filter handle.
1943 * @retval None
1944 */
1945static void DFSDMx_FilterMspInit(void)
1946{
1947 /* Enable DFSDM clock */
1948 sil_orw_mem((uint32_t *)(TADR_RCC_BASE+TOFF_RCC_APB2ENR), RCC_APB2ENR_DFSDM1EN);
1949
1950 /* Enable the DMA clock */
1951 sil_orw_mem((uint32_t *)(TADR_RCC_BASE+TOFF_RCC_AHB1ENR), RCC_AHB1ENR_DMA2EN);
1952
1953 /*********** Configure DMA stream for TOP LEFT microphone *******************/
1954 hDmaTopLeft.Init.Direction = DMA_PERIPH_TO_MEMORY;
1955 hDmaTopLeft.Init.PeriphInc = DMA_PINC_DISABLE;
1956 hDmaTopLeft.Init.MemInc = DMA_MINC_ENABLE;
1957 hDmaTopLeft.Init.PeriphDataAlignment = AUDIO_DFSDMx_DMAx_PERIPH_DATA_SIZE;
1958 hDmaTopLeft.Init.MemDataAlignment = AUDIO_DFSDMx_DMAx_MEM_DATA_SIZE;
1959 hDmaTopLeft.Init.Mode = DMA_CIRCULAR;
1960 hDmaTopLeft.Init.Priority = DMA_PRIORITY_HIGH;
1961 hDmaTopLeft.base = (uint32_t)TADR_DMA2_STM4_BASE;
1962 hDmaTopLeft.Init.Channel = AUDIO_DFSDMx_DMAx_CHANNEL;
1963
1964 /* Associate the DMA handle */
1965 hAudioInTopLeftFilter.hdmaReg = &hDmaTopLeft;
1966 hDmaTopLeft.localdata = &hAudioInTopLeftFilter;
1967
1968 /* Reset DMA handle state */
1969 hDmaTopLeft.status = 0;
1970
1971 /* Configure the DMA Channel */
1972 dma_init(&hDmaTopLeft);
1973
1974 /*********** Configure DMA stream for TOP RIGHT microphone ******************/
1975 hDmaTopRight.Init.Direction = DMA_PERIPH_TO_MEMORY;
1976 hDmaTopRight.Init.PeriphInc = DMA_PINC_DISABLE;
1977 hDmaTopRight.Init.MemInc = DMA_MINC_ENABLE;
1978 hDmaTopRight.Init.PeriphDataAlignment = AUDIO_DFSDMx_DMAx_PERIPH_DATA_SIZE;
1979 hDmaTopRight.Init.MemDataAlignment = AUDIO_DFSDMx_DMAx_MEM_DATA_SIZE;
1980 hDmaTopRight.Init.Mode = DMA_CIRCULAR;
1981 hDmaTopRight.Init.Priority = DMA_PRIORITY_HIGH;
1982 hDmaTopRight.base = (uint32_t)TADR_DMA2_STM1_BASE;
1983 hDmaTopRight.Init.Channel = AUDIO_DFSDMx_DMAx_CHANNEL;
1984
1985 /* Associate the DMA handle */
1986 hAudioInTopRightFilter.hdmaReg = &hDmaTopRight;
1987 hDmaTopRight.localdata = &hAudioInTopRightFilter;
1988
1989 /* Reset DMA handle state */
1990 hDmaTopRight.status = 0;
1991
1992 /* Configure the DMA Channel */
1993 dma_init(&hDmaTopRight);
1994
1995 if(AudioIn_ChannelNumber > 2){
1996 /*********** Configure DMA stream for BUTTOM LEFT microphone ****************/
1997 hDmaButtomLeft.Init.Direction = DMA_PERIPH_TO_MEMORY;
1998 hDmaButtomLeft.Init.PeriphInc = DMA_PINC_DISABLE;
1999 hDmaButtomLeft.Init.MemInc = DMA_MINC_ENABLE;
2000 hDmaButtomLeft.Init.PeriphDataAlignment = AUDIO_DFSDMx_DMAx_PERIPH_DATA_SIZE;
2001 hDmaButtomLeft.Init.MemDataAlignment = AUDIO_DFSDMx_DMAx_MEM_DATA_SIZE;
2002 hDmaButtomLeft.Init.Mode = DMA_CIRCULAR;
2003 hDmaButtomLeft.Init.Priority = DMA_PRIORITY_HIGH;
2004 hDmaButtomLeft.base = (uint32_t)AUDIO_DFSDMx_DMAx_BUTTOM_LEFT_STREAM;
2005 hDmaButtomLeft.Init.Channel = AUDIO_DFSDMx_DMAx_CHANNEL;
2006
2007 /* Associate the DMA handle */
2008 hAudioInButtomLeftFilter.hdmaReg = &hDmaButtomLeft;
2009 hDmaButtomLeft.localdata = &hAudioInButtomLeftFilter;
2010
2011 /* Reset DMA handle state */
2012 hDmaButtomLeft.status = 0;
2013
2014 /* Configure the DMA Channel */
2015 dma_init(&hDmaButtomLeft);
2016
2017 /*********** Configure DMA stream for BUTTOM RIGHT microphone ***************/
2018 hDmaButtomRight.Init.Direction = DMA_PERIPH_TO_MEMORY;
2019 hDmaButtomRight.Init.PeriphInc = DMA_PINC_DISABLE;
2020 hDmaButtomRight.Init.MemInc = DMA_MINC_ENABLE;
2021 hDmaButtomRight.Init.PeriphDataAlignment = AUDIO_DFSDMx_DMAx_PERIPH_DATA_SIZE;
2022 hDmaButtomRight.Init.MemDataAlignment = AUDIO_DFSDMx_DMAx_MEM_DATA_SIZE;
2023 hDmaButtomRight.Init.Mode = DMA_CIRCULAR;
2024 hDmaButtomRight.Init.Priority = DMA_PRIORITY_HIGH;
2025 hDmaButtomRight.base = (uint32_t)AUDIO_DFSDMx_DMAx_BUTTOM_RIGHT_STREAM;
2026 hDmaButtomRight.Init.Channel = AUDIO_DFSDMx_DMAx_CHANNEL;
2027
2028 /* Associate the DMA handle */
2029 hAudioInButtomRightFilter.hdmaReg = &hDmaButtomRight;
2030 hDmaButtomRight.localdata = &hAudioInButtomRightFilter;
2031
2032 /* Reset DMA handle state */
2033 hDmaButtomRight.status = 0;
2034
2035 /* Configure the DMA Channel */
2036 dma_init(&hDmaButtomRight);
2037 }
2038}
2039
2040/**
2041 * @brief DeInitialize the DFSDM filter MSP.
2042 * @param hdfsdm_filter : DFSDM filter handle.
2043 * @retval None
2044 */
2045static void DFSDMx_FilterMspDeInit(void)
2046{
2047 /* Configure the DMA Channel */
2048 dma_deinit(&hDmaTopLeft);
2049 dma_deinit(&hDmaTopRight);
2050 if(AudioIn_ChannelNumber > 2){
2051 dma_deinit(&hDmaButtomLeft);
2052 dma_deinit(&hDmaButtomRight);
2053 }
2054}
2055
2056void dfsdm1fl0_handler(void)
2057{
2058 dfsdm_irqhandler(&hAudioInTopLeftFilter);
2059}
2060
2061void dfsdm1fl1_handler(void)
2062{
2063 dfsdm_irqhandler(&hAudioInTopRightFilter);
2064}
2065
2066void dfsdm1fl2_handler(void)
2067{
2068 dfsdm_irqhandler(&hAudioInButtomLeftFilter);
2069}
2070
2071void dfsdm1fl3_handler(void)
2072{
2073 dfsdm_irqhandler(&hAudioInButtomRightFilter);
2074}
2075
2076#endif
2077
2078/*
2079 * オーディオ入力初期化設定
2080 * param1: STAUDIOハンドラ
2081 * param2: 入力デバイス設定
2082 * param3: オーディオ周波数値
2083 * param4: BitRes
2084 * param5: チャネル番号
2085 * return: E_OKで正常設定
2086 */
2087ER
2088staudio_in_init(STAUDIO_Handle_t *haudio, uint16_t InputDevice, uint32_t AudioFreq, uint32_t BitRes, uint32_t ChnlNbr)
2089{
2090 ER ercd = E_OK;
2091 uint32_t slot_active;
2092
2093 haudio->InputDevice = InputDevice;
2094 if(InputDevice == INPUT_DEVICE_DIGITAL_MIC){
2095#ifdef TOPPERS_STM32F769_DISCOVERY
2096 AudioIn_ChannelNumber = ChnlNbr;
2097 /* PLL clock is set depending by the AudioFreq (44.1khz vs 48khz groups) */
2098 dfsdm_clockconfig(AUDIO2_PORTID, AudioFreq);
2099 sil_modw_mem((uint32_t *)(TADR_RCC_BASE+TOFF_RCC_DCKCFGR1), RCC_DCKCFGR1_ADFSDM1SEL, (uint32_t)(RCC_DCKCFGR1_ADFSDM1SEL));
2100
2101 /* Init the SAI MSP: this __weak function can be redefined by the application*/
2102 /* MSP channels initialization */
2103 DFSDMx_ChannelMspInit();
2104 /* MSP filters initialization */
2105 DFSDMx_FilterMspInit();
2106
2107 /* Initializes DFSDM peripheral */
2108 DFSDMx_Init(AudioFreq);
2109 hstaudio = haudio;
2110 ercd = E_OK;
2111#else
2112 ercd = E_PAR;
2113#endif
2114 }
2115 /* Only INPUT_LINE_1, MICROPHONE_1, MICROPHONE_2 and MIC1&MIC2 inputs supported */
2116 else if((InputDevice != INPUT_DEVICE_INPUT_LINE_1) &&
2117 (InputDevice != INPUT_DEVICE_DIGITAL_MICROPHONE_1) &&
2118 (InputDevice != INPUT_DEVICE_DIGITAL_MICROPHONE_2) &&
2119 (InputDevice != INPUT_DEVICE_DIGITAL_MIC1_MIC2)){
2120 ercd = E_PAR;
2121 }
2122 else{
2123 /* PLL clock is set depending on the AudioFreq (44.1khz vs 48khz groups) */
2124 if(haudio->hsai == NULL){
2125 haudio->hsai = audio_init(haudio->saiid);
2126 }
2127 else{
2128 /* Disable SAI peripheral */
2129 audio_disable(haudio->hsai, AUDIO_IN_BLOCK);
2130 audio_end(haudio->hsai, AUDIO_IN_BLOCK);
2131 }
2132 audio_clockconfig(haudio->hsai, AudioFreq, NULL); /* Clock config is shared between AUDIO IN and OUT */
2133
2134 /* Configure SAI in master RX mode :
2135 * - SAI2_block_A in master RX mode
2136 * - SAI2_block_B in slave RX mode synchronous from SAI2_block_A
2137 */
2138 if(InputDevice == INPUT_DEVICE_DIGITAL_MICROPHONE_2){
2139 slot_active = CODEC_AUDIOFRAME_SLOT_13;
2140 }
2141 else if(InputDevice == INPUT_DEVICE_DIGITAL_MIC1_MIC2){
2142 slot_active = CODEC_AUDIOFRAME_SLOT_0123;
2143 }
2144 else{
2145 slot_active = CODEC_AUDIOFRAME_SLOT_02;
2146 }
2147 SAIx_In_Init(haudio, SAI_MODEMASTER_RX, slot_active, AudioFreq);
2148
2149 /* wm8994 codec initialization */
2150 ercd = wm8994_Reset(haudio);
2151 if(ercd == E_OK){
2152 /* Initialize the codec internal registers */
2153 wm8994_Init(haudio, InputDevice, haudio->AudioInVolume, AudioFreq);
2154 }
2155 }
2156 return ercd;
2157}
2158
2159#ifndef TOPPERS_STM32F769_DISCOVERY
2160/*
2161 * オーディオ入出力初期化設定
2162 * param1: STAUDIOハンドラ
2163 * param2: 入力デバイス設定
2164 * param3: 出力デバイス設定
2165 * param4: オーディオ周波数値
2166 * param5: BitRes
2167 * param6: チャネル番号
2168 * return: E_OKで正常設定
2169 */
2170ER
2171staudio_in_out_init(STAUDIO_Handle_t *haudio, uint16_t InputDevice, uint16_t OutputDevice, uint32_t AudioFreq, uint32_t BitRes, uint32_t ChnlNbr)
2172{
2173 ER ercd = E_OK;
2174 uint32_t slot_active;
2175
2176 haudio->InputDevice = InputDevice;
2177 /* Only INPUT_LINE_1, MICROPHONE_1, MICROPHONE_2 and MIC1&MIC2 inputs supported */
2178 if ((InputDevice != INPUT_DEVICE_INPUT_LINE_1) &&
2179 (InputDevice != INPUT_DEVICE_DIGITAL_MICROPHONE_1) &&
2180 (InputDevice != INPUT_DEVICE_DIGITAL_MICROPHONE_2) &&
2181 (InputDevice != INPUT_DEVICE_DIGITAL_MIC1_MIC2)){
2182 ercd = E_PAR;
2183 }
2184 else{
2185 /* PLL clock is set depending on the AudioFreq (44.1khz vs 48khz groups) */
2186 if(haudio->hsai == NULL){
2187 haudio->hsai = audio_init(haudio->saiid);
2188 }
2189 else{
2190 /* Disable SAI peripheral */
2191 audio_disable(haudio->hsai, AUDIO_IN_BLOCK);
2192 audio_end(haudio->hsai, AUDIO_IN_BLOCK);
2193 }
2194 audio_clockconfig(haudio->hsai, AudioFreq, NULL); /* Clock config is shared between AUDIO IN and OUT */
2195
2196 /* Configure SAI in master RX mode :
2197 * - SAI2_block_A in master RX mode
2198 * - SAI2_block_B in slave RX mode synchronous from SAI2_block_A
2199 */
2200 if(InputDevice == INPUT_DEVICE_DIGITAL_MICROPHONE_2){
2201 slot_active = CODEC_AUDIOFRAME_SLOT_13;
2202 }
2203 else if(InputDevice == INPUT_DEVICE_DIGITAL_MIC1_MIC2){
2204 slot_active = CODEC_AUDIOFRAME_SLOT_0123;
2205 }
2206 else{
2207 slot_active = CODEC_AUDIOFRAME_SLOT_02;
2208 }
2209 SAIx_In_Init(haudio, SAI_MODEMASTER_RX, slot_active, AudioFreq);
2210
2211 /* wm8994 codec initialization */
2212 ercd = wm8994_Reset(haudio);
2213 if(ercd == E_OK){
2214 /* Initialize the codec internal registers */
2215 wm8994_Init(haudio, InputDevice | OutputDevice, haudio->AudioInVolume, AudioFreq);
2216 }
2217 }
2218 return ercd;
2219}
2220#endif
2221
2222/*
2223 * オーディオ録音開始設定
2224 * param1: STAUDIOハンドラ
2225 * param2: 入力バッファポインタ
2226 * param3: 入力バッファサイズ
2227 * return: E_OKで正常設定
2228 */
2229ER
2230staudio_in_record(STAUDIO_Handle_t *haudio, uint16_t* pbuf, uint32_t size)
2231{
2232 AUDIO_Handle_t *hsai = haudio->hsai;
2233 ER ercd = E_OK;
2234
2235#ifdef TOPPERS_STM32F769_DISCOVERY
2236 if(haudio->InputDevice == INPUT_DEVICE_DIGITAL_MIC){
2237 hAudioIn.pRecBuf = pbuf;
2238 hAudioIn.RecSize = size;
2239 /* Reset Application Buffer Trigger */
2240 AppBuffTrigger = 0;
2241 AppBuffHalf = 0;
2242
2243 if(AudioIn_ChannelNumber > 2){
2244 /* Call the Media layer start function for buttom right channel */
2245 if(E_OK != (ercd = dfsdm_filterRegularStart(&hAudioInButtomRightFilter, pScratchBuff[2], ScratchSize))){
2246 return ercd;
2247 }
2248 /* Call the Media layer start function for buttom left channel */
2249 if(E_OK != (ercd = dfsdm_filterRegularStart(&hAudioInButtomLeftFilter, pScratchBuff[3], ScratchSize))){
2250 return ercd;
2251 }
2252 }
2253 /* Call the Media layer start function for top right channel */
2254 if(E_OK != (ercd = dfsdm_filterRegularStart(&hAudioInTopRightFilter, pScratchBuff[0], ScratchSize))){
2255 return ercd;
2256 }
2257 /* Call the Media layer start function for top left channel */
2258 if(E_OK != (ercd = dfsdm_filterRegularStart(&hAudioInTopLeftFilter, pScratchBuff[1], ScratchSize))){
2259 return ercd;
2260 }
2261 return ercd;
2262 }
2263#endif
2264 /* Start the process receive DMA */
2265 hsai->recevcallback = (void (*)(AUDIO_Handle_t *hsai))haudio->audio_fullin_func;
2266 hsai->recevhalfcallback = (void (*)(AUDIO_Handle_t *hsai))haudio->audio_halfin_func;
2267 hsai->errorcallback = haudio->audio_error_func;
2268 ercd = audio_receive(hsai, (uint8_t*)pbuf, size);
2269 return ercd;
2270}
2271
2272/*
2273 * オーディオ録音停止設定
2274 * param1: STAUDIOハンドラ
2275 * param2: 終了オプション
2276 * return: E_OKで正常設定
2277 */
2278ER
2279staudio_in_stop(STAUDIO_Handle_t *haudio, uint32_t Option)
2280{
2281#ifdef TOPPERS_STM32F769_DISCOVERY
2282 ER ercd = E_OK;
2283 if(haudio->InputDevice == INPUT_DEVICE_DIGITAL_MIC){
2284 AppBuffTrigger = 0;
2285 AppBuffHalf = 0;
2286 if(AudioIn_ChannelNumber > 2){
2287 /* Call the Media layer stop function for buttom right channel */
2288 if(E_OK != (ercd = dfsdm_filterRegularStop(&hAudioInButtomRightFilter))){
2289 return ercd;
2290 }
2291 /* Call the Media layer stop function for buttom left channel */
2292 if(E_OK != (ercd = dfsdm_filterRegularStop(&hAudioInButtomLeftFilter))){
2293 return ercd;
2294 }
2295 }
2296 /* Call the Media layer stop function for top right channel */
2297 if(E_OK != (ercd = dfsdm_filterRegularStop(&hAudioInTopRightFilter))){
2298 return ercd;
2299 }
2300 /* Call the Media layer stop function for top left channel */
2301 if(E_OK != (ercd = dfsdm_filterRegularStop(&hAudioInTopLeftFilter))){
2302 return ercd;
2303 }
2304 return ercd;
2305 }
2306#endif
2307 /* Call the Media layer stop function */
2308 audio_dmastop(haudio->hsai, AUDIO_IN_BLOCK);
2309
2310 /* Call Audio Codec Stop function */
2311 if(wm8994_Stop(haudio, Option) != 0){
2312 return E_SYS;
2313 }
2314 else{
2315 if(Option == CODEC_PDWN_HW){
2316 /* Wait at least 100us */
2317 dly_tsk(1);
2318 }
2319 /* Return AUDIO_OK when all operations are correctly done */
2320 return E_OK;
2321 }
2322}
2323
2324/*
2325 * オーディオ録音PAUSE設定
2326 * param1: STAUDIOハンドラ
2327 * return: E_OKで正常設定
2328 */
2329ER
2330staudio_in_pause(STAUDIO_Handle_t *haudio)
2331{
2332#ifdef TOPPERS_STM32F769_DISCOVERY
2333 ER ercd = E_OK;
2334 if(haudio->InputDevice == INPUT_DEVICE_DIGITAL_MIC){
2335 if(AudioIn_ChannelNumber > 2){
2336 /* Call the Media layer stop function */
2337 if(E_OK != (ercd = dfsdm_filterRegularStop(&hAudioInButtomRightFilter))){
2338 return ercd;
2339 }
2340 /* Call the Media layer stop function */
2341 if(E_OK != (ercd = dfsdm_filterRegularStop(&hAudioInButtomLeftFilter))){
2342 return ercd;
2343 }
2344 }
2345 /* Call the Media layer stop function */
2346 if(E_OK != (ercd = dfsdm_filterRegularStop(&hAudioInTopRightFilter))){
2347 return ercd;
2348 }
2349 /* Call the Media layer stop function */
2350 if(E_OK != (ercd = dfsdm_filterRegularStop(&hAudioInTopLeftFilter))){
2351 return ercd;
2352 }
2353 /* Return AUDIO_OK when all operations are correctly done */
2354 return ercd;
2355 }
2356#endif
2357 /* Call the Media layer pause function */
2358 return audio_dmapause(haudio->hsai, AUDIO_IN_BLOCK);
2359}
2360
2361/*
2362 * オーディオ録音RESUME設定
2363 * param1: STAUDIOハンドラ
2364 * return: E_OKで正常設定
2365 */
2366ER
2367staudio_in_resume(STAUDIO_Handle_t *haudio)
2368{
2369#ifdef TOPPERS_STM32F769_DISCOVERY
2370 ER ercd = E_OK;
2371 if(haudio->InputDevice == INPUT_DEVICE_DIGITAL_MIC){
2372 if(AudioIn_ChannelNumber > 2){
2373 /* Call the Media layer start function for buttom right channel */
2374 if(E_OK != (ercd = dfsdm_filterRegularStart(&hAudioInButtomRightFilter, pScratchBuff[2], ScratchSize))){
2375 return ercd;
2376 }
2377 /* Call the Media layer start function for buttom left channel */
2378 if(E_OK != (ercd = dfsdm_filterRegularStart(&hAudioInButtomLeftFilter, pScratchBuff[3], ScratchSize))){
2379 return ercd;
2380 }
2381 }
2382 /* Call the Media layer start function for top right channel */
2383 if(E_OK != (ercd = dfsdm_filterRegularStart(&hAudioInTopRightFilter, pScratchBuff[0], ScratchSize))){
2384 return ercd;
2385 }
2386 /* Call the Media layer start function for top left channel */
2387 if(E_OK != (ercd = dfsdm_filterRegularStart(&hAudioInTopLeftFilter, pScratchBuff[1], ScratchSize))){
2388 return ercd;
2389 }
2390 /* Return AUDIO_OK when all operations are correctly done */
2391 return ercd;
2392 }
2393#endif
2394 /* Call the Media layer pause/resume function */
2395 return audio_dmaresume(haudio->hsai, AUDIO_IN_BLOCK);
2396}
2397
2398/*
2399 * オーディオ録音終了設定
2400 * param1: STAUDIOハンドラ
2401 */
2402void
2403staudio_in_deinit(STAUDIO_Handle_t *haudio)
2404{
2405#ifdef TOPPERS_STM32F769_DISCOVERY
2406 if(haudio->InputDevice == INPUT_DEVICE_DIGITAL_MIC){
2407 /* MSP filters initialization */
2408 DFSDMx_FilterMspDeInit();
2409 DFSDMx_DeInit();
2410 }
2411 else
2412#endif
2413 SAIx_In_DeInit(haudio);
2414}
2415
2416#ifndef TOPPERS_STM32F769_DISCOVERY
2417/*
2418 * オーディオ録音ボリューム設定
2419 * param1: STAUDIOハンドラ
2420 * param2: ボリューム値(0..100)
2421 * return: E_OKで正常設定
2422 */
2423ER
2424staudio_in_setvolume(STAUDIO_Handle_t *haudio, uint8_t Volume)
2425{
2426 /* Call the codec volume control function with converted volume value */
2427 if(wm8994_SetVolume(haudio, Volume) != 0){
2428 return E_SYS;
2429 }
2430 else{
2431 /* Set the Global variable AudioInVolume */
2432 haudio->AudioInVolume = Volume;
2433 /* Return AUDIO_OK when all operations are correctly done */
2434 return E_OK;
2435 }
2436}
2437
2438
2439#else /* TOPPERS_STM32F769_DISCOVERY */
2440/*
2441 * オーディオ録音スクラッチ領域E設定
2442 * param1: スクラッチ領域へのポインタ
2443 * param2: スクラッチ領域サイズ
2444 * return: E_OKで正常設定
2445 */
2446ER
2447BSP_AUDIO_IN_AllocScratch(int32_t *pScratch, uint32_t size)
2448{
2449 uint32_t idx;
2450
2451 ScratchSize = (size / AudioIn_ChannelNumber);
2452
2453 /* copy scratch pointers */
2454 for (idx = 0; idx < AudioIn_ChannelNumber; idx++){
2455 pScratchBuff[idx] = (int32_t *)(pScratch + (idx * ScratchSize));
2456 }
2457 /* Return AUDIO_OK */
2458 return E_OK;
2459}
2460
2461/*
2462 * オーディオチャネル番号取り出し
2463 * return: チャネル番号
2464 */
2465uint8_t BSP_AUDIO_IN_GetChannelNumber(void)
2466{
2467 return AudioIn_ChannelNumber;
2468}
2469
2470#endif
2471
Note: See TracBrowser for help on using the repository browser.