初级会员
- 积分
- 169
- 金钱
- 169
- 注册时间
- 2015-11-12
- 在线时间
- 29 小时
|
发表于 2018-9-29 17:11:32
|
显示全部楼层
有个rt1021的,凑合着看吧:
sai1.h:
#include "board.h"
#include "fsl_dmamux.h"
#include "fsl_sai_edma.h"
#include "fsl_debug_console.h"
#include "arm_math.h"
#include "usb_audio_config.h"
#include "system.h"
/*******************************************************************************
* Definitions
******************************************************************************/
#define OVER_SAMPLE_RATE (384U)
#if defined AUDIO_SAMPLING_RATE_KHZ && (AUDIO_SAMPLING_RATE_KHZ == 48)
#define SAMPLE_RATE (kSAI_SampleRate48KHz)
#elif defined AUDIO_SAMPLING_RATE_KHZ && (AUDIO_SAMPLING_RATE_KHZ == 16)
#define SAMPLE_RATE (kSAI_SampleRate16KHz)
#elif defined AUDIO_SAMPLING_RATE_KHZ && (AUDIO_SAMPLING_RATE_KHZ == 8)
#define SAMPLE_RATE (kSAI_SampleRate8KHz)
#endif
#define BUFFER_SIZE (AUDIO_SAMPLING_RATE_KHZ*AUDIO_FORMAT_SIZE*2*8)
#define BUFFER_NUM (2)
#if defined BOARD_HAS_SDCARD && (BOARD_HAS_SDCARD != 0)
#define DEMO_SDCARD (1U)
#endif
/*******************************************************************************
* Prototypes
******************************************************************************/
void init_sai1(void);
void sai1_record(void);
sai1.c:
/*
* The Clear BSD License
* Copyright (c) 2015, Freescale Semiconductor, Inc.
* Copyright 2016-2017 NXP
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted (subject to the limitations in the disclaimer below) provided
* that the following conditions are met:
*
* o Redistributions of source code must retain the above copyright notice, this list
* of conditions and the following disclaimer.
*
* o Redistributions in binary form must reproduce the above copyright notice, this
* list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
*
* o Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED BY THIS LICENSE.
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <sai1.h>
#include "fsl_wm8960.h"
#include "pin_mux.h"
#include "board.h"
#include "clock_config.h"
#include "lpuart.h"
#include "module_cfg.h"
#include "algorithm.h"
/*******************************************************************************
* Definitions
******************************************************************************/
/* SAI instance and clock */
#define DEMO_CODEC_WM8960
#define DEMO_SAI SAI1
#define DEMO_SAI_CHANNEL (0)
#define DEMO_SAI_BITWIDTH (kSAI_WordWidth24bits)
#define DEMO_SAI_IRQ SAI1_IRQn
#define SAI_UserIRQHandler SAI1_IRQHandler
/* IRQ */
#define DEMO_SAI_TX_IRQ SAI1_IRQn
#define DEMO_SAI_RX_IRQ SAI1_IRQn
/* DMA */
#define EXAMPLE_DMA DMA0
#define EXAMPLE_DMAMUX DMAMUX
#define EXAMPLE_TX_CHANNEL (CONFIG_SAI1_TX_DMA_CHANNEL)
#define EXAMPLE_RX_CHANNEL (CONFIG_SAI1_RX_DMA_CHANNEL)
#define EXAMPLE_SAI_TX_SOURCE kDmaRequestMuxSai1Tx
#define EXAMPLE_SAI_RX_SOURCE kDmaRequestMuxSai1Rx
/* Select Audio/Video PLL (786.48 MHz) as sai1 clock source */
#define DEMO_SAI1_CLOCK_SOURCE_SELECT (2U)
/* Clock pre divider for sai1 clock source */
#define DEMO_SAI1_CLOCK_SOURCE_PRE_DIVIDER (0U)
/* Clock divider for sai1 clock source */
#define DEMO_SAI1_CLOCK_SOURCE_DIVIDER (63U)
/* Get frequency of sai1 clock */
#define DEMO_SAI_CLK_FREQ \
(CLOCK_GetFreq(kCLOCK_AudioPllClk) / (DEMO_SAI1_CLOCK_SOURCE_DIVIDER + 1U) / \
(DEMO_SAI1_CLOCK_SOURCE_PRE_DIVIDER + 1U))
/* I2C instance and clock */
#define DEMO_I2C LPI2C1
/* Select USB1 PLL (480 MHz) as master lpi2c clock source */
#define DEMO_LPI2C_CLOCK_SOURCE_SELECT (0U)
/* Clock divider for master lpi2c clock source */
#define DEMO_LPI2C_CLOCK_SOURCE_DIVIDER (5U)
/* Get frequency of lpi2c clock */
#define DEMO_I2C_CLK_FREQ ((CLOCK_GetFreq(kCLOCK_Usb1PllClk) / 8) / (DEMO_LPI2C_CLOCK_SOURCE_DIVIDER + 1U))
/*******************************************************************************
* Prototypes
******************************************************************************/
static void txCallback(I2S_Type *base, sai_edma_handle_t *handle,
status_t status, void *userData);
static void rxCallback(I2S_Type *base, sai_edma_handle_t *handle,
status_t status, void *userData);
/*******************************************************************************
* Variables
******************************************************************************/
AT_NONCACHEABLE_SECTION_INIT(sai_edma_handle_t txHandle) = { 0 };
edma_handle_t dmaTxHandle = { 0 };
AT_NONCACHEABLE_SECTION_INIT(sai_edma_handle_t rxHandle) = { 0 };
edma_handle_t dmaRxHandle = { 0 };
sai_transfer_format_t format = { 0 };
AT_NONCACHEABLE_SECTION_ALIGN(uint8_t audioBuff[BUFFER_SIZE * BUFFER_NUM], 4);
codec_handle_t codecHandle = { 0 };
extern codec_config_t boardCodecConfig;
volatile bool istxFinished = false;
volatile bool isrxFinished = false;
//volatile uint32_t beginCount = 0;
//volatile uint32_t sendCount = 0;
//volatile uint32_t receiveCount = 0;
volatile bool sdcard = false;
volatile uint64_t receiveBlock = 0;
volatile uint64_t emptyBlock = BUFFER_NUM;
volatile uint64_t read_idx = 0;
/*******************************************************************************
* Code
******************************************************************************/
/*
* AUDIO PLL setting: Frequency = Fref * (DIV_SELECT + NUM / DENOM)
* = 24 * (32 + 77/100)
* = 786.48 MHz
*/
const clock_audio_pll_config_t audioPllConfig = { .loopDivider = 32, /* PLL loop divider. Valid range for DIV_SELECT divider value: 27~54. */
.postDivider = 1, /* Divider after the PLL, should only be 1, 2, 4, 8, 16. */
.numerator = 77, /* 30 bit numerator of fractional loop divider. */
.denominator = 100, /* 30 bit denominator of fractional loop divider */
};
void BOARD_EnableSaiMclkOutput(bool enable) {
if (enable) {
IOMUXC_GPR->GPR1 |= IOMUXC_GPR_GPR1_SAI1_MCLK_DIR_MASK;
} else {
IOMUXC_GPR->GPR1 &= (~IOMUXC_GPR_GPR1_SAI1_MCLK_DIR_MASK);
}
}
static void txCallback(I2S_Type *base, sai_edma_handle_t *handle,
status_t status, void *userData) {
emptyBlock++;
// if (sendCount == beginCount) {
// istxFinished = true;
// SAI_TransferTerminateSendEDMA(base, handle);
// sendCount = 0;
// }
}
static void rxCallback(I2S_Type *base, sai_edma_handle_t *handle,
status_t status, void *userData) {
receiveBlock++;
// if (receiveCount == beginCount) {
// isrxFinished = true;
// SAI_TransferTerminateReceiveEDMA(base, handle);
// receiveCount = 0;
// }
}
/*!
* @brief init_sai1 function
*/
void init_sai1(void) {
gpio_pin_config_t output1_config = {kGPIO_DigitalOutput, 1, kGPIO_NoIntmode};
gpio_pin_config_t output0_config = {kGPIO_DigitalOutput, 0, kGPIO_NoIntmode};
GPIO_PinInit(EN_ANALOG_PORT, EN_ANALOG_PIN, &output1_config);
sai_config_t config;
uint32_t mclkSourceClockHz = 0U;
edma_config_t dmaConfig = { 0 };
CLOCK_InitAudioPll(&audioPllConfig);
//BOARD_InitDebugConsole();
/*Clock setting for LPI2C*/
// CLOCK_SetMux(kCLOCK_Lpi2cMux, DEMO_LPI2C_CLOCK_SOURCE_SELECT);
// CLOCK_SetDiv(kCLOCK_Lpi2cDiv, DEMO_LPI2C_CLOCK_SOURCE_DIVIDER);
/*Clock setting for SAI1*/
CLOCK_SetMux(kCLOCK_Sai1Mux, DEMO_SAI1_CLOCK_SOURCE_SELECT);
CLOCK_SetDiv(kCLOCK_Sai1PreDiv, DEMO_SAI1_CLOCK_SOURCE_PRE_DIVIDER);
CLOCK_SetDiv(kCLOCK_Sai1Div, DEMO_SAI1_CLOCK_SOURCE_DIVIDER);
/*Enable MCLK clock*/
BOARD_EnableSaiMclkOutput(true);
//BOARD_Codec_I2C_Init();
rt_kprintf("SAI Demo started!\r\n");
/* Create EDMA handle */
/*
* dmaConfig.enableRoundRobinArbitration = false;
* dmaConfig.enableHaltOnError = true;
* dmaConfig.enableContinuousLinkMode = false;
* dmaConfig.enableDebugMode = false;
*/
EDMA_GetDefaultConfig(&dmaConfig);
EDMA_Init(EXAMPLE_DMA, &dmaConfig);
EDMA_CreateHandle(&dmaTxHandle, EXAMPLE_DMA, EXAMPLE_TX_CHANNEL);
EDMA_CreateHandle(&dmaRxHandle, EXAMPLE_DMA, EXAMPLE_RX_CHANNEL);
DMAMUX_Init(EXAMPLE_DMAMUX);
DMAMUX_SetSource(EXAMPLE_DMAMUX, EXAMPLE_TX_CHANNEL,
(uint8_t) EXAMPLE_SAI_TX_SOURCE);
DMAMUX_EnableChannel(EXAMPLE_DMAMUX, EXAMPLE_TX_CHANNEL);
DMAMUX_SetSource(EXAMPLE_DMAMUX, EXAMPLE_RX_CHANNEL,
(uint8_t) EXAMPLE_SAI_RX_SOURCE);
DMAMUX_EnableChannel(EXAMPLE_DMAMUX, EXAMPLE_RX_CHANNEL);
/* Init SAI module */
/*
* config.masterSlave = kSAI_Master;
* config.mclkSource = kSAI_MclkSourceSysclk;
* config.protocol = kSAI_BusLeftJustified;
* config.syncMode = kSAI_ModeAsync;
* config.mclkOutputEnable = true;
*/
config.masterSlave = kSAI_Master;
SAI_TxGetDefaultConfig(&config);
SAI_TxInit(DEMO_SAI, &config);
/* Initialize SAI Rx */
config.masterSlave = kSAI_Master;
SAI_RxGetDefaultConfig(&config);
SAI_RxInit(DEMO_SAI, &config);
/* Configure the audio format */
format.bitWidth = kSAI_WordWidth32bits;
format.channel = 0U;
format.sampleRate_Hz = SAMPLE_RATE;
#if (defined FSL_FEATURE_SAI_HAS_MCLKDIV_REGISTER && FSL_FEATURE_SAI_HAS_MCLKDIV_REGISTER) || \
(defined FSL_FEATURE_PCC_HAS_SAI_DIVIDER && FSL_FEATURE_PCC_HAS_SAI_DIVIDER)
format.masterClockHz = OVER_SAMPLE_RATE * format.sampleRate_Hz;
#else
format.masterClockHz = DEMO_SAI_CLK_FREQ;
#endif
format.protocol = config.protocol;
format.stereo = kSAI_Stereo;
#if defined(FSL_FEATURE_SAI_FIFO_COUNT) && (FSL_FEATURE_SAI_FIFO_COUNT > 1)
format.watermark = FSL_FEATURE_SAI_FIFO_COUNT / 2U;
#endif
/* Use default setting to init codec */
// CODEC_Init(&codecHandle, &boardCodecConfig);
// CODEC_SetFormat(&codecHandle, format.masterClockHz, format.sampleRate_Hz,
// format.bitWidth);
//#if defined CODEC_USER_CONFIG
// BOARD_Codec_Config(&codecHandle);
//#endif
SAI_TransferTxCreateHandleEDMA(DEMO_SAI, &txHandle, txCallback, NULL,
&dmaTxHandle);
SAI_TransferRxCreateHandleEDMA(DEMO_SAI, &rxHandle, rxCallback, NULL,
&dmaRxHandle);
mclkSourceClockHz = DEMO_SAI_CLK_FREQ;
SAI_TransferTxSetFormatEDMA(DEMO_SAI, &txHandle, &format, mclkSourceClockHz,
format.masterClockHz);
SAI_TransferRxSetFormatEDMA(DEMO_SAI, &rxHandle, &format, mclkSourceClockHz,
format.masterClockHz);
/* Enable interrupt to handle FIFO error */
SAI_TxEnableInterrupts(DEMO_SAI, kSAI_FIFOErrorInterruptEnable);
SAI_RxEnableInterrupts(DEMO_SAI, kSAI_FIFOErrorInterruptEnable);
EnableIRQ(DEMO_SAI_TX_IRQ);
EnableIRQ(DEMO_SAI_RX_IRQ);
rt_kprintf("SAI is Ready!\r\n");
// rt_kprintf("\n\rPlease choose the option :\r\n");
// while (1)
// {
// rt_kprintf("\r1. Record and playback at same time\r\n");
// rt_kprintf("\r2. Playback sine wave\r\n");
//#if defined DEMO_SDCARD
// rt_kprintf("\r3. Record to SDcard, after record playback it\r\n");
//#endif /* DEMO_SDCARD */
//#if defined DIG_MIC
// rt_kprintf("\r4. Record using digital mic and playback at the same time\r\n");
//#endif
// rt_kprintf("\r5. Quit\r\n");
//
// input = GETCHAR();
// PUTCHAR(input);
// rt_kprintf("\r\n");
//
// if (input == '5')
// {
// break;
// }
//
// switch (input)
// {
// case '1':
//#if defined DIG_MIC
// /* Set the audio input source to AUX */
// DA7212_ChangeInput(&codecHandle, kDA7212_Input_AUX);
//#endif
// RecordPlayback(DEMO_SAI, 30);
// break;
// case '2':
// PlaybackSine(DEMO_SAI, 250, 5);
// break;
//#if defined DEMO_SDCARD
// case '3':
// RecordSDCard(DEMO_SAI, 5);
// break;
//#endif
//#if defined DIG_MIC
// case '4':
// /* Set the audio input source to DMIC */
// DA7212_ChangeInput(&codecHandle, kDA7212_Input_MIC1_Dig);
// RecordPlayback(DEMO_SAI, 30);
// break;
//#endif
// default:
// rt_kprintf("\rInvallid Input Parameter, please re-enter\r\n");
// break;
// }
// }
// CODEC_Deinit(&codecHandle);
// rt_kprintf("\n\r SAI demo finished!\n\r ");
// while (1)
// {
// }
}
AT_NONCACHEABLE_SECTION_ALIGN(int32_t processedBuff[BUFFER_SIZE/(2*AUDIO_FORMAT_SIZE) * 4], 4);
AT_NONCACHEABLE_SECTION_ALIGN(int32_t dspInputBuff[BUFFER_SIZE/2], 4);
AT_NONCACHEABLE_SECTION_ALIGN(int32_t dspOutputBuff[BUFFER_SIZE/2], 4);
void sai1_record(void) {
uint32_t i = 0;
uint32_t rxindex = 0;
// uint8_t time_s = 5;
sai_transfer_t xfer = { 0 };
/* Reset SAI internal logic */
SAI_TxSoftwareReset(DEMO_SAI, kSAI_ResetTypeSoftware);
SAI_RxSoftwareReset(DEMO_SAI, kSAI_ResetTypeSoftware);
// /* Start to record */
// beginCount = time_s * SAMPLE_RATE * 2U * 2U / BUFFER_SIZE;
/* Start record first */
memset(audioBuff, 0, BUFFER_SIZE * BUFFER_NUM);
xfer.dataSize = BUFFER_SIZE;
for (i = 0; i < BUFFER_NUM; i++) {
xfer.data = audioBuff + i * BUFFER_SIZE;
SAI_TransferReceiveEDMA(DEMO_SAI, &rxHandle, &xfer);
}
uint32_t old_blocks = receiveBlock;
gpio_pin_config_t output1_config = {kGPIO_DigitalOutput, 1, kGPIO_NoIntmode};
gpio_pin_config_t output0_config = {kGPIO_DigitalOutput, 0, kGPIO_NoIntmode};
uint32_t processed_idx = 0;
/*初始化滤波算法*/
init_iir(200);
while (1) {
if (old_blocks != receiveBlock) {
// 双通道,抛弃一个通道,每次数据为16bit.
// local_idx = process_idx;
for(i = 0; i < BUFFER_SIZE/(2*AUDIO_FORMAT_SIZE); i++)
{
uint32_t data_idx = rxindex*BUFFER_SIZE + 2*AUDIO_FORMAT_SIZE*i;
/*复制数据进入DSP算法进行处理*/
memcpy(&dspInputBuff[i], &audioBuff[data_idx],4);
//memcpy(&dspOutputBuff[i], &audioBuff[data_idx],4);
//processed_idx = (processed_idx + 1)%(sizeof(processedBuff)/sizeof(int32_t));
}
#if 1
audio_filter(dspInputBuff, dspOutputBuff, BUFFER_SIZE/(2*AUDIO_FORMAT_SIZE));
#else
memcpy(dspOutputBuff, dspInputBuff, BUFFER_SIZE/2);
#endif
memcpy(&processedBuff[processed_idx], dspOutputBuff, BUFFER_SIZE/2);
processed_idx = (processed_idx + BUFFER_SIZE/(2*AUDIO_FORMAT_SIZE))%(sizeof(processedBuff)/sizeof(int32_t));
xfer.data = audioBuff + rxindex * BUFFER_SIZE;
//xfer.data = audioBuff;
rxindex = (rxindex + 1U) % BUFFER_NUM;
SAI_TransferReceiveEDMA(DEMO_SAI, &rxHandle, &xfer);
old_blocks = receiveBlock;
if(receiveBlock%2 == 0)
GPIO_PinInit(GPIO2, 6U, &output1_config);
else
GPIO_PinInit(GPIO2, 6U, &output0_config);
}
}
rt_kprintf("\r\nRecord is finished!\r\n");
}
void SAI_UserTxIRQHandler(void) {
/* Clear the FEF flag */
SAI_TxClearStatusFlags(DEMO_SAI, kSAI_FIFOErrorFlag);
SAI_TxSoftwareReset(DEMO_SAI, kSAI_ResetTypeFIFO);
/* Add for ARM errata 838869, affects Cortex-M4, Cortex-M4F Store immediate overlapping
exception return operation might vector to incorrect interrupt */
#if defined __CORTEX_M && (__CORTEX_M == 4U)
__DSB();
#endif
}
void SAI_UserRxIRQHandler(void) {
SAI_RxClearStatusFlags(DEMO_SAI, kSAI_FIFOErrorFlag);
SAI_RxSoftwareReset(DEMO_SAI, kSAI_ResetTypeFIFO);
/* Add for ARM errata 838869, affects Cortex-M4, Cortex-M4F Store immediate overlapping
exception return operation might vector to incorrect interrupt */
#if defined __CORTEX_M && (__CORTEX_M == 4U)
__DSB();
#endif
}
void SAI_UserIRQHandler(void) {
if (DEMO_SAI->TCSR & kSAI_FIFOErrorFlag) {
SAI_UserTxIRQHandler();
}
if (DEMO_SAI->RCSR & kSAI_FIFOErrorFlag) {
SAI_UserRxIRQHandler();
}
}
|
|