imxrt1050/imxrt1050-evkb/source/pv_audio_rec.c
Go to the documentation of this file.
1 /*
2  Copyright 2020-2021 Picovoice Inc.
3 
4  You may not use this file except in compliance with the license. A copy of the license is located in the "LICENSE"
5  file accompanying this source.
6 
7  Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
8  an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
9  specific language governing permissions and limitations under the License.
10 */
11 
12 #include <stdbool.h>
13 #include <stdint.h>
14 #include <stdlib.h>
15 
16 #include "board.h"
17 #include "clock_config.h"
18 #include "fsl_codec_adapter.h"
19 #include "fsl_codec_common.h"
20 #include "fsl_dmamux.h"
21 #include "fsl_sai_edma.h"
22 #include "fsl_wm8960.h"
23 
24 #include "picovoice.h"
25 
26 #define PV_SAI (SAI1)
27 #define PV_SAI_CHANNEL (0)
28 #define PV_SAI_IRQ (SAI1_IRQn)
29 #define PV_SAITxIRQHandler (SAI1_IRQHandler)
30 #define PV_SAI_TX_SYNC_MODE (kSAI_ModeAsync)
31 #define PV_SAI_RX_SYNC_MODE (kSAI_ModeSync)
32 #define PV_SAI_MCLK_OUTPUT (true)
33 #define PV_SAI_MASTER_SLAVE (kSAI_Master)
34 #define PV_SAI1_CLOCK_SOURCE_SELECT (2U)
35 #define PV_SAI1_CLOCK_SOURCE_PRE_DIVIDER (0U)
36 #define PV_SAI1_CLOCK_SOURCE_DIVIDER (63U)
37 #define PV_SAI_CLK_FREQ \
38  (CLOCK_GetFreq(kCLOCK_AudioPllClk) / (PV_SAI1_CLOCK_SOURCE_DIVIDER + 1U) / \
39  (PV_SAI1_CLOCK_SOURCE_PRE_DIVIDER + 1U))
40 #define PV_SAI_TX_IRQ (SAI1_IRQn)
41 #define PV_SAI_RX_IRQ (SAI1_IRQn)
42 
43 #define PV_I2C (LPI2C1)
44 #define PV_LPI2C_CLOCK_SOURCE_SELECT (0U)
45 #define PV_LPI2C_CLOCK_SOURCE_DIVIDER (5U)
46 #define PV_I2C_CLK_FREQ ((CLOCK_GetFreq(kCLOCK_Usb1PllClk) / 8) / (PV_LPI2C_CLOCK_SOURCE_DIVIDER + 1U))
47 
48 #define PV_AUDIO_REC_AUDIO_FREQUENCY (kSAI_SampleRate16KHz)
49 #define PV_AUDIO_REC_CHANNEL_NUMBER (2U)
50 #define PV_AUDIO_REC_RECORD_BUFFER_SIZE (512U)
51 #define PV_AUDIO_REC_BIT_WIDTH (kSAI_WordWidth16bits)
52 #define PV_AUDIO_REC_MASTER_CLOCK (PV_SAI_CLK_FREQ)
53 #define AUDIO_IN_PCM_BUFFER_SIZE_INT16 ((uint32_t)(PV_AUDIO_REC_AUDIO_FREQUENCY / 1000 \
54  * PV_AUDIO_REC_CHANNEL_NUMBER))
55 #define AUDIO_IN_PCM_BUFFER_SIZE_INT8 (2 * AUDIO_IN_PCM_BUFFER_SIZE_INT16)
56 #define PV_AUDIO_REC_RECORD_BUFFER_NUMBER (2U)
57 
58 #define PV_DMA (DMA0)
59 #define PV_DMAMUX (DMAMUX)
60 #define PV_TX_EDMA_CHANNEL (0U)
61 #define PV_RX_EDMA_CHANNEL (1U)
62 #define PV_SAI_TX_SOURCE (kDmaRequestMuxSai1Tx)
63 #define PV_SAI_RX_SOURCE (kDmaRequestMuxSai1Rx)
64 
67 
70 
74 static edma_config_t dmaConfig = {0};
76 
77 static bool rx_error = false;
78 static int32_t last_read_index = -1;
79 volatile static int32_t read_index = 1;
80 volatile static int32_t write_index = 0;
81 volatile static int32_t buffer_index = 0;
82 
83 struct {
84  uint32_t channel_number;
85  uint32_t audio_frequency;
89 } pv_audio_rec;
90 
91 static void rx_callback(I2S_Type *base, sai_edma_handle_t *handle, status_t status, void *userData)
92 {
93  if (kStatus_SAI_RxError == status) {
94  rx_error = true;
95  } else {
96  int16_t *record_pcm_buffer_int16 = (int16_t*) record_pcm_buffer;
97  for (uint32_t i = 0; i < (AUDIO_IN_PCM_BUFFER_SIZE_INT16 / 2); i++) {
98  ping_pong_buffer[write_index][buffer_index++] = record_pcm_buffer_int16[i * 2 + 1];
99  }
102  write_index = 1 - write_index;
103  buffer_index = 0;
104  }
105  if (pv_audio_rec.is_recording) {
109  }
110  }
111 }
112 
113 static void BOARD_EnableSaiMclkOutput(bool enable)
114 {
115  if (enable)
116  {
118  }
119  else
120  {
122  }
123 }
124 
126 
127  wm8960_config_t wm8960Config = {
129  .route = kWM8960_RouteRecord,
130  .rightInputSource = kWM8960_InputDifferentialMicInput2,
131  .playSource = kWM8960_PlaySourceDAC,
132  .slaveAddress = WM8960_I2C_ADDR,
133  .bus = kWM8960_BusI2S,
134  .format = {.mclk_HZ = 6144000U, .sampleRate = kWM8960_AudioSampleRate16KHz, .bitWidth = kWM8960_AudioBitWidth16bit},
135  .master_slave = false,
136  };
137  codec_config_t boardCodecConfig = {.codecDevType = kCODEC_WM8960, .codecDevConfig = &wm8960Config};
138 
139  const clock_audio_pll_config_t audioPllConfig = {
140  .loopDivider = 32,
141  .postDivider = 1,
142  .numerator = 77,
143  .denominator = 100,
144  };
145 
146  CLOCK_InitAudioPll(&audioPllConfig);
147 
157 
161 
162  SAI_Init(PV_SAI);
174 
175  if (!CODEC_Init(&codecHandle, &boardCodecConfig)) {
177  }
178 
179  pv_audio_rec.channel_number = PV_AUDIO_REC_CHANNEL_NUMBER;
180  pv_audio_rec.audio_frequency = PV_AUDIO_REC_AUDIO_FREQUENCY;
181  pv_audio_rec.record_buffer_size = PV_AUDIO_REC_RECORD_BUFFER_SIZE;
182  pv_audio_rec.record_pcm_buffer = record_pcm_buffer;
183  return PV_STATUS_SUCCESS;
184 }
185 
190  pv_audio_rec.is_recording = true;
191  return PV_STATUS_SUCCESS;
192  } else {
194  }
195 }
196 
198  pv_audio_rec.is_recording = false;
199  return PV_STATUS_SUCCESS;
200 }
201 
202 const int16_t *pv_audio_rec_get_new_buffer(void) {
203  if (read_index == -1) {
204  return NULL;
205  }
206 
207  if (last_read_index == read_index) {
208  return NULL;
209  }
210 
212 
214 }
215 
217 }
218 
_sai_transfer::data
uint8_t * data
Definition: fsl_sai.h:416
PV_SAI_TX_SYNC_MODE
#define PV_SAI_TX_SYNC_MODE
Definition: imxrt1050/imxrt1050-evkb/source/pv_audio_rec.c:30
dmaRxHandle
static edma_handle_t dmaRxHandle
Definition: imxrt1050/imxrt1050-evkb/source/pv_audio_rec.c:71
fsl_sai_edma.h
is_recording
bool is_recording
Definition: imxrt1050/imxrt1050-evkb/source/pv_audio_rec.c:88
_edma_handle
eDMA transfer handle structure
Definition: fsl_edma.h:243
PV_SAI
#define PV_SAI
Definition: imxrt1050/imxrt1050-evkb/source/pv_audio_rec.c:26
pv_audio_rec_start
pv_status_t pv_audio_rec_start(void)
Definition: imxrt1050/imxrt1050-evkb/source/pv_audio_rec.c:186
ping_pong_buffer
static int16_t ping_pong_buffer[2][PV_AUDIO_REC_RECORD_BUFFER_SIZE]
Definition: psoc062s2/src/pv_audio_rec.c:49
clock_config.h
WM8960_I2C_ADDR
#define WM8960_I2C_ADDR
WM8960 I2C address.
Definition: fsl_wm8960.h:196
NULL
#define NULL
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/extras/speex_resampler/thirdparty/resample.c:92
DMAMUX_EnableChannel
static void DMAMUX_EnableChannel(DMAMUX_Type *base, uint32_t channel)
Enables the DMAMUX channel.
Definition: fsl_dmamux.h:75
_codec_config
Initialize structure of the codec.
Definition: fsl_codec_common.h:221
PV_STATUS_INVALID_STATE
@ PV_STATUS_INVALID_STATE
Definition: porcupine/include/picovoice.h:40
I2S_Type
Definition: MIMXRT1052.h:19867
PV_SAI_MASTER_SLAVE
#define PV_SAI_MASTER_SLAVE
Definition: imxrt1050/imxrt1050-evkb/source/pv_audio_rec.c:33
PV_SAI1_CLOCK_SOURCE_SELECT
#define PV_SAI1_CLOCK_SOURCE_SELECT
Definition: imxrt1050/imxrt1050-evkb/source/pv_audio_rec.c:34
kCODEC_WM8960
@ kCODEC_WM8960
Definition: fsl_codec_adapter.h:26
PV_AUDIO_REC_MASTER_CLOCK
#define PV_AUDIO_REC_MASTER_CLOCK
Definition: imxrt1050/imxrt1050-evkb/source/pv_audio_rec.c:52
_sai_transfer::dataSize
size_t dataSize
Definition: fsl_sai.h:417
SAI_TransferRxSetConfigEDMA
void SAI_TransferRxSetConfigEDMA(I2S_Type *base, sai_edma_handle_t *handle, sai_transceiver_t *saiConfig)
Configures the SAI Rx.
Definition: fsl_sai_edma.c:358
PV_SAI_RX_SOURCE
#define PV_SAI_RX_SOURCE
Definition: imxrt1050/imxrt1050-evkb/source/pv_audio_rec.c:63
sai_edma_handle
SAI DMA transfer handle, users should not touch the content of the handle.
Definition: fsl_sai_edma.h:34
pv_audio_rec
struct @364 pv_audio_rec
pv_audio_rec_get_new_buffer
const int16_t * pv_audio_rec_get_new_buffer(void)
Definition: imxrt1050/imxrt1050-evkb/source/pv_audio_rec.c:202
PV_AUDIO_REC_RECORD_BUFFER_SIZE
#define PV_AUDIO_REC_RECORD_BUFFER_SIZE
Definition: imxrt1050/imxrt1050-evkb/source/pv_audio_rec.c:50
PV_AUDIO_REC_RECORD_BUFFER_NUMBER
#define PV_AUDIO_REC_RECORD_BUFFER_NUMBER
Definition: imxrt1050/imxrt1050-evkb/source/pv_audio_rec.c:56
BOARD_EnableSaiMclkOutput
static void BOARD_EnableSaiMclkOutput(bool enable)
Definition: imxrt1050/imxrt1050-evkb/source/pv_audio_rec.c:113
AUDIO_IN_PCM_BUFFER_SIZE_INT16
#define AUDIO_IN_PCM_BUFFER_SIZE_INT16
Definition: imxrt1050/imxrt1050-evkb/source/pv_audio_rec.c:53
_sai_transceiver::masterSlave
sai_master_slave_t masterSlave
Definition: fsl_sai.h:402
wm8960_config::i2cConfig
codec_i2c_config_t i2cConfig
Definition: fsl_wm8960.h:315
kCLOCK_Sai1Div
@ kCLOCK_Sai1Div
Definition: fsl_clock.h:796
SAI_TxSetBitClockRate
void SAI_TxSetBitClockRate(I2S_Type *base, uint32_t sourceClockHz, uint32_t sampleRate, uint32_t bitWidth, uint32_t channelNumbers)
Transmitter bit clock rate configurations.
Definition: fsl_sai.c:1048
CLOCK_InitAudioPll
void CLOCK_InitAudioPll(const clock_audio_pll_config_t *config)
Initializes the Audio PLL.
Definition: fsl_clock.c:636
CODEC_Init
status_t CODEC_Init(codec_handle_t *handle, codec_config_t *config)
Codec initilization.
Definition: fsl_codec_common.c:32
PV_SAI_CHANNEL
#define PV_SAI_CHANNEL
Definition: imxrt1050/imxrt1050-evkb/source/pv_audio_rec.c:27
codecHandle
static codec_handle_t codecHandle
Definition: imxrt1050/imxrt1050-evkb/source/pv_audio_rec.c:72
audio_frequency
uint32_t audio_frequency
Definition: imxrt1050/imxrt1050-evkb/source/pv_audio_rec.c:85
BOARD_CODEC_I2C_CLOCK_FREQ
#define BOARD_CODEC_I2C_CLOCK_FREQ
Definition: board.h:135
kStatus_SAI_RxError
@ kStatus_SAI_RxError
Definition: fsl_sai.h:34
PV_AUDIO_REC_AUDIO_FREQUENCY
#define PV_AUDIO_REC_AUDIO_FREQUENCY
Definition: imxrt1050/imxrt1050-evkb/source/pv_audio_rec.c:48
fsl_codec_common.h
last_read_index
static int32_t last_read_index
Definition: imxrt1050/imxrt1050-evkb/source/pv_audio_rec.c:78
channel_number
uint32_t channel_number
Definition: imxrt1050/imxrt1050-evkb/source/pv_audio_rec.c:84
IOMUXC_GPR_GPR1_SAI1_MCLK_DIR_MASK
#define IOMUXC_GPR_GPR1_SAI1_MCLK_DIR_MASK
Definition: MIMXRT1052.h:20979
fsl_dmamux.h
SAI_TransferRxCreateHandleEDMA
void SAI_TransferRxCreateHandleEDMA(I2S_Type *base, sai_edma_handle_t *handle, sai_edma_callback_t callback, void *userData, edma_handle_t *rxDmaHandle)
Initializes the SAI Rx eDMA handle.
Definition: fsl_sai_edma.c:190
PV_STATUS_SUCCESS
@ PV_STATUS_SUCCESS
Definition: porcupine/include/picovoice.h:34
rx_callback
static void rx_callback(I2S_Type *base, sai_edma_handle_t *handle, status_t status, void *userData)
Definition: imxrt1050/imxrt1050-evkb/source/pv_audio_rec.c:91
IOMUXC_GPR
#define IOMUXC_GPR
Definition: MIMXRT1052.h:22774
fsl_wm8960.h
kSAI_Stereo
@ kSAI_Stereo
Definition: fsl_sai.h:75
pv_status_t
pv_status_t
Definition: porcupine/include/picovoice.h:33
kWM8960_PlaySourceDAC
@ kWM8960_PlaySourceDAC
Definition: fsl_wm8960.h:229
PV_LPI2C_CLOCK_SOURCE_DIVIDER
#define PV_LPI2C_CLOCK_SOURCE_DIVIDER
Definition: imxrt1050/imxrt1050-evkb/source/pv_audio_rec.c:45
_clock_audio_pll_config
PLL configuration for AUDIO and VIDEO.
Definition: fsl_clock.h:894
kWM8960_BusI2S
@ kWM8960_BusI2S
Definition: fsl_wm8960.h:251
rx_error
static bool rx_error
Definition: imxrt1050/imxrt1050-evkb/source/pv_audio_rec.c:77
CLOCK_SetMux
static void CLOCK_SetMux(clock_mux_t mux, uint32_t value)
Set CCM MUX node to certain value.
Definition: fsl_clock.h:969
DMAMUX_Init
void DMAMUX_Init(DMAMUX_Type *base)
Initializes the DMAMUX peripheral.
Definition: fsl_dmamux.c:72
EDMA_GetDefaultConfig
void EDMA_GetDefaultConfig(edma_config_t *config)
Gets the eDMA default configuration structure.
Definition: fsl_edma.c:170
buffer_index
static volatile int32_t buffer_index
Definition: imxrt1050/imxrt1050-evkb/source/pv_audio_rec.c:81
read_index
static volatile int32_t read_index
Definition: imxrt1050/imxrt1050-evkb/source/pv_audio_rec.c:79
record_buffer_size
uint32_t record_buffer_size
Definition: imxrt1050/imxrt1050-evkb/source/pv_audio_rec.c:86
_sai_transceiver
sai transceiver configurations
Definition: fsl_sai.h:394
kWM8960_InputDifferentialMicInput2
@ kWM8960_InputDifferentialMicInput2
Definition: fsl_wm8960.h:263
EDMA_CreateHandle
void EDMA_CreateHandle(edma_handle_t *handle, DMA_Type *base, uint32_t channel)
Creates the eDMA handle.
Definition: fsl_edma.c:790
EDMA_Init
void EDMA_Init(DMA_Type *base, const edma_config_t *config)
Initializes the eDMA peripheral.
Definition: fsl_edma.c:118
_sai_transceiver::syncMode
sai_sync_mode_t syncMode
Definition: fsl_sai.h:404
wm8960_config
Initialize structure of WM8960.
Definition: fsl_wm8960.h:304
AT_NONCACHEABLE_SECTION_INIT
AT_NONCACHEABLE_SECTION_INIT(static sai_edma_handle_t txHandle)
kCLOCK_Sai1Mux
@ kCLOCK_Sai1Mux
Definition: fsl_clock.h:663
CLOCK_SetDiv
static void CLOCK_SetDiv(clock_div_t divider, uint32_t value)
Set CCM DIV node to certain value.
Definition: fsl_clock.h:1006
_clock_audio_pll_config::loopDivider
uint8_t loopDivider
Definition: fsl_clock.h:896
PV_DMAMUX
#define PV_DMAMUX
Definition: imxrt1050/imxrt1050-evkb/source/pv_audio_rec.c:59
PV_SAI1_CLOCK_SOURCE_PRE_DIVIDER
#define PV_SAI1_CLOCK_SOURCE_PRE_DIVIDER
Definition: imxrt1050/imxrt1050-evkb/source/pv_audio_rec.c:35
buffer_config
static sai_transfer_t buffer_config
Definition: imxrt1050/imxrt1050-evkb/source/pv_audio_rec.c:73
record_pcm_buffer
uint8_t * record_pcm_buffer
Definition: imxrt1050/imxrt1050-evkb/source/pv_audio_rec.c:87
DMAMUX_SetSource
static void DMAMUX_SetSource(DMAMUX_Type *base, uint32_t channel, uint32_t source)
Configures the DMAMUX channel source.
Definition: fsl_dmamux.h:105
pv_audio_rec_init
pv_status_t pv_audio_rec_init(void)
Definition: imxrt1050/imxrt1050-evkb/source/pv_audio_rec.c:125
pv_audio_rec_stop
pv_status_t pv_audio_rec_stop(void)
Definition: imxrt1050/imxrt1050-evkb/source/pv_audio_rec.c:197
kWM8960_AudioBitWidth16bit
@ kWM8960_AudioBitWidth16bit
Definition: fsl_wm8960.h:289
AUDIO_IN_PCM_BUFFER_SIZE_INT8
#define AUDIO_IN_PCM_BUFFER_SIZE_INT8
Definition: imxrt1050/imxrt1050-evkb/source/pv_audio_rec.c:55
PV_SAI_RX_SYNC_MODE
#define PV_SAI_RX_SYNC_MODE
Definition: imxrt1050/imxrt1050-evkb/source/pv_audio_rec.c:31
kCLOCK_Lpi2cMux
@ kCLOCK_Lpi2cMux
Definition: fsl_clock.h:695
board.h
pv_audio_rec_deinit
void pv_audio_rec_deinit(void)
Definition: imxrt1050/imxrt1050-evkb/source/pv_audio_rec.c:216
PV_AUDIO_REC_BIT_WIDTH
#define PV_AUDIO_REC_BIT_WIDTH
Definition: imxrt1050/imxrt1050-evkb/source/pv_audio_rec.c:51
fsl_codec_adapter.h
kCLOCK_Lpi2cDiv
@ kCLOCK_Lpi2cDiv
Definition: fsl_clock.h:827
_sai_transfer
SAI transfer structure.
Definition: fsl_sai.h:414
_edma_config
eDMA global configuration structure.
Definition: fsl_edma.h:150
BOARD_CODEC_I2C_INSTANCE
#define BOARD_CODEC_I2C_INSTANCE
Definition: board.h:132
AT_NONCACHEABLE_SECTION_ALIGN
AT_NONCACHEABLE_SECTION_ALIGN(static uint8_t record_pcm_buffer[AUDIO_IN_PCM_BUFFER_SIZE_INT8], 16)
SAI_TransferTxSetConfigEDMA
void SAI_TransferTxSetConfigEDMA(I2S_Type *base, sai_edma_handle_t *handle, sai_transceiver_t *saiConfig)
Configures the SAI Tx.
Definition: fsl_sai_edma.c:274
PV_DMA
#define PV_DMA
Definition: imxrt1050/imxrt1050-evkb/source/pv_audio_rec.c:58
dmaConfig
static edma_config_t dmaConfig
Definition: imxrt1050/imxrt1050-evkb/source/pv_audio_rec.c:74
_codec_i2c_config::codecI2CInstance
uint32_t codecI2CInstance
Definition: fsl_codec_i2c.h:41
PV_AUDIO_REC_CHANNEL_NUMBER
#define PV_AUDIO_REC_CHANNEL_NUMBER
Definition: imxrt1050/imxrt1050-evkb/source/pv_audio_rec.c:49
SAI_RxSetBitClockRate
void SAI_RxSetBitClockRate(I2S_Type *base, uint32_t sourceClockHz, uint32_t sampleRate, uint32_t bitWidth, uint32_t channelNumbers)
Receiver bit clock rate configurations.
Definition: fsl_sai.c:1095
kWM8960_RouteRecord
@ kWM8960_RouteRecord
Definition: fsl_wm8960.h:242
config
static sai_transceiver_t config
Definition: imxrt1050/imxrt1050-evkb/source/pv_audio_rec.c:75
PV_RX_EDMA_CHANNEL
#define PV_RX_EDMA_CHANNEL
Definition: imxrt1050/imxrt1050-evkb/source/pv_audio_rec.c:61
kWM8960_AudioSampleRate16KHz
@ kWM8960_AudioSampleRate16KHz
Definition: fsl_wm8960.h:275
SAI_TransferReceiveEDMA
status_t SAI_TransferReceiveEDMA(I2S_Type *base, sai_edma_handle_t *handle, sai_transfer_t *xfer)
Performs a non-blocking SAI receive using eDMA.
Definition: fsl_sai_edma.c:467
kCLOCK_Sai1PreDiv
@ kCLOCK_Sai1PreDiv
Definition: fsl_clock.h:792
status_t
int32_t status_t
Type used for all status and error return values.
Definition: fsl_common.h:189
write_index
static volatile int32_t write_index
Definition: imxrt1050/imxrt1050-evkb/source/pv_audio_rec.c:80
PV_SAI1_CLOCK_SOURCE_DIVIDER
#define PV_SAI1_CLOCK_SOURCE_DIVIDER
Definition: imxrt1050/imxrt1050-evkb/source/pv_audio_rec.c:36
_codec_config::codecDevType
uint32_t codecDevType
Definition: fsl_codec_common.h:223
kStatus_Success
@ kStatus_Success
Definition: fsl_common.h:179
SAI_GetClassicI2SConfig
void SAI_GetClassicI2SConfig(sai_transceiver_t *config, sai_word_width_t bitWidth, sai_mono_stereo_t mode, uint32_t saiChannelMask)
Get classic I2S mode configurations.
Definition: fsl_sai.c:1693
PV_LPI2C_CLOCK_SOURCE_SELECT
#define PV_LPI2C_CLOCK_SOURCE_SELECT
Definition: imxrt1050/imxrt1050-evkb/source/pv_audio_rec.c:44
SAI_Init
void SAI_Init(I2S_Type *base)
Initializes the SAI peripheral.
Definition: fsl_sai.c:648
_codec_handle
Codec handle definition.
Definition: fsl_codec_common.h:240


picovoice_driver
Author(s):
autogenerated on Fri Apr 1 2022 02:14:50