1 /***************************************************************************//**
2 * \file cy_pdm_pcm.c
3 * \version 2.30.1
4 *
5 * The source code file for the PDM_PCM driver.
6 *
7 ********************************************************************************
8 * \copyright
9 * Copyright 2016-2020 Cypress Semiconductor Corporation
10 * SPDX-License-Identifier: Apache-2.0
11 *
12 * Licensed under the Apache License, Version 2.0 (the "License");
13 * you may not use this file except in compliance with the License.
14 * You may obtain a copy of the License at
15 *
16 * http://www.apache.org/licenses/LICENSE-2.0
17 *
18 * Unless required by applicable law or agreed to in writing, software
19 * distributed under the License is distributed on an "AS IS" BASIS,
20 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
21 * See the License for the specific language governing permissions and
22 * limitations under the License.
23 *******************************************************************************/
24
25 #include "cy_device.h"
26
27 #if defined (AUDIOSS_PDM_PRESENT)
28
29 #include "cy_pdm_pcm.h"
30
31 /**
32 * \addtogroup group_pdm_pcm_functions
33 * \{
34 */
35
36 /******************************************************************************
37 * Function Name: Cy_PDM_PCM_Init
38 ***************************************************************************//**
39 *
40 * Initialize the PDM-PCM module
41 *
42 * \pre If the PDM-PCM module is initialized previously, the
43 * \ref Cy_PDM_PCM_DeInit() must be called before calling this function.
44 *
45 * \param base The pointer to the PDM-PCM instance address
46 * \param config The pointer to a configuration structure.
47 * \return error / status code. See \ref cy_en_pdm_pcm_status_t.
48 *
49 * An example of a configuration structure:
50 * \snippet pdm_pcm/snippet/main.c PDM_PCM Configuration
51 *
52 *******************************************************************************/
Cy_PDM_PCM_Init(PDM_Type * base,cy_stc_pdm_pcm_config_t const * config)53 cy_en_pdm_pcm_status_t Cy_PDM_PCM_Init(PDM_Type * base, cy_stc_pdm_pcm_config_t const * config)
54 {
55 cy_en_pdm_pcm_status_t ret = CY_PDM_PCM_BAD_PARAM;
56
57 if((NULL != base) && (NULL != config))
58 {
59 CY_ASSERT_L3(CY_PDM_PCM_IS_CLK_DIV_VALID(config->clkDiv));
60 CY_ASSERT_L3(CY_PDM_PCM_IS_CLK_DIV_VALID(config->mclkDiv));
61 CY_ASSERT_L3(CY_PDM_PCM_IS_CKO_CLOCK_DIV_VALID(config->ckoDiv));
62 CY_ASSERT_L3(CY_PDM_PCM_IS_SINC_RATE_VALID(config->sincDecRate));
63 CY_ASSERT_L3(CY_PDM_PCM_IS_GAIN_VALID(config->gainRight));
64 CY_ASSERT_L3(CY_PDM_PCM_IS_GAIN_VALID(config->gainLeft));
65 CY_ASSERT_L3(CY_PDM_PCM_IS_STEP_SEL_VALID(config->softMuteFineGain));
66 CY_ASSERT_L3(CY_PDM_PCM_IS_CH_SET_VALID(config->chanSelect));
67 CY_ASSERT_L3(CY_PDM_PCM_IS_S_CYCLES_VALID(config->softMuteCycles));
68 CY_ASSERT_L3(CY_PDM_PCM_IS_CKO_DELAY_VALID(config->ckoDelay));
69 CY_ASSERT_L3(CY_PDM_PCM_IS_HPF_GAIN_VALID(config->highPassFilterGain));
70 CY_ASSERT_L3(CY_PDM_PCM_IS_WORD_LEN_VALID(config->wordLen));
71 CY_ASSERT_L3(CY_PDM_PCM_IS_TRIG_LEVEL(config->rxFifoTriggerLevel, config->chanSelect));
72
73 ret = CY_PDM_PCM_SUCCESS;
74
75 PDM_PCM_CTL(base) &= (uint32_t) ~PDM_CTL_ENABLED_Msk; /* Disable the PDM_PCM block */
76
77 /* The clock setting */
78 PDM_PCM_CLOCK_CTL(base) = _VAL2FLD(PDM_CLOCK_CTL_CLK_CLOCK_DIV, config->clkDiv) |
79 _VAL2FLD(PDM_CLOCK_CTL_MCLKQ_CLOCK_DIV, config->mclkDiv) |
80 _VAL2FLD(PDM_CLOCK_CTL_CKO_CLOCK_DIV, config->ckoDiv) |
81 _VAL2FLD(PDM_CLOCK_CTL_SINC_RATE, config->sincDecRate);
82
83 /* Enable the PDM-PCM block */
84 PDM_PCM_CTL(base) = _VAL2FLD(PDM_CTL_PGA_R, config->gainRight) |
85 _VAL2FLD(PDM_CTL_PGA_L, config->gainLeft) |
86 _VAL2FLD(PDM_CTL_STEP_SEL, config->softMuteFineGain) |
87 _BOOL2FLD(PDM_CTL_SOFT_MUTE, config->softMuteEnable) |
88 PDM_CTL_ENABLED_Msk;
89
90 PDM_PCM_MODE_CTL(base) = _VAL2FLD(PDM_MODE_CTL_PCM_CH_SET, config->chanSelect) |
91 _BOOL2FLD(PDM_MODE_CTL_SWAP_LR, config->chanSwapEnable) |
92 _VAL2FLD(PDM_MODE_CTL_S_CYCLES, config->softMuteCycles) |
93 _VAL2FLD(PDM_MODE_CTL_CKO_DELAY, config->ckoDelay) |
94 _VAL2FLD(PDM_MODE_CTL_HPF_GAIN, config->highPassFilterGain) |
95 _BOOL2FLD(PDM_MODE_CTL_HPF_EN_N, config->highPassDisable);
96
97 PDM_PCM_DATA_CTL(base) = _VAL2FLD(PDM_DATA_CTL_WORD_LEN, config->wordLen) |
98 _BOOL2FLD(PDM_DATA_CTL_BIT_EXTENSION, config->signExtension);
99
100 PDM_PCM_RX_FIFO_CTL(base) = _VAL2FLD(PDM_RX_FIFO_CTL_TRIGGER_LEVEL, config->rxFifoTriggerLevel);
101
102 PDM_PCM_TR_CTL(base) = _BOOL2FLD(PDM_TR_CTL_RX_REQ_EN, config->dmaTriggerEnable);
103
104 Cy_PDM_PCM_SetInterruptMask(base, config->interruptMask);
105 }
106
107 return (ret);
108 }
109
110 /*******************************************************************************
111 * Function Name: Cy_PDM_PCM_DeInit
112 ****************************************************************************//**
113 *
114 * Uninitializes the PDM-PCM module.
115 *
116 * \param base The pointer to the PDM-PCM instance address.
117 *
118 *******************************************************************************/
Cy_PDM_PCM_DeInit(PDM_Type * base)119 void Cy_PDM_PCM_DeInit(PDM_Type * base)
120 {
121 PDM_PCM_CMD(base) = 0UL; /* Stop PDM-PCM operation */
122 PDM_PCM_INTR_MASK(base) = 0UL; /* Disable interrupts */
123 PDM_PCM_RX_FIFO_CTL(base) = 0UL;
124 PDM_PCM_TR_CTL(base) = 0UL;
125 PDM_PCM_DATA_CTL(base) = 0UL;
126 PDM_PCM_MODE_CTL(base) = CY_PDM_PCM_MODE_CTL_DEFAULT;
127 PDM_PCM_CTL(base) = CY_PDM_PCM_CTL_DEFAULT; /* Disable the PDM_PCM IP block */
128 PDM_PCM_CLOCK_CTL(base) = CY_PDM_PCM_CLOCK_CTL_DEFAULT; /* The default clock settings */
129 }
130
131 /******************************************************************************
132 * Function Name: Cy_PDM_PCM_SetGain
133 ***************************************************************************//**
134 *
135 * Sets the gain factor to the left or right channel.
136 *
137 * \param base
138 * The pointer to the PDM-PCM instance address.
139 *
140 * \param chan
141 * The channel selector for gain setting \ref cy_en_pdm_pcm_chan_select_t.
142 *
143 * \param gain
144 * Gain for the selected channel \ref cy_en_pdm_pcm_gain_t.
145 *
146 ******************************************************************************/
Cy_PDM_PCM_SetGain(PDM_Type * base,cy_en_pdm_pcm_chan_select_t chan,cy_en_pdm_pcm_gain_t gain)147 void Cy_PDM_PCM_SetGain(PDM_Type * base, cy_en_pdm_pcm_chan_select_t chan, cy_en_pdm_pcm_gain_t gain)
148 {
149 CY_ASSERT_L3(CY_PDM_PCM_IS_CHAN_VALID(chan));
150 CY_ASSERT_L3(CY_PDM_PCM_IS_GAIN_VALID(gain));
151
152 if (chan == CY_PDM_PCM_CHAN_LEFT)
153 {
154 CY_REG32_CLR_SET(PDM_PCM_CTL(base), PDM_CTL_PGA_L, ((uint32_t) gain));
155 }
156 else
157 {
158 CY_REG32_CLR_SET(PDM_PCM_CTL(base), PDM_CTL_PGA_R, ((uint32_t) gain));
159 }
160 }
161
162 /******************************************************************************
163 * Function Name: Cy_PDM_PCM_GetGain
164 ***************************************************************************//**
165 *
166 * Retrieves the current gain factor of the left or right channel.
167 *
168 * \param base
169 * The pointer to the PDM-PCM instance address.
170 *
171 * \param chan
172 * The channel selector for gain setting \ref cy_en_pdm_pcm_chan_select_t.
173 *
174 * \return
175 * Gain of the selected channel \ref cy_en_pdm_pcm_gain_t.
176 *
177 ******************************************************************************/
Cy_PDM_PCM_GetGain(PDM_Type const * base,cy_en_pdm_pcm_chan_select_t chan)178 cy_en_pdm_pcm_gain_t Cy_PDM_PCM_GetGain(PDM_Type const * base, cy_en_pdm_pcm_chan_select_t chan)
179 {
180 cy_en_pdm_pcm_gain_t ret;
181
182 CY_ASSERT_L3(CY_PDM_PCM_IS_CHAN_VALID(chan));
183
184 if (chan == CY_PDM_PCM_CHAN_LEFT)
185 {
186 ret = (cy_en_pdm_pcm_gain_t) ((uint32_t)_FLD2VAL(PDM_CTL_PGA_L, PDM_PCM_CTL(base)));
187 }
188 else
189 {
190 ret = (cy_en_pdm_pcm_gain_t) ((uint32_t)_FLD2VAL(PDM_CTL_PGA_R, PDM_PCM_CTL(base)));
191 }
192
193 return (ret);
194 }
195
196
197 /*******************************************************************************
198 * Function Name: Cy_PDM_PCM_DeepSleepCallback
199 ****************************************************************************//**
200 *
201 * This is an example callback function that can be used at the application layer to
202 * manage the PDM-PCM operation before entering and after exiting Deep Sleep mode.
203 *
204 * \param callbackParams
205 * The structure with the syspm callback parameters,
206 * see \ref cy_stc_syspm_callback_params_t.
207 *
208 * \param mode
209 * Callback mode, see \ref cy_en_syspm_callback_mode_t
210 *
211 * \return
212 * syspm return status, see \ref cy_en_syspm_status_t
213 *
214 *******************************************************************************/
Cy_PDM_PCM_DeepSleepCallback(cy_stc_syspm_callback_params_t const * callbackParams,cy_en_syspm_callback_mode_t mode)215 cy_en_syspm_status_t Cy_PDM_PCM_DeepSleepCallback(cy_stc_syspm_callback_params_t const * callbackParams, cy_en_syspm_callback_mode_t mode)
216 {
217 cy_en_syspm_status_t ret = CY_SYSPM_SUCCESS;
218
219 switch(mode)
220 {
221 case CY_SYSPM_CHECK_READY:
222 case CY_SYSPM_CHECK_FAIL:
223 break;
224
225 case CY_SYSPM_BEFORE_TRANSITION:
226 Cy_PDM_PCM_Disable((PDM_Type*) callbackParams->base); /* Stop PDM-PCM operation */
227 /* Unload FIFO to not lose any data (if needed) */
228 break;
229
230 case CY_SYSPM_AFTER_TRANSITION:
231 Cy_PDM_PCM_ClearFifo((PDM_Type*) callbackParams->base); /* Clear FIFO */
232 Cy_PDM_PCM_Enable((PDM_Type*) callbackParams->base); /* Start PDM-PCM operation */
233 break;
234
235 default:
236 ret = CY_SYSPM_FAIL;
237 break;
238 }
239
240 return(ret);
241 }
242
243 /** \} group_pdm_pcm_functions */
244
245
246 #endif /* (defined (AUDIOSS_PDM_PRESENT) || defined(CY_DOXYGEN)) */
247
248 /* [] END OF FILE */
249