後で読めるように記録してください〜
最初は、21489 AD1939Cブロックベースのトークスルー48または96kHzのケースを理解できると思いました。このケースを見るだけで理解できます。実際、違いはかなり大きいです。
良い習慣を身に付け、最初にケースのReadme部分を見てください。
このプロジェクトには、オンボードAD1939を使用してオーディオストリームを取得および出力するトークスルーの例が含まれています。デジタルオーディオデータは、ファイルSPORT1_ISR_processor_samples_.asmで処理できます。ブロックTheサイズはオーディオチャネルあたり256サンプルです
。Baiduの直訳は次のとおりです。このプロジェクトでは、オンボードAD1939を使用してオーディオストリームをキャプチャおよび出力します。デジタルオーディオデータは、SPORT1_ISR_processor_samples.asmファイルで処理されます。ブロックサイズは、オーディオチャネルあたり256サンプルです。VisualDSP ++ケースの解釈の21489AD1939Cブロックベーストークスルー48または96kHzに関する記事を
参照してください。このケースのデジタルオーディオデータ処理は、SPORT1_isr.c。ファイルで行われます。これは別のポイントです。
では、.asmファイルはどのような形式ですか?オンライン資料の参照:ASMはアセンブリ言語ソースプログラムの拡張であり、アセンブリ言語(Assembly Language)はマシン指向プログラミング言語です。アセンブリ言語は強力なプログラミング言語であり、コンピューターのすべてのハードウェア特性を使用し、ハードウェアを直接制御できる言語です。
さて、コンパイル。。。
続きを読むReadme
AD1939は、48/96 / 192Khzのサンプリングレートに設定できます。ADCはSPORT0Aに接続されます。DAC1はSPORT1Aに接続され、DAC2はSPORT 1Aに、DAC3はSPORT1Aに、DAC4(ヘッドフォン出力)はSPORT1Aに接続されます。すべてコーデックのチャネルはTDMモードでアクセスされます。コーデックへのアクセスに使用されるDAIピンの詳細については、initSRU.cを参照してください。OUT2
の出力は遅延し、ユーザーはエコー効果を聞くことができます
。Baiduのリテラル変換は次のとおりです。 AD1939 48/96 / 192Khzサンプリングレートに設定できます。ADCはSPORT0Aに接続されています。DAC1、DAC2、DAC3、DAC4(ヘッドフォン出力)はすべてSPORT1Aに接続されています。コーデックのすべてのチャネルは、TDMモードでアクセスされます。コーデックへのアクセスに使用されるDAIピンの詳細については、initSRU.cファイルを参照してください。
言い換えると、ハードウェアのピン構成は、VisualDSP ++の場合の21489AD1939Cブロックベースのトークスルー48または96kHzの記事を解釈する場合と同じであり、知識のこの部分は同じです。
最後の文はOUT2の出力遅延についてであり、ユーザーはエコー効果を聞くことが期待できます。
接下来看下该案例所包含的文件:
ソースファイルがこのディレクトリに含ま:
21489 AD1939 CサンプリングさベースTalkthru 48または96 kHz.dpj -----------のVisualDSPプロジェクトファイル
ad1939.h - --------- AD1939レジスタのマクロ定義
ADDS_21489_EzKit.h -----------すべてのファイルに使用されるインクルードと外部宣言
init1939viaSPI.c ----------- ADSP-21489ソース- AD1939 SPI制御ポートサブルーチン
initSRU.c ----------- AD1939に接続するためのDAIピンとSRUを設定
initPLL_SDRAM.c -----------コアを400MHzに構成し、SDRAMメモリを有効にします
main.c -----------メインセクションでセットアップルーチンProcess_audio.cを呼び出します
-----------複数のオーディオデータストリームを処理します
SPORT01_TDM_init.c ----------- AD1939SPORT1_ISR_process_samples_.asmと通信するためにSPORTDMAを初期化し
ます------- ----プロセスSPORT1割り込み
VisualDSP ++のデフォルトに含まれる依存関係には、パスが含まれます
。def21489.h ----------- ADSP-21489の一般的な定義を
含むヘッダーファイルSRU.h ----------- SRU定義を含むヘッダーファイルおよびマクロ
前のケース(下の図に示す)と比較すると、主な違いは次のとおりです。1)この場合のSPORT1割り込み関数はSPORT1_ISR_process_samples_.asmファイルにあります。2)Process_audio.cファイルは複数のオーディオを処理するために使用されます。前のケースでは、blockProcess_audio.cファイルを使用してオーディオデータブロックを処理します。
この場合のプロジェクトツリー図を見てください。プロジェクトツリーに
追加のSinetbl.datファイルがあり、そこにオーディオデータが保存され、1次元配列形式で保存されます。最初の数行SPORT1_ISR_process_samples_.asmファイルのコード行がコメント化されています。:
//#define GENERATE_DAC_PURE_TONES_TEST
コメントをキャンセルすると、プログラムのコンパイルと実行時に純音が鳴り、デフォルトでケースが閉じられます。
次に、main関数の内容とコードを見てみましょう。
/
// (c) Copyright 2009 - Analog Devices, Inc. //
// NAME: main.c (sample-based Talkthrough) //
// DATE: 02/06/10 //
// PURPOSE: Function main() for AD1939/ADSP-21489 Talkthrough framework. //
// USAGE: This file contains the main routine calls functions to set up the talkthrough //
// routine. //
// Author: VS., Analog Devices, Inc //
/
#include "ADDS_21489_EzKit.h"
float *DelayLine;
int Index = 0;
int Sine_Index = 0;
int SPORT1_isr_count = 0;
int SPORT0_isr_count = 0;
void SPORT1_isr_counter(void);
void SPORT0_isr_counter(void);
void main()
{
initPLL_SDRAM(); // Initialize the PLL and SDRAM controller,时钟配置,位于init_PLL_SDRAM.c文件里
InitDAI(); // Initialize DAI because the SPORT and SPI signals need to be routed,DAI配置,位于initSRU.c文件里
Init1939viaSPI(); // This function will configure the AD1939 codec on the 21489 EZ-KIT,SPI配置,比较好理解
enable_SPORT01_MCM_mode(); // Turn on SPORT0 TX and SPORT1 RX for Multichannel Operation,SPORT配置,位于SPORT01_TDM_init.c文件里
interrupts(SIG_SP1, process_AD1939_samples); // Unmask SPORT1 RX ISR Interrupt,当SIG_SP1中断发生,运行process_AD1939_samples中断函数,比较好理解
// Enable multichannel operation (SPORT mode and DMA in standby and ready)
*pSPMCTL0 |= MCEA;
*pSPMCTL1 |= MCEA;
SinTableInit(); // 只有//#define GENERATE_DAC_PURE_TONES_TEST取消注释才有用,这里不用关注
DelayLine = (float *) 0x000C4000; // Set up small delay buffer
for (;;)
{
asm("idle;");
}
}
InitDAI()関数は前のケースの説明を参照できますが、今回はenable_SPORT01_MCM_mode()関数とprocess_AD1939_samples割り込みサービス関数に焦点を当てます。
まず、enable_SPORT01_MCM_mode()関数を見てください
void enable_SPORT01_MCM_mode()
{
// Clear out SPORT 0/1 registers
// SPMCTLx(SPORT Multichannel Control Registers),SPCTLx(Serial Control Registers),这两个寄存器所有位至0
*pSPMCTL0 = 0; *pSPMCTL1 = 0; *pSPCTL0 = 0; *pSPCTL1 = 0;
// External clock and frame syncs generated by AD1939
// DIVx(SPORT Divisor Registers),高16位用于frame syncs的除数,低16位用于clock的除数
*pDIV0 = 0x00000000; // Transmitter (SPORT0)
*pDIV1 = 0x00000000; // Receiver (SPORT1) at 12.288 MHz SCLK and 48 kHz sample rate
// SPORT0 and SPORT1 are being operated in "multichannel" mode. This is synonymous with TDM mode which is the operating mode for the AD1939
// SP01MCTL = 0x000000E2, Hold off on MCM enable, and number of TDM slots to 8 active channels
// Multichannel Frame Delay=1, Number of Channels = 8, LB disabled
// NCH = Actual number of channel slots – 1,MFD(Multichannel Frame Delay):
*pSPMCTL0 = NCH7 | MFD1; // NCH7即[5:7]=111,MFD1即[1]=1,1个串行时钟周期,即0x000000E2;
*pSPMCTL1 = NCH7 | MFD1; // 参考上面的解释
// Enable chain pointer registers before enabling DMA
xmit0a_tcb[4] = *pCPSP0A = ((int) xmit0a_tcb + 7) & 0x7FFFF | (1<<19);
rcv1a_tcb[4] = *pCPSP1A = ((int) rcv1a_tcb + 7) & 0x7FFFF | (1<<19);
// sport1 control register set up as a receiver in MCM
// externally generated SCLK1 and RFS1
// SDEN_A,Enable Channel A Serial Port DMA,0:Disable,1:Enable
// SCHEN_A,Enable Channel A Serial Port DMA Chaining,0:Disable,1:Enable
// SLEN,Serial Word Length Select.
// sport 1 control register SPCTL1 = 0x000C01F0
*pSPCTL1 = SCHEN_A | SDEN_A | SLEN32; // SCHEN_A即[19]=1, SDEN_A即[18]=1,SLEN32即[4:8]=11111
// sport0 control register set up as a transmitter in MCM
// SPTRAN,Data Transfer Direction,0 = Receive on both channels A and B,1 = Transmit on both channels A and B.
*pSPCTL0 = SCHEN_A | SDEN_A | SPTRAN | SLEN32;
// sport1 receive & sport0 transmit multichannel word enable registers
// enable receive channels 0-7
// enable transmit channels 0-7
*pMR1CS0 = *pMT0CS0 =0x000000FF;
// sport1 & sport0 receive & transmit multichannel companding enable registers
// no companding for our 8 active timeslots*/
// no companding on SPORT1 receive */
// no companding on SPORT0 transmit */
*pMR1CCS0 = *pMT0CCS0 = 0;
}
この場合のenable_SPORT01_MCM_mode()関数と前の場合のvoid InitSPORT()関数のオーバーラップ率は80%を超えています。この関数を理解するには、「ADSP21489_ハードウェアリファレンスマニュアル」を使用する必要があります。関係するレジスタの各ビットの情報。つまり、この機能は主に21489チップのレジスタを構成するためのものです。ケースの説明とリファレンスマニュアルを使用して、このコードをさらに説明しました。このコードは、コードで確認できます。
さらに、この場合のmain.c関数のコードは次のとおりです。
// Enable multichannel operation (SPORT mode and DMA in standby and ready)
*pSPMCTL0 |= MCEA;
*pSPMCTL1 |= MCEA;
このコードは、前のケースのvoid InitSPORT()関数のコードでもあります。このケースをmain.cに個別に配置する必要がある理由は明確ではありません。
次に、process_AD1939_samples関数を見てください
void process_AD1939_samples( int sig_int)
{
/* Perform AD1939 Audio Processing Here Using 32-bit Floating-point Math.(Note: The ADC/DAC variables below are used to "double-buffer" the audio samples with temporary variables, allowing active DMA completion of rx1a_buf[] and tx0a_buf[]) */
Receive_ADC_Samples(); // 从ADC采集信号
/* Loop back AD1939 ADC1 data to DAC1 */
Left_Channel_Out1 = Left_Channel_In2; // 直接将输入信号传至输出端口
Right_Channel_Out1 = Right_Channel_In2;
/* create a simple stereo digital delay on internal AD1939 stereo DAC2 channels */
/* Delay-line length must not exceed usable seg_dmda memory addresses! */
Left_Channel_Out2 = Left_Channel_In2; // 左输入信号不经过处理直接传至左输出端口
Right_Channel_Out2 = DelayLine[Index] + Right_Channel_In2; // 右输入信号与上一时刻的右输入信号叠加,一起传至左输出端口
DelayLine[Index++] = Right_Channel_In2; // 将此次的右输入信号保存到缓存中
if (Index == 16000) Index = 0;
/* loop back ADC1 audio data to other DACs 3 & 4 */
Left_Channel_Out3 = Left_Channel_In1;
Right_Channel_Out3 = Right_Channel_In1;
Left_Channel_Out4 = Left_Channel_In1;
Right_Channel_Out4 = Right_Channel_In1;
Transmit_DAC_Samples(); // 将处理好的信号发送至DAC
}
process_AD1939_samples()関数には、アセンブリによって記述された2つの関数Receive_ADC_Samples()とTransmit_DAC_Samples()が含まれています。他のコードは理解するのが難しくありません。以下に示すように、アセンブルされた2つの関数はSPORT1_ISR_process_samples_.asmファイルにあります。
_Receive_ADC_Samples:
.global _Receive_ADC_Samples;
/* get AD1939 left channel input samples, save to data holders for processing */
r1 = -31;
r0 = dm(_rx1a_buf + Internal_ADC_L1); f0 = float r0 by r1; dm(_Left_Channel_In1) = r0;
r0 = dm(_rx1a_buf + Internal_ADC_L2); f0 = float r0 by r1; dm(_Left_Channel_In2) = r0;
/* get AD1939 right channel input samples, save to data holders for processing */
r0 = dm(_rx1a_buf + Internal_ADC_R1); f0 = float r0 by r1; dm(_Right_Channel_In1) = r0;
r0 = dm(_rx1a_buf + Internal_ADC_R2); f0 = float r0 by r1; dm(_Right_Channel_In2) = r0;
r0 = DM(AD1939_audio_frame_timer);
r0 = r0 + 1;
DM(AD1939_audio_frame_timer) = r0;
leaf_exit;
_Receive_ADC_Samples.end:
_Transmit_DAC_Samples:
.global _Transmit_DAC_Samples;
r1 = 31;
/* output processed left ch audio samples to AD1939 */
r0 = dm(_Left_Channel_Out1); r0 = trunc f0 by r1; dm(_tx0a_buf + Internal_DAC_L1) = r0;
r0 = dm(_Left_Channel_Out2); r0 = trunc f0 by r1; dm(_tx0a_buf + Internal_DAC_L2) = r0;
r0 = dm(_Left_Channel_Out3); r0 = trunc f0 by r1; dm(_tx0a_buf + Internal_DAC_L3) = r0;
r0 = dm(_Left_Channel_Out4); r0 = trunc f0 by r1; dm(_tx0a_buf + Internal_DAC_L4) = r0;
/* output processed right ch audio samples to AD1939 */
r0 = dm(_Right_Channel_Out1); r0 = trunc f0 by r1; dm(_tx0a_buf + Internal_DAC_R1) = r0;
r0 = dm(_Right_Channel_Out2); r0 = trunc f0 by r1; dm(_tx0a_buf + Internal_DAC_R2) = r0;
r0 = dm(_Right_Channel_Out3); r0 = trunc f0 by r1; dm(_tx0a_buf + Internal_DAC_R3) = r0;
r0 = dm(_Right_Channel_Out4); r0 = trunc f0 by r1; dm(_tx0a_buf + Internal_DAC_R4) = r0;
#ifdef GENERATE_DAC_PURE_TONES_TEST
Call make_DAC_Pure_Tones;
#endif
leaf_exit;
_Transmit_DAC_Samples.end:
アセンブリを学習していません。Receive_ADC_Samples()が同時に8チャネルの入力信号を収集でき、Transmit_DAC_Samples()関数が同時に8チャネルに異なる信号を出力できることを知っているだけです。このスキルはSPORT独自のスキルであり、関連するマニュアルを参照して学ぶことができます。
さて、今日はたくさん書きましょう。
備考:
ソフトウェア開発に関連する技術交流のためにメッセージまたはプライベートメッセージを残すことができます(LabVIEW、Matlab、STM32、ADSPはすべて利用可能です)