📄 codec_processing_isr.asm
字号:
/*******************************************************************************************************
(C) Copyright 2002 - Analog Devices, Inc. All rights reserved.
File Name: Codec_Processing_ISR.asm
Date Modified: 4/11/02 Rev 1.0
Purpose: AD1881 SPORT0 TX/RX INTERRUPT SERVICE ROUTINE
Receives LINEIN input from the AD1881 via SPORT0 and then transmits the audio data back out to the
AD1881 Stereo DACs/Head-phone Outputs
This ISR version assumes the use of the default 48kHz pro audio sample rate, in which data is valid for
every audio frame. Therefore, TAG slot info and ADC valid bit synchronization is not as critical,
since the tag bits and ADC valid bits are being set by the AD1881 and the DSP every time there is a
new audio frame (and thus a new interrupt) Therefore, the RX Interrupt can be used for audio processing
after codec initialization. This makes it somewhat easier to initialize the codec, while saving
the user the extra overhead and code space for programming the codec to use it's variable sample rate
features.
*****************************************************************************************************/
// ADSP-21160 System Register bit definitions
#include "bandpass.h"
//#include <def21160.h>
#include "AD1881_Registers.h"
.GLOBAL Level_Buffer;
.GLOBAL Process_AD1881_Audio_Samples;
.GLOBAL Left_Channel_In;
.GLOBAL Right_Channel_In;
.GLOBAL Left_Channel_Out;
.GLOBAL Right_Channel_Out;
.GLOBAL RX_left_flag;
.GLOBAL RX_right_flag;
.EXTERN tx_buf;
.EXTERN rx_buf;
.EXTERN process_audio;
.EXTERN filtering;
.EXTERN fir;
.segment /dm seg_dmda;
// AD1881 stereo-channel data holders - used for DSP processing of audio data recieved from codec
.VAR Left_Channel_In; // Input values from AD1881 ADCs
.VAR Right_Channel_In;
.VAR Left_Channel_Out; // Output values for AD1881 DACs
.VAR Right_Channel_Out;
.VAR RX_left_flag; // DSP algorithm only processed when these bits are set
.VAR RX_right_flag;
.VAR ADC_valid_bits;
.var Level_Buffer[256];
.var total;
// AC'97 audio frame/ISR counter, for debug purposes
.VAR audio_frame_timer = 0;
.endseg;
.segment /pm seg_pmco;
Process_AD1881_Audio_Samples:
// Build Transmit Tag Phase Slot Information
r0 = 0x8000; // Set Valid Frame bit 15 in slot 0 tag phase
dm(tx_buf + TAG_PHASE) = r0; // Write tag to tx-buf ASAP before it's shifted out of SPORT!
r0 = 0; // Clear AC97 link Audio Output Frame slots for now
dm(tx_buf + COMMAND_ADDRESS_SLOT) = r0;
dm(tx_buf + COMMAND_DATA_SLOT) = r0;
dm(tx_buf + LEFT) = r0;
dm(tx_buf + RIGHT) = r0;
check_ADCs_for_valid_data:
r0 = dm(rx_buf + TAG_PHASE); // Get ADC valid bits from tag phase slot
r1 = 0x1800; // Inspect for valid L/R ADC data
r2 = r0 and r1; // Mask other bits in tag
dm(ADC_valid_bits) = r2;
set_tx_slot_valid_bits:
r1 = dm(tx_buf + TAG_PHASE); // set tx valid bits based on ADC valid bits info
r4 = r2 or r1; // set left/right channel bits in tag, if required
dm(tx_buf + TAG_PHASE) = r4; // Write tag to tx-buf ASAP before it's shifted out of SPORT!
R6 = 0;
R7 = 0;
check_AD1881_ADC_left:
BTST r2 by M_Left_ADC; // Check Master left ADC valid bit
IF sz JUMP check_AD1881_ADC_right; // If valid data then save ADC sample
r8 = dm(rx_buf + LEFT); // get Master 1881 left channel input sample
r8 = lshift r8 by 16; // shift up to MSBs to preserve sign in 1.31 format
dm(Left_Channel_In) = r8; // save to data holder for processing
r4 = 1;
dm(RX_left_flag) = r4; // if we have a new left sample, let the DSP filter routine know
r8 = lshift r8 by -16;
check_AD1881_ADC_right:
BTST r2 by M_Right_ADC; // Check Master right ADC valid bit
If sz rti; // If valid data then save ADC sample
r8 = dm(rx_buf + RIGHT); // get Master 1881 right channel input sample
r8 = lshift r8 by 16; // shift up to MSBs to preserve sign in 1.31 format
dm(Right_Channel_In) = r8; // save to data holder for processing
r4 = 1;
dm(RX_right_flag) = r4; // if we have a new right sample, let the DSP filter routine know
// --------------------------------------------------------------------------------------------
// user_applic( ) - User Applications Routines
// *** Insert DSP Algorithms Here ***
//
// Input L/R Data Streams - DM(Left_Channel_In) DM(Right_Channel_In)
// Output L/R Results - DM(Left_Channel_Out) DM(Right_Channel_Out)
//
// These left/right data holders are used to pipeline data through multiple modules, and
// can be removed if the dsp programmer needs to save instruction cycles
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Coding TIP:
// The samples from the AD1881 are 16-bit and are in the lower 16 bits of the the 32-bit
// word. They are shifted to the most significant bit positions in order to preserve the
// sign of the samples when they are converted to floating point numbers. The values are
// also scaled to the range +/-1.0 with the integer to float conversion
// (f0 = float r0 by r1).
//
// To convert between our assumed 1.31 fractional number and IEEE floating point math,
// here are some example assembly instructions ...
//
// r1 = -31 <-- scale the sample to the range of +/-1.0
// r0 = DM(Left_Channel);
// f0 = float r0 by r1;
// [Call Floating_Point_Algorithm]
// r1 = 31; <-- scale the result back up to MSBs
// r8 = fix f8 by r1;
// DM(Left_Channel) = r8;
// --------------------------------------------------------------------------------------------
user_applic:
// do audio processing on input samples
r4 = 0x0; // since we are not using the right flag, always clear
dm(RX_right_flag) = r4; // since left & right come in pairs at same fs rate, we
// only need one flag (because we powered down ADCs for L/R sync).
// Thus, the user can optionally remove the right flag set/clear
// instructions to save cycles
r4 = dm(RX_left_flag);
r4 = pass r4;
if eq jump playback_audio_data; // if RX_left_flag = 1, then do audio processing
// reverb routine will clear RX_left_flag
do_audio_processing:
R0 = dm(filtering); // are we filtering or not
R0 = pass R0;
if eq jump skip_to_no_processing;
call (pc, fir); // call the fir routine
jump playback_audio_data;
skip_to_no_processing:
r1 = -31; // scale the sample to the range of +/-1.0
r0 = DM(Left_Channel_In); // get left AD1881 input sample
r2 = DM(Right_Channel_In); // get right AD1881 input sample
f0 = float r0 by r1; // convert to floating point
f2 = float r2 by r1;
// insert floating point processing algorithm here
r1 = 31; // scale the result back up to MSBs
r0 = fix f0 by r1; // convert back to fixed point
r2 = fix f2 by r1;
DM(Left_Channel_Out) = r0; // send left channel result to AD1881 Left DAC
DM(Right_Channel_Out) = r2; // send right channel result to AD1881 Right DAC
// ---- DSP processing is finished, now playback results to AD1881 ----
playback_audio_data:
r4 = 0; // if selecting slower sample rates, this flag clear instruction is required
dm(RX_left_flag) = r4; // clear RX_left_flag since we have processed incoming data
// Transmit Left and Right Valid Data every time there the ADCs have valid data
r2 = dm(ADC_valid_bits);
tx_AD1881_DAC_left:
BTST r2 by M_Left_ADC; // Check to see if we need to send DAC right sample
IF sz JUMP tx_AD1881_DAC_right; // If valid data then transmit DAC sample
r12 = dm(Left_Channel_Out); // get channel 1 output result
r12 = lshift r12 by -16; // put back in bits 0..15 for SPORT tx
dm(tx_buf + LEFT) = r12; // output right result to AD1881 Slot 3
tx_AD1881_DAC_right:
BTST r2 by M_Right_ADC; // Check to see if we need to send DAC right sample
If sz jump tx_done; // If valid data then transmit DAC sample
r12 = dm(Right_Channel_Out); // get channel 2 output result
r12 = lshift r12 by -16; // put back in bits 0..15 for SPORT tx
dm(tx_buf + RIGHT) = r12; // output right result to AD1881 Slot 4
tx_done:
r0=dm(audio_frame_timer); // get last count
rti(db); // return from interrupt, delayed branch
r0=r0+1; // increment count
dm(audio_frame_timer)=r0; // save updated count
// -----------------------------------------------------------------------------------------
RTI;
Process_AD1881_Audio_Samples.end:
.endseg;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -