5. VisualDSP ++の場合の21489AD1939Cサンプルベースのトークスルー48または96kHzの解釈

後で読めるように記録してください〜

最初は、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はすべて利用可能です)

おすすめ

転載: blog.csdn.net/Leisure_ksj/article/details/113825297