1 /* 2 * Copyright (c) 2015 - 2020, Nordic Semiconductor ASA 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are met: 7 * 8 * 1. Redistributions of source code must retain the above copyright notice, this 9 * list of conditions and the following disclaimer. 10 * 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 15 * 3. Neither the name of the copyright holder nor the names of its 16 * contributors may be used to endorse or promote products derived from this 17 * software without specific prior written permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 23 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 * POSSIBILITY OF SUCH DAMAGE. 30 */ 31 32 #ifndef NRFX_I2S_H__ 33 #define NRFX_I2S_H__ 34 35 #include <nrfx.h> 36 #include <hal/nrf_i2s.h> 37 38 #ifdef __cplusplus 39 extern "C" { 40 #endif 41 42 /** 43 * @defgroup nrfx_i2s I2S driver 44 * @{ 45 * @ingroup nrf_i2s 46 * @brief Inter-IC Sound (I2S) peripheral driver. 47 */ 48 49 /** 50 * @brief This value can be provided instead of a pin number for the signals 51 * SDOUT, SDIN, and MCK to specify that a given signal is not used 52 * and therefore does not need to be connected to a pin. 53 */ 54 #define NRFX_I2S_PIN_NOT_USED 0xFF 55 56 /** @brief I2S driver configuration structure. */ 57 typedef struct 58 { 59 uint8_t sck_pin; ///< SCK pin number. 60 uint8_t lrck_pin; ///< LRCK pin number. 61 uint8_t mck_pin; ///< MCK pin number. 62 /**< Optional. Use @ref NRFX_I2S_PIN_NOT_USED 63 * if this signal is not needed. */ 64 uint8_t sdout_pin; ///< SDOUT pin number. 65 /**< Optional. Use @ref NRFX_I2S_PIN_NOT_USED 66 * if this signal is not needed. */ 67 uint8_t sdin_pin; ///< SDIN pin number. 68 /**< Optional. Use @ref NRFX_I2S_PIN_NOT_USED 69 * if this signal is not needed. */ 70 uint8_t irq_priority; ///< Interrupt priority. 71 72 nrf_i2s_mode_t mode; ///< Mode of operation. 73 nrf_i2s_format_t format; ///< Frame format. 74 nrf_i2s_align_t alignment; ///< Alignment of sample within a frame. 75 nrf_i2s_swidth_t sample_width; ///< Sample width. 76 nrf_i2s_channels_t channels; ///< Enabled channels. 77 nrf_i2s_mck_t mck_setup; ///< Master clock setup. 78 nrf_i2s_ratio_t ratio; ///< MCK/LRCK ratio. 79 #if NRF_I2S_HAS_CLKCONFIG 80 nrf_i2s_clksrc_t clksrc; ///< Clock source selection. 81 bool enable_bypass; ///< Bypass clock generator. MCK will be equal to source input. 82 #endif 83 } nrfx_i2s_config_t; 84 85 /** @brief I2S driver buffers structure. */ 86 typedef struct 87 { 88 uint32_t * p_rx_buffer; ///< Pointer to the buffer for received data. 89 uint32_t const * p_tx_buffer; ///< Pointer to the buffer with data to be sent. 90 } nrfx_i2s_buffers_t; 91 92 #if NRF_I2S_HAS_CLKCONFIG || defined(__NRFX_DOXYGEN__) 93 /** @brief I2S additional clock source configuration. */ 94 #define NRF_I2S_DEFAULT_EXTENDED_CLKSRC_CONFIG \ 95 .clksrc = NRF_I2S_CLKSRC_PCLK32M, \ 96 .enable_bypass = false, 97 #else 98 #define NRF_I2S_DEFAULT_EXTENDED_CLKSRC_CONFIG 99 #endif 100 /** 101 * @brief I2S driver default configuration. 102 * 103 * This configuration sets up I2S with the following options: 104 * - master mode 105 * - i2s data format 106 * - left alignment 107 * - sample width 16 bit 108 * - left channel enabled 109 * - MCK frequency 4 MHz 110 * - LRCK frequency 125 kHz 111 * 112 * @param[in] _pin_sck SCK pin number. 113 * @param[in] _pin_lrck LRCK pin number. 114 * @param[in] _pin_mck MCK pin number. 115 * @param[in] _pin_sdout SDOUT pin number. 116 * @param[in] _pin_sdin SDIN pin number. 117 */ 118 #define NRFX_I2S_DEFAULT_CONFIG(_pin_sck, _pin_lrck, _pin_mck, _pin_sdout, _pin_sdin) \ 119 { \ 120 .sck_pin = _pin_sck, \ 121 .lrck_pin = _pin_lrck, \ 122 .mck_pin = _pin_mck, \ 123 .sdout_pin = _pin_sdout, \ 124 .sdin_pin = _pin_sdin, \ 125 .irq_priority = NRFX_I2S_DEFAULT_CONFIG_IRQ_PRIORITY, \ 126 .mode = NRF_I2S_MODE_MASTER, \ 127 .format = NRF_I2S_FORMAT_I2S, \ 128 .alignment = NRF_I2S_ALIGN_LEFT, \ 129 .sample_width = NRF_I2S_SWIDTH_16BIT, \ 130 .channels = NRF_I2S_CHANNELS_LEFT, \ 131 .mck_setup = NRF_I2S_MCK_32MDIV8, \ 132 .ratio = NRF_I2S_RATIO_32X, \ 133 NRF_I2S_DEFAULT_EXTENDED_CLKSRC_CONFIG \ 134 } 135 136 #define NRFX_I2S_STATUS_NEXT_BUFFERS_NEEDED (1UL << 0) 137 /**< The application must provide buffers that are to be used in the next 138 * part of the transfer. A call to @ref nrfx_i2s_next_buffers_set must 139 * be done before the currently used buffers are completely processed 140 * (that is, the time remaining for supplying the next buffers depends on 141 * the used size of the buffers). */ 142 143 #define NRFX_I2S_STATUS_TRANSFER_STOPPED (1UL << 1) 144 /**< The I2S peripheral has been stopped and all buffers that were passed 145 * to the driver have been released. */ 146 147 /** 148 * @brief I2S driver data handler type. 149 * 150 * A data handling function of this type must be specified during the initialization 151 * of the driver. The driver will call this function when it finishes using 152 * buffers passed to it by the application, and when it needs to be provided 153 * with buffers for the next part of the transfer. 154 * 155 * @note The @c p_released pointer passed to this function is temporary and 156 * will be invalid after the function returns, hence it cannot be stored 157 * and used later. If needed, the pointed content (that is, buffers pointers) 158 * must be copied instead. 159 * 160 * @param[in] p_released Pointer to a structure with pointers to buffers 161 * passed previously to the driver that will no longer 162 * be accessed by it (they can be now safely released or 163 * used for another purpose, in particular for a next 164 * part of the transfer). 165 * This pointer will be NULL if the application did not 166 * supply the buffers for the next part of the transfer 167 * (via a call to @ref nrfx_i2s_next_buffers_set) since 168 * the previous time the data handler signaled such need. 169 * This means that data corruption occurred (the previous 170 * buffers are used for the second time) and no buffers 171 * can be released at the moment. 172 * Both pointers in this structure are NULL when the 173 * handler is called for the first time after a transfer 174 * is started, because no data has been transferred yet 175 * at this point. In all successive calls, the pointers 176 * specify what has been sent (TX) and what has been 177 * received (RX) in the part of the transfer that has 178 * just been completed (provided that a given direction 179 * is enabled, see @ref nrfx_i2s_start). 180 * @note Since the peripheral is stopped asynchronously, 181 * buffers that are released after the call to 182 * @ref nrfx_i2s_stop are not used entirely. 183 * In this case, only a part (if any) of the TX 184 * buffer has been actually transmitted and only 185 * a part (if any) of the RX buffer is filled with 186 * received data. 187 * @param[in] status Bit field describing the current status of the transfer. 188 * It can be 0 or a combination of the following flags: 189 * - @ref NRFX_I2S_STATUS_NEXT_BUFFERS_NEEDED 190 * - @ref NRFX_I2S_STATUS_TRANSFER_STOPPED 191 */ 192 typedef void (* nrfx_i2s_data_handler_t)(nrfx_i2s_buffers_t const * p_released, 193 uint32_t status); 194 195 /** 196 * @brief Function for initializing the I2S driver. 197 * 198 * @param[in] p_config Pointer to the structure with the initial configuration. 199 * @param[in] handler Data handler provided by the user. Must not be NULL. 200 * 201 * @retval NRFX_SUCCESS Initialization was successful. 202 * @retval NRFX_ERROR_INVALID_STATE The driver was already initialized. 203 * @retval NRFX_ERROR_INVALID_PARAM The requested combination of configuration 204 * options is not allowed by the I2S peripheral. 205 */ 206 nrfx_err_t nrfx_i2s_init(nrfx_i2s_config_t const * p_config, 207 nrfx_i2s_data_handler_t handler); 208 209 /** @brief Function for uninitializing the I2S driver. */ 210 void nrfx_i2s_uninit(void); 211 212 /** 213 * @brief Function for starting the continuous I2S transfer. 214 * 215 * The I2S data transfer can be performed in one of three modes: RX (reception) 216 * only, TX (transmission) only, or in both directions simultaneously. 217 * The mode is selected by specifying a proper buffer for a given direction 218 * in the call to this function or by passing NULL instead if this direction 219 * is to be disabled. 220 * 221 * The length of the buffer (which is a common value for RX and TX if both 222 * directions are enabled) is specified in 32-bit words. One 32-bit memory 223 * word can either contain four 8-bit samples, two 16-bit samples, or one 224 * right-aligned 24-bit sample sign-extended to a 32-bit value. 225 * For a detailed memory mapping for different supported configurations, 226 * see the Product Specification. 227 * 228 * @note Peripherals using EasyDMA (including I2S) require the transfer buffers 229 * to be placed in the Data RAM region. If this condition is not met, 230 * this function will fail with the error code NRFX_ERROR_INVALID_ADDR. 231 * 232 * @param[in] p_initial_buffers Pointer to a structure specifying the buffers 233 * to be used in the initial part of the transfer 234 * (buffers for all consecutive parts are provided 235 * through the data handler). 236 * @param[in] buffer_size Size of the buffers (in 32-bit words). 237 * Must not be 0. 238 * @param[in] flags Transfer options (0 for default settings). 239 * Currently, no additional flags are available. 240 * 241 * @retval NRFX_SUCCESS The operation was successful. 242 * @retval NRFX_ERROR_INVALID_STATE Transfer was already started or 243 * the driver has not been initialized. 244 * @retval NRFX_ERROR_INVALID_ADDR The provided buffers are not placed 245 * in the Data RAM region. 246 */ 247 nrfx_err_t nrfx_i2s_start(nrfx_i2s_buffers_t const * p_initial_buffers, 248 uint16_t buffer_size, 249 uint8_t flags); 250 251 /** 252 * @brief Function for supplying the buffers to be used in the next part of 253 * the transfer. 254 * 255 * The application must call this function when the data handler receives 256 * @ref NRFX_I2S_STATUS_NEXT_BUFFERS_NEEDED in the @c status parameter. 257 * The call can be done immediately from the data handler function or later, 258 * but it has to be done before the I2S peripheral finishes processing the 259 * buffers supplied previously. Otherwise, data corruption will occur. 260 * 261 * @param[in] p_buffers Pointer to a structure specifying the buffers 262 * to be used in the upcoming part of the transfer. 263 * 264 * @retval NRFX_SUCCESS If the operation was successful. 265 * @retval NRFX_ERROR_INVALID_STATE If the buffers were already supplied or 266 * the peripheral is currently being stopped. 267 * 268 * @sa nrfx_i2s_data_handler_t 269 */ 270 nrfx_err_t nrfx_i2s_next_buffers_set(nrfx_i2s_buffers_t const * p_buffers); 271 272 /** @brief Function for stopping the I2S transfer. */ 273 void nrfx_i2s_stop(void); 274 275 /** @} */ 276 277 278 void nrfx_i2s_irq_handler(void); 279 280 281 #ifdef __cplusplus 282 } 283 #endif 284 285 #endif // NRFX_I2S_H__ 286 287