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