📄 codec.c
字号:
#include <p30f6014.h>
#include <dci.h>
#include "common.h"
#include "timers.h"
#include "codec.h"
#define FRAMECLKRATE (SAMPLE_RATE*256L)
#define CMD_STAGE0 0 //正常模式
#define CMD_STAGE1 1 //设置lsb告诉解码器下一个控制字是命令
#define CMD_STAGE2 2 //把带命令的字节放到输出缓冲
#define CMD_STAGE3 3 //设置帧模式
#define CMD_STAGE4 4 //回复正常帧模式
#define QUEUE_SIZE (PROC_BLOCK_SIZE*2) //Rx和Tx队列的大小,必须为处理缓冲
//大小的2倍
unsigned int* pActiveRxBuf;
unsigned int* pActiveTxBuf;
static volatile unsigned char CmdStage;
static volatile unsigned int CodecCmd;
static volatile char ClkAdjTrig;
static int TxQue[QUEUE_SIZE];
static int RxQue[QUEUE_SIZE];
static volatile unsigned int TxQTail;
static volatile unsigned int RxQHead;
void InitCodec(void);
void WriteCodecCtrl( unsigned char adr, unsigned char parm );
void AdjustClock( char shift );
unsigned char ReadCodecCtrl( unsigned char adr );
//把数据放到接收缓冲的子程序
inline void PutRxQue(int data)
{
RxQue[RxQHead++] = data;
if(RxQHead==QUEUE_SIZE)
{
RxQHead = 0;
pActiveRxBuf = RxQue + QUEUE_SIZE/2;
SemA.CodecRxDataRdy = TRUE;
}
else
{
if(RxQHead==QUEUE_SIZE/2)
{
pActiveRxBuf = RxQue;
SemA.CodecRxDataRdy = TRUE;
}
}
}
//从接收缓冲获取数据的子程序
inline int GetTxQue(void)
{
static int tmp; //因为是在线(inline)函数,须定义为静态
tmp = TxQue[TxQTail++]&0xFFFE;
if(TxQTail==QUEUE_SIZE)
{
TxQTail = 0;
pActiveTxBuf = TxQue+QUEUE_SIZE/2;
SemA.CodecTxDataRdy = TRUE;
}
else
{
if(TxQTail==QUEUE_SIZE/2)
{
pActiveTxBuf = TxQue;
SemA.CodecTxDataRdy = TRUE;
}
}
return tmp;
}
//DCI中断服务子程序
void __attribute__((__interrupt__)) _DCIInterrupt(void)
{
int tmp;
switch( CmdStage )
{
case CMD_STAGE0:
TXBUF0 = GetTxQue();
TXBUF1 = GetTxQue();
TXBUF2 = GetTxQue();
TXBUF3 = GetTxQue();
PutRxQue(RXBUF0);
PutRxQue(RXBUF1);
PutRxQue(RXBUF2);
tmp = RXBUF3; //调整时钟的相位
if(ClkAdjTrig > 0) //如果需要插入采样
PutRxQue(tmp);
if(ClkAdjTrig >= 0) //如果不须,则跳过
PutRxQue(tmp);
ClkAdjTrig = 0;
break;
case CMD_STAGE1:
TXBUF0 = GetTxQue();
TXBUF1 = GetTxQue();
TXBUF2 = GetTxQue();
TXBUF3 = GetTxQue() | 1; //告诉编码解码器下一个值是命令
PutRxQue(RXBUF0);
PutRxQue(RXBUF1);
PutRxQue(RXBUF2);
PutRxQue(RXBUF3);
CmdStage = CMD_STAGE2;
break;
case CMD_STAGE2:
TXBUF0 = CodecCmd; //插入编码解码器命令
TXBUF1 = GetTxQue(); //取采样数据
TXBUF2 = 0x0000; //写虚拟值
TXBUF3 = 0x0000; //写虚拟值
PutRxQue(RXBUF0);
PutRxQue(RXBUF1);
PutRxQue(RXBUF2);
PutRxQue(RXBUF3);
CmdStage = CMD_STAGE3;
break;
case CMD_STAGE3:
TXBUF0 = GetTxQue();
TXBUF1 = GetTxQue();
TXBUF2 = GetTxQue();
TXBUF3 = GetTxQue();
PutRxQue(RXBUF0);
PutRxQue(RXBUF1);
PutRxQue(RXBUF2);
PutRxQue(RXBUF3);
//设置DCI缓冲长度为2
DCICON2 = DCI_BUFF_LEN_2 & DCI_FRAME_LEN_8 & DCI_DATA_WORD_16;
CmdStage = CMD_STAGE4;
break;
case CMD_STAGE4:
TXBUF0 = GetTxQue();
TXBUF1 = GetTxQue();
TXBUF2 = GetTxQue();
TXBUF3 = GetTxQue();
CodecCmd = RXBUF0;
PutRxQue(RXBUF1);
//设置DCI缓冲长度为4
DCICON2 = DCI_BUFF_LEN_4 & DCI_FRAME_LEN_16 & DCI_DATA_WORD_16;
CmdStage = CMD_STAGE0;
break;
}
IFS2bits.DCIIF = 0; // 清DCI中断标志
}
//初始化DCI和编码解码器
void InitCodec(void)
{
int i;
for(i=0; i<QUEUE_SIZE ;i++)
{
RxQue[i] = 0;
TxQue[i] = 0;
}
TxQTail = 0;
RxQHead = 0;
SemA.CodecRxDataRdy = FALSE;
SemA.CodecTxDataRdy = FALSE;
CmdStage = CMD_STAGE0;
CodecCmd = 0;
ClkAdjTrig = 0;
TRISFbits.TRISF6 = 1; //编码解码器(Codec)引脚为输入
/* 配置DCI接收/传送中断*/
ConfigIntDCI( DCI_INT_ON & DCI_INT_PRI_6);
/* 配置DCI模块用于传送16位数据且工作在多通道模式*/
/*详细的位定义请参见文件 dci.h */
OpenDCI( DCI_EN & DCI_IDLE_CON &
DCI_DIGI_LPBACK_DIS &
DCI_SCKD_OUP &
DCI_FSD_OUP &
DCI_SAMP_CLK_FAL &
DCI_TX_ZERO_UNF &
DCI_SDO_TRISTAT &
// DCI_SDO_ZERO &
DCI_DJST_OFF &
DCI_FSM_MULTI,
DCI_BUFF_LEN_4 & DCI_FRAME_LEN_16 & DCI_DATA_WORD_16,
( CLOCK_FREQ / ( 2 * FRAMECLKRATE) ) - 1,
~DCI_DIS_SLOT_0,
~DCI_DIS_SLOT_0
);
LATFbits.LATF6 = 0; //复位编码解码器
TRISFbits.TRISF6 = 0;
TimeDelay(1);
TRISFbits.TRISF6 = 1; //编码解码器设为输入
TimeDelay(1);
//发送编码解码器的设定参数
WriteCodecCtrl( CODEC_N1, 1-1); //N=1
WriteCodecCtrl( CODEC_M1, 20-1); //M=20
WriteCodecCtrl( CODEC_CTRL_1,CODEC_PARM_LPD|CODEC_PARM_SPD );
WriteCodecCtrl( CODEC_CTRL_2, 0); //Div除以5, HPF使能
WriteCodecCtrl( CODEC_RXGAIN, CODEC_PARM_HIM|CODEC_PARM_MCG0|CODEC_PARM_LIG0);
WriteCodecCtrl( CODEC_ADCVOL, CODEC_PARM_LOM| (23<<2) );
WriteCodecCtrl( CODEC_DACVOL, CODEC_PARM_SLM|CODEC_PARM_SRM|(23<<2) );
WriteCodecCtrl( CODEC_ATTN, CODEC_PARM_SOT0|CODEC_PARM_LOT0);
}
//写命令到编码解码器子程序
void WriteCodecCtrl( unsigned char adr, unsigned char parm )
{
CodecCmd = (unsigned int)adr;
CodecCmd = (CodecCmd<<8) & 0x1F00;
CodecCmd += (unsigned int)parm;
CmdStage = CMD_STAGE1;
while( CmdStage != CMD_STAGE0 ){}
}
//从编码解码器读命令子程序
unsigned char ReadCodecCtrl( unsigned char adr )
{
CodecCmd = (unsigned int)adr;
CodecCmd = (CodecCmd<<8) & 0x1F00;
CodecCmd |= 0x2000;
CmdStage = CMD_STAGE1;
while( CmdStage != CMD_STAGE0 ){}
return CodecCmd&0x00FF;
}
//调整时钟子程序
void AdjustClock( char shift )
{
ClkAdjTrig = shift;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -