📄 aic27.c
字号:
/******************************************************************************/
/******************************************************************************/
/* aic27.c - TLV320AIC27 Audio Codec Driver Routines */
/* */
/* This module is the device driver library for the TLV320AIC27 Audio Codec */
/* on the 5510 EVM board. */
/* */
/* FUNCTIONS: */
/* */
/* aic27_open() - Open codec connection to McBSP with default reg values */
/* aic27_close() - Close codec connection to McBSP */
/* aic27_init() - Initializes AIC27 control registers. */
/* aic27_reset() - Reset the codec to the default configuration. */
/* aic27_read_reg() - Read an AIC27 control register */
/* aic27_write_reg() - Write an AIC27 control register */
/* aic27_sample_rate() - Configures the specified channel's sampling rate */
/* aic27_cont_play() - Sets continuous play (D/A) mode */
/* aic27_cont_capture() - Sets continuous capture (A/D) mode */
/* aic27_stop_play() - Stops sending data to AIC27 */
/* aic27_stop_capture() - Stops receiving data from AIC27 */
/* */
/******************************************************************************/
/******************************************************************************/
/* FILE Global PROTOTYPES */
/******************************************************************************/
#pragma CODE_SECTION(aic27_open, "EVM5510");
#pragma CODE_SECTION(aic27_close, "EVM5510");
#pragma CODE_SECTION(aic27_init, "EVM5510");
#pragma CODE_SECTION(aic27_reset, "EVM5510");
#pragma CODE_SECTION(aic27_read_reg, "EVM5510");
#pragma CODE_SECTION(aic27_write_reg, "EVM5510");
#pragma CODE_SECTION(aic27_sample_rate, "EVM5510");
#pragma CODE_SECTION(aic27_cont_play, "EVM5510");
#pragma CODE_SECTION(aic27_cont_capture, "EVM5510");
#pragma CODE_SECTION(aic27_stop_play, "EVM5510");
#pragma CODE_SECTION(aic27_stop_capture, "EVM5510");
/******************************************************************************/
/* INCLUDES */
/******************************************************************************/
//EVM Driver Include Files
#include <stddef.h>
#include <type.h> //typedefs
#include <aic27.h> //AIC27 Codec public header file
#include <board.h> //board definitions
#include <regs55x.h>
#include <mcbsp55x.h>
#include <dma55x.h>
#include <intr.h>
/******************************************************************************/
/* DEFINITIONS */
/******************************************************************************/
//AIC27 timeslot valid bits
#define AIC27_CODEC_READY 0x8000ul
#define AIC27_VALID_FRAME 0x8000ul
#define AIC27_VALID_REGADDR_CH 0x4000ul //SLOT 1
#define AIC27_VALID_REGDATA_CH 0x2000ul //SLOT 2
#define AIC27_LEFT_CH 0x1000ul //Play data to left channel only
#define AIC27_RIGHT_CH 0x0800ul //Play data to Right channel only
#define AIC27_BOTH_CH 0x1800ul //Play data to both channels
#define AIC27_DATA_REQ 0x0C00ul //On-demand data requests bit for channels 3 & 4
#define AIC27_SLOT3_REQ 0x0800ul //On-demand data request bit for channel 3
#define AIC27_SLOT4_REQ 0x0400ul //On-demand data request bit for channel 4
#define REG_READ_REQUEST 0x80000ul // b19 in composite 20-bit word
//DMA settings
#define AIC27TXCH 4 //DMA Ch 4
#define AIC27_TXDMA_FLAG DMAC4
#define AIC27_TXDMA_TRAP DMAC4_TRAP
#define AIC27RXCH 5 //DMA Ch 5
#define AIC27_RXDMA_FLAG DMAC5
#define AIC27_RXDMA_TRAP DMAC5_TRAP
#define DMA_BUFSIZE 5
//McBsp setting for AC'97 compliant codec in dual mode
#define WD_PER_FRAME_1 0x0
#define WD_PER_FRAME_4 0x3
#define RCR1_VAL ((WD_PER_FRAME_1 << 8) | (WORD_LENGTH_16 << 5))
#define RCR2_VAL ((DUAL_PHASE << 15) |\
(WD_PER_FRAME_4 << 8) |\
(WORD_LENGTH_20 << 5) |\
(NO_COMPAND_MSB_1ST << 3) |\
(NO_FRAME_IGNORE << 2) |\
(DATA_DELAY1 << 0))
#define XCR1_VAL ((WD_PER_FRAME_1 << 8) | (WORD_LENGTH_16 << 5))
#define XCR2_VAL ((DUAL_PHASE << 15) |\
(WD_PER_FRAME_4 << 8) |\
(WORD_LENGTH_20 << 5) |\
(NO_COMPAND_MSB_1ST << 3) |\
(NO_FRAME_IGNORE << 2) |\
(DATA_DELAY1 << 0))
#define PCR_VAL ((FSYNC_POL_HIGH<<3)|(FSYNC_POL_HIGH<<2)|(CLKX_POL_RISING<<1)|(CLKR_POL_FALLING))
#define SPCR1_VAL 0
#define SPCR2_VAL 0
#define SRGR1_VAL 0
#define SRGR2_VAL 0
/******************************************************************************/
/* ENUMs */
/******************************************************************************/
/*****************************************************************************/
/* AIC27 state */
/*****************************************************************************/
typedef enum
{
AIC27_CODEC_CLOSED = 0,
AIC27_CODEC_OPENED = 1
} AIC27State, *PAIC27State;
/******************************************************************************/
/* AIC27 codec structure */
/******************************************************************************/
typedef struct _AIC27packet
{
s16 status; //complete (1) or not complete (0)
u16 size; //buffer size (64K max)
u16 indx; //sample count
bool bufi; //selects ping-pong buffer
s16 *pBuf[2]; //pointers to ping-pong buffers
Fp callback; //callback function
} AIC27Packet, *PAIC27Packet;
typedef struct _AIC27Codec
{
AIC27State state; //codec state
AIC27Packet rxPkt; //receive packet
AIC27Packet txPkt; //transmit packet
} AIC27Codec, *PAIC27Codec;
typedef struct _AIC27Reg
{
u32 tag;
u32 addr; //20-bit reg address (slot 0)
u32 data; //20-bit reg value (slot 1)
} AIC27Prog, *PAIC27Prog;
typedef struct _AIC27DmaStruct
{
u32 tag;
u32 addr;
u32 data;
u32 leftCh;
u32 rightCh;
} AIC27DmaStruct, *PAIC27DmaStruct;
/******************************************************************************/
/* GLOBAL VARIABLES */
/******************************************************************************/
#pragma DATA_ALIGN(dmaTxBuf, 2 /*4*/)
#pragma DATA_ALIGN(dmaRxBuf, 2 /*4*/)
#pragma DATA_SECTION(dmaTxBuf, "EVMDATA");
#pragma DATA_SECTION(dmaRxBuf, "EVMDATA");
#pragma DATA_SECTION(aic27Status, "EVMDATA");
#pragma DATA_SECTION(aic27Cmd, "EVMDATA");
//pointer to DMA buffers allocated in ASM
volatile AIC27DmaStruct dmaTxBuf;
volatile AIC27DmaStruct dmaRxBuf;
volatile AIC27Prog aic27Status = {0,0,0};
volatile AIC27Prog aic27Cmd = {(u32)AIC27_VALID_FRAME,0,0};
/******************************************************************************/
/* FILE LOCAL (STATIC) VARIABLES */
/******************************************************************************/
#pragma DATA_SECTION(cdx, "EVMDATA");
#pragma DATA_SECTION(writeDone, "EVMDATA");
#pragma DATA_SECTION(readDone, "EVMDATA");
#pragma DATA_SECTION(rx_stop, "EVMDATA");
#pragma DATA_SECTION(tx_stop, "EVMDATA");
static volatile AIC27Codec cdx = {AIC27_CODEC_CLOSED, 0, 0};
static volatile bool writeDone = True;
static volatile bool readDone = True;
static volatile bool rx_stop = False;
static volatile bool tx_stop = False;
/******************************************************************************/
/* FILE LOCAL (STATIC) PROTOTYPES */
/******************************************************************************/
#pragma CODE_SECTION(_serial_reset, "EVM5510");
#pragma CODE_SECTION(_setup_aic27_serial_port, "EVM5510");
#pragma CODE_SECTION(_reset_aic27_pkts, "EVM5510");
#pragma CODE_SECTION(_setup_aic27_registers, "EVM5510");
#pragma CODE_SECTION(_setup_aic27_dma, "EVM5510");
#pragma CODE_SECTION(_enable_aic27_interrupt, "EVM5510");
#pragma CODE_SECTION(_disable_aic27_interrupt, "EVM5510");
#pragma CODE_SECTION(enable_codec_comm, "EVM5510");
#pragma CODE_SECTION(disable_codec_comm, "EVM5510");
#pragma CODE_SECTION(reset_dma, "EVM5510");
#pragma CODE_SECTION(setMemSpace, "EVM5510");
#pragma CODE_SECTION(_aic27_rxdma_isr, "EVM5510");
static void _serial_reset();
static void _setup_aic27_serial_port();
static void _reset_aic27_pkts();
static void _setup_aic27_registers();
static void _setup_aic27_dma();
static void _enable_aic27_interrupt();
static void _disable_aic27_interrupt();
static void enable_codec_comm();
static void disable_codec_comm();
static void reset_dma();
static u16 setMemSpace(u32 addr);
// McBSP Interrupt Handler
interrupt void _aic27_rxdma_isr(void);
/******************************************************************************/
/* aic27_open() - Open AIC27 codec and connect codec to McBSP. */
/* */
/* */
/* Parameters - None */
/* */
/* Returns - BRD_OK on success, BRD_ERROR on failure. */
/* */
/******************************************************************************/
int aic27_open()
{
// If codec is already open return BRD_OK
if (cdx.state == AIC27_CODEC_OPENED)
return BRD_OK;
// Set flag to opened
cdx.state = AIC27_CODEC_OPENED;
// Initialize AIC27
aic27_init();
// Return true
return BRD_OK;
}
/******************************************************************************/
/* aic27_close() - Closes codec connection */
/* */
/* Parameters - None */
/* */
/* Returns - BRD_OK on success, BRD_ERROR on failure. */
/* */
/******************************************************************************/
int aic27_close()
{
// If codec not opened, then just return
if (cdx.state == AIC27_CODEC_CLOSED)
return BRD_OK;
// Disable codec interrupt
disable_codec_comm();
cdx.state = AIC27_CODEC_CLOSED;
return BRD_OK;
}
/******************************************************************************/
/* aic27_init() - Initialize AIC27 codec by setting up the registers */
/* */
/* Parameters - None */
/* */
/* Returns - None */
/* */
/******************************************************************************/
void aic27_init()
{
rx_stop = tx_stop = False;
//Enable codec communications
enable_codec_comm();
//Setup AIC27 codec registers
_setup_aic27_registers();
}
/******************************************************************************/
/* aic27_reset() - Reset the codec to the default configuration. */
/* */
/* This function resets the AIC27 codec by sending it a software reset. */
/* All registers are configured to their default values. */
/* */
/* Parameters - None */
/* */
/* Returns - BRD_OK on success, BRD_ERROR on failure. */
/* */
/******************************************************************************/
int aic27_reset()
{
//reset aic27 codec by writing any value to register the reset reg (addr 0x00)
if (aic27_write_reg(RESET, 0xffff, 0xffff) == (u16)BRD_ERROR)
return BRD_ERROR;
disable_codec_comm();
cdx.state = AIC27_CODEC_OPENED;
return BRD_OK;
}
/******************************************************************************/
/* aic27_read_reg() - Read an AIC27 control register */
/* */
/* Parameters - */
/* reg - an element of an enumeration indicating the register to read. */
/* */
/* Returns - Content of the indicated register */
/* */
/******************************************************************************/
u16 aic27_read_reg(AIC27Reg reg)
{
if (cdx.state == AIC27_CODEC_CLOSED)
return (u16)BRD_ERROR;
//disable receive DMA interrupt
IER0 &= (u16)(~(1<<AIC27_RXDMA_FLAG));
//assemble cmd addr
//b19 in composite 20-bit word is 1
//aic27Cmd.addrL = ((reg & 0xe) << 12);
//aic27Cmd.addrH = REG_READ_REQUEST | ((reg & 0x70) >> 4);
aic27Cmd.addr = REG_READ_REQUEST | ((u32)((u32)reg & 0x7e) << 12);
//data must be 0 for read
aic27Cmd.data = 0;
//set tag for next output frame (indicate addr/data slots are valid)
aic27Cmd.tag |= (AIC27_VALID_REGADDR_CH | AIC27_VALID_REGDATA_CH);
aic27Status.tag &= ~(AIC27_VALID_REGADDR_CH | AIC27_VALID_REGDATA_CH);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -