OSDN Git Service

451c6b18405e6086f72f90190b35a47d09f24388
[trx-305dsp/dsp.git] / trx305 / framework.c
1
2
3 #include <t_services.h>
4 #include <s_services.h>
5 #include "kernel_id.h"
6 #include "framework.h"
7 #include <cdefBF533.h>
8
9
10
11 static void init_sport0_rx(void);
12 static void init_sport0_tx(void);
13 static void pack_af_sample( short left, short right, unsigned int * pri_ch, unsigned int * sec_ch);
14 static void unpack_wide_fm ( unsigned int pri_ch, unsigned int sec_ch, int* idata, int* qdata );
15 static void unpack_non_wide_fm(  unsigned int pri_ch, unsigned int sec_ch, int* idata, int* qdata, int* valid_iq );
16
17
18
19 struct dma_descripter{
20     struct dma_descripter * next_descripter;
21     unsigned int * start_address;
22     unsigned short config;
23     unsigned short x_count;
24     unsigned short x_modify;
25 };
26
27     // フレームワークの作業用内部変数
28 static struct {
29     struct dma_descripter rx_dma_dsc[2];        // FPGAからのデータDMAデスクリプタ
30     struct dma_descripter tx_dma_dsc[2];        // FPGAへのデータDMAデスクリプタ
31
32     unsigned int rxif_buffer[2][RXIF_BUFSIZE];  // FPGAからのデータDMAバッファ
33     unsigned int af_buffer[2][AF_BUFSIZE];      // FPGAへのデータDMAバッファ
34     int index;             // パッカーが使う。現在のワードインデックスが0か1か
35     short wide_fm_i[WIDE_FM_OVERSAMPE]; // Wide FMを複数サンプルまとめて処理するためのバッファ
36     short wide_fm_q[WIDE_FM_OVERSAMPE]; // Wide FMを複数サンプルまとめて処理するためのバッファ
37     int wide_fm_index;  // 次のバッファ格納位置。現在のバッファ長でもある。
38 } framework;
39
40     // ラジオアルゴリズムとのやりとりに使う変数
41  struct RADIO radio;
42
43
44     // デバッグ用変数群
45 #if defined (DEBUG_QUEUEDEPTH)
46 static  int debug_queue_level = 0;
47 static  int debug_queue_max = INT_MIN;
48 static  int debug_queue_min = INT_MAX;
49 #endif
50
51
52 /**
53  * \brief RX_IF受信データの処理タスク
54  * \param cfgファイルから値を渡すための引数。使っていない
55  * \details 受信データをDMAバッファから取り出して復調し、データキューに
56  * 書き込む。データキューは \ref af_task との共用である。
57  *
58  * また、受信DMA内のRX-IFデータにはコマンドが含まれている。これらの
59  * コマンドを内部変数に記録して復調器が利用できるようにしておく。
60  */
61 void rx_if_task(VP_INT exinf)
62 {
63     int i;
64
65         // オーディオ送信プライマリチャンネルとセカンダリチャンネルデータ
66     unsigned int af_pri_ch, af_sec_ch;
67
68     vmsk_log(LOG_UPTO(LOG_INFO), LOG_UPTO(LOG_EMERG));
69     syslog(LOG_NOTICE, "Sample program starts (exinf = %d).", (INT) exinf);
70
71     syscall(serial_ctl_por(TASK_PORTID,
72             (IOCTL_CRLF | IOCTL_FCSND | IOCTL_FCRCV)));
73
74         // データキューのプリフィル。半分まで詰める
75     for ( i=0; i<AF_QUESIZE/2; i+=2)
76     {
77         pack_af_sample(0, 0, &af_pri_ch, &af_sec_ch);
78         syscall(psnd_dtq(DTQ_AF, (VP_INT)af_pri_ch));
79         syscall(psnd_dtq(DTQ_AF, (VP_INT)af_sec_ch));
80 #ifdef DEBUG_QUEUEDEPTH
81         debug_queue_level +=2;
82         if ( debug_queue_level > debug_queue_max)
83             debug_queue_max = debug_queue_level;
84 #endif // DEBUG_QUEUEDEPTH
85     }
86
87
88     framework.index = FALSE;        // パッカーのインデックスの初期値設定。実のところ、初期値はランダムでも構わない。
89
90     framework.wide_fm_index = 0;    // 配列内部の有効データ数
91
92         // 受信機パラメタの初期化
93     for ( i=0; i<PARAMDATA_NUM; i++)
94         radio.comdata[i] = 0;
95
96     radio.flags = 0;
97     radio.smeter = 0;
98
99         // SPORT0の送受割り込み受付を可能にする
100     syscall(ena_int(INTNO_SPORT0_RX));
101     syscall(ena_int(INTNO_SPORT0_TX));
102
103         // SPORT0の送受信を初期化する。
104     init_sport0_tx();       // 送信DMA開始。割り込みはまだ生成しない
105     init_sport0_rx();       // 受信DMA開始。割り込みイネーブル。
106
107         // AF送信を開始する。ただし、送信DMA割り込みはまだ発生しない。
108     *pDMA2_CONFIG |= DMAEN;     // TX SPORT DMA Enable
109     *pSPORT0_TCR1 |= TSPEN;     // TX SPORT Enable
110     ssync();
111
112
113
114     tslp_tsk(1);      // DMAがFIFOを充填するのに十分な時間待つ。
115     syscall(act_tsk(TASK_AF));  // AFデータ送信タスクをアクティブにする
116
117         // 頃合いなので送信DMA割り込みを開始する。
118         // CPUロックするのは割り込みにより、タイミングがずれるのを嫌って。
119     loc_cpu();
120     framework.tx_dma_dsc[0].config |= 1 << DI_EN_P;
121     framework.tx_dma_dsc[1].config |= 1 << DI_EN_P;
122     unl_cpu();
123
124         // RX受信を開始する。転送と同時に割り込みが始まる
125     *pDMA1_CONFIG |= DMAEN;     // RX SPORT DMA Enable
126     *pSPORT0_RCR1 |= RSPEN;     // RX SPORT Enable
127     ssync();
128
129
130     /*
131      *  メインループ
132      *  受信DMA割り込み待ってから、DMAバッファ内部のデータを解析して然るべき受信処理を行う。
133      */
134     do {
135             // DMA転送が完了した受信バッファ
136         unsigned int* filled_buffer;
137             // next_descriptor
138         struct dma_descripter * next;
139             // ループカウンタ
140         int i;
141
142
143             // SPORT0受信DMAがバッファを埋めるのを待つ。
144         syscall(wai_sem(SEM_SPORT0_RX));
145
146
147             // SPORT0受信DMAコントローラが次にロードするデスクリプタへのポインタを取得する。
148             // このデスクリプタは、「現在使われていない」DMAデスクリプタであり、逆に言うと
149             // 割り込みが完了したDMAのデスクリプタである
150         next = (struct dma_descriptor *) *pDMA1_NEXT_DESC_PTR;
151
152             // 取得したデスクリプタから、割り込みを発生したバッファを割り出す。
153         filled_buffer = next->start_address;
154
155             // RX-IF DMAバッファ内部のデータを処理
156         for ( i= 0; i<RXIF_BUFSIZE; i+=2)
157         {
158                 // アンパック済みIQデータ
159             int idata, qdata;
160                 // デコード済みオーディオデータ
161             short left, right;
162                 // オーディオ送信プライマリチャンネルとセカンダリチャンネルデータ
163             unsigned int af_pri_ch, af_sec_ch;
164
165                 // Wide FMモードか否かを確認。
166                 // Wide FMモードフラグはプライマリチャンネルでのみ確認可能である。
167                 // プライマリ・チャンネルは必ずバッファの偶数番目に位置する。
168             if ( filled_buffer[i] & WIDE_FM_FLAG )
169             {   // Wide FMの場合
170                     // データはバッファにまとめて WIDE_FM_OVERSAMPE個ごとに処理する
171                     // 同時にFPGAから送られてくるデータも紐解いて格納する
172                 unpack_wide_fm(filled_buffer[i], filled_buffer[i+1], &idata, &qdata );
173                 framework.wide_fm_i[framework.wide_fm_index] = idata;
174                 framework.wide_fm_q[framework.wide_fm_index] = qdata;
175                 framework.wide_fm_index++;
176
177                     // IQデータが揃ったら、デコードする
178                 if ( framework.wide_fm_index >= WIDE_FM_OVERSAMPE )
179                 {
180
181                         // FM受信アルゴリズムを呼び出す
182                     radio_demodulate_wide_FM( framework.wide_fm_i, framework.wide_fm_q, &left, &right );
183                         // バッファクリア
184                     framework.wide_fm_index = 0;
185                         // デコード済みオーディオサンプルを、DMAから送信できる形式にパックする
186                     pack_af_sample( left, right, &af_pri_ch, &af_sec_ch);
187
188                         // パック済みオーディオサンプルをAFキューに送信する
189                         // キューに空きがなければ、待たずにエラーをもって帰る
190                     syscall(psnd_dtq(DTQ_AF, (VP_INT)af_pri_ch));
191                     syscall(psnd_dtq(DTQ_AF, (VP_INT)af_sec_ch));
192 #ifdef DEBUG_QUEUEDEPTH
193                     debug_queue_level += 2;
194                     if ( debug_queue_level > debug_queue_max)
195                         debug_queue_max = debug_queue_level;
196 #endif // DEBUG_QUEUEDEPTH
197                 }
198
199             }
200             else
201             {   // 非Wide FMの場合
202                     // IQデータが有効か否か
203                 int is_valid_iq;
204
205                     // 問答無用でWide FMのバッファ済みデータを消す
206                     // これで変数の値が変わるのはシステム稼働中多くても1回である。
207                     // 必要な場合だけ書き換えるとif文が増えるのでこうしている
208                 framework.wide_fm_index = 0;
209                     // 非ワイドFMデータをアンパックする
210                     // 同時にFPGAから送られてくるデータも紐解いて格納する
211                 unpack_non_wide_fm(filled_buffer[i], filled_buffer[i+1], &idata, &qdata, &is_valid_iq );
212                     // IQデータが有効の場合だけデコードする
213                 if ( is_valid_iq )
214                 {
215                         // 非ワイドFM受信アルゴリズムを呼び出す
216                     radio_demodulate_non_wide_FM( idata, qdata, &left, &right);
217                         // デコード済みオーディオサンプルを、DMAから送信できる形式にパックする
218                     pack_af_sample( left, right, &af_pri_ch, &af_sec_ch);
219                         // パック済みオーディオサンプルをAFキューに送信する
220                         // キューに空きがなければ、待たずにエラーをもって帰る
221                     syscall(psnd_dtq(DTQ_AF, (VP_INT)af_pri_ch));
222                     syscall(psnd_dtq(DTQ_AF, (VP_INT)af_sec_ch));
223 #ifdef DEBUG_QUEUEDEPTH
224                     debug_queue_level += 2;
225                     if ( debug_queue_level > debug_queue_max)
226                         debug_queue_max = debug_queue_level;
227 #endif // DEBUG_QUEUEDEPTH
228                 }
229             }   // 非ワイドFMの場合
230
231
232         }   // RX-IF DMAバッファ内部のデータを処理
233
234
235     } while (1);
236
237     syslog(LOG_NOTICE, "rx_if_task ends.");
238     kernel_exit();
239 }
240
241
242 /**
243  * \brief AF送信データの処理タスク。
244  * \param exinf cfgファイルに記述されたパラメタを受け取る引数。使っていない。
245  * \details データキューから取り出したAF信号をDMAバッファに転送する。
246  * このタスクは受信データ処理タスクより優先順位が高い。これは、DMAの送信割り込みへの
247  * 応答が遅れると、バッファを埋め終わる前に送信が始まってしまうからである。
248  *
249  * このタスクではあまり多くの時間を割くべきではなく、そのため、データキューへデータを
250  * 送り込む段階でAFデータの組み立ては終わっている。また、データの初期化などは全部
251  * RX-IF処理タスクに任せている。
252  */
253 void af_task(VP_INT exinf)
254 {
255     syslog( LOG_NOTICE, "TASK_AF activatred!" );
256
257     do{
258             // DMA転送が完了した受信バッファ
259         unsigned int* filled_buffer;
260             // next_descriptor
261         struct dma_descripter * next;
262             // ループカウンタ
263         int i;
264
265
266             // 送信が終わるのを待つ
267         syscall(wai_sem(SEM_SPORT0_TX));
268
269
270             // SPORT0送信DMAコントローラが次にロードするデスクリプタへのポインタを取得する。
271             // このデスクリプタは、「現在使われていない」DMAデスクリプタであり、逆に言うと
272             // 割り込みが完了したDMAのデスクリプタである
273         next = (struct dma_descriptor *) *pDMA2_NEXT_DESC_PTR;
274
275             // 取得したデスクリプタから、割り込みを発生したバッファを割り出す。
276         filled_buffer = next->start_address;
277
278             // ここに送信処理を書く
279             // AF DMAバッファに送信すべきデータを書く
280         for ( i= 0; i<AF_BUFSIZE; i++)
281         {
282             unsigned int data;
283
284                 // AFキューから送信すべきデータを取り出す
285                 // SVCにポーリングを使用しているため、取り出すべきデータがなければ待ちに入らずに
286                 // エラーコードを返す
287             syscall(prcv_dtq( DTQ_AF, (VP_INT)&data));
288                 // DMAバッファに書き込み
289             filled_buffer[i] = data;
290 #ifdef DEBUG_QUEUEDEPTH
291             debug_queue_level --;
292             if ( debug_queue_min >  debug_queue_level)
293                 debug_queue_min = debug_queue_level;
294 #endif // DEBUG_QUEUEDEPTH
295         }
296
297     }while (1);
298 }
299
300
301 /**
302  * \brief AFサンプルをパックしてデータキューに書き込みできる形式に変換する
303  * \param left  左チャンネルのオーディオデータ。[-1,1.0)の固定小数点形式
304  * \param right 右チャンネルのオーディオデータ。[-1,1.0)の固定小数点形式
305  * \param pri_ch パック済みオーディオデータ。最初にデータキューにコピーする。
306  * \param sec_ch パック済みオーディオデータ。2番めにデータキューにコピーする。
307  * \detail
308  * 与えられたステレオ・データから、データキュー書き込み用のデータを組み立てる。
309  * 書き込みデータはSPORTのプライマリ・チャンネル用、セカンダリ・チャンネル用がある。
310  * さらに、これらがindex ==0 および 1の場合に別れる。
311  *
312  * この関数はindexを af_ctrl.index で管理しており、その値に応じて適切な
313  * プライマリ・チャンネル、セカンダリ・チャンネル用のデータを組み立てる。
314  *
315  * なお、セカンダリ・チャンネルはindex = 1の時にサブ・オーディオを伝送するが、
316  * TRX-305はサブ・オーディオを使わないためこのルーチンは常に値を0としている。
317  */
318 static void pack_af_sample( short left, short right, unsigned int * pri_ch, unsigned int * sec_ch)
319 {
320         // オーディオデータは15bitしか使わない。Rchの16bit目は0に固定する
321     right >>= 1;        // 15bitに変換
322     right &= 0x7FFF;    // 本当はMSBは無視されるのだが、念の為0にする
323
324     left >>= 1;         //15bitに変換
325
326     if ( framework.index )
327     {
328         left |= 0x8000; // MSBを1にする
329
330             // indexが1のとき、セカンダリチャンネルはサブオーディオとなっている。
331             // TRX-305はサブオーディオを使わないのでindexデータのみ送る
332         *sec_ch = 0x00008000;
333     }
334     else
335     {
336         left &= 0x7FFF;    // MSBを0にする
337
338             // indexが0のとき、セカンダリオーディオはDSPからSH2へのデータ回線である
339         *sec_ch =
340                 radio.smeter << 16  |
341                 radio.flags;           // flagsのbit15は0なので、indexも0になる
342     }
343
344         // プライマリ・チャンネルの組み立て
345     *pri_ch = (right << 16) | left;
346
347
348     framework.index = ! framework.index;  // indexの論理反転
349 }
350
351 /**
352  * \brief ワイドFMのRX-IFデータを解析する
353  * \param pri_ch プライマリ・チャンネルからのデータ
354  * \param sec_ch セカンダリ・チャンネルからのデータ
355  * \param idata 抽出したIデータ。[-1,1.0)の固定小数点形式
356  * \param qdata 抽出したQデータ。[-1,1.0)の固定小数点形式
357  * \detail
358  */
359 static void unpack_wide_fm ( unsigned int pri_ch, unsigned int sec_ch, int* idata, int* qdata )
360 {
361     int command, data;
362
363
364         // iデータとqデータを抽出する。両者とも16bitで、bit14からbit29に格納されている
365     *idata = ( pri_ch << 2 ) & 0xFFFF0000;
366     *qdata = ( sec_ch << 2 ) & 0xFFFF0000;
367
368         // パラメータ・データを配列に格納する。
369         // 配列インデックスは comaddr、データはcomdataから。
370         // comdataはpri/secに分散している。
371
372     command = ( pri_ch >> 6 ) & 0x0F;
373     data =
374             (( pri_ch << 10 ) & 0xF000) |      //
375             (( sec_ch >> 2 ) & 0x0FFF);
376         // パラメータ・データをrx_parameter.data配列に格納する。
377         // 配列インデックスは comaddr、データはcomdataから。
378
379 #ifdef DEBUG_COMMAND
380     if ( radio.comdata[command] != data ){
381        syslog(LOG_NOTICE, "pri_ch : %8x, sec_ch : %8x, Command : %d, Data : %d", pri_ch, sec_ch, command, data );
382     }
383 #endif
384
385     radio.comdata[ command ] = data;
386 }
387
388 /**
389  * \brief 非ワイドFMのRX-IFデータを解析する
390  * \param pri_ch プライマリ・チャンネルからのデータ
391  * \param sec_ch セカンダリ・チャンネルからのデータ
392  * \param idata 抽出したIデータ。[-1,1.0)の固定小数点形式。valid_iqが真の時のみ有効
393  * \param qdata 抽出したQデータ。[-1,1.0)の固定小数点形式。valid_iqが真の時のみ有効
394  * \param valid_iq IQデータが有効の時真、向こうの時は偽
395  * \detail
396  */
397
398 static void unpack_non_wide_fm(  unsigned int pri_ch, unsigned int sec_ch, int* idata, int* qdata, int* valid_iq )
399 {
400         // インデックス分け
401     if ( sec_ch & 0x02 )    // bit1が1ならindex = 1
402     {
403             // IQデータはbit[29:2]に格納されている
404         *idata = (pri_ch << 2);                 // プライマリ・チャンネルの場合はマスク不要
405         *qdata = (sec_ch << 2) & 0xFFFFFFF0;
406             // IQデータが有効であると通知する
407         *valid_iq = TRUE;
408     }
409     else                    // index = 0
410     {
411             // ラジオパラメータ
412         int command, data;
413
414         command = ( pri_ch >> 6 ) & 0x0F;
415         data = ( sec_ch >> 2 ) & 0xFFFF;
416             // パラメータ・データをrx_parameter.data配列に格納する。
417             // 配列インデックスは comaddr、データはcomdataから。
418
419 #ifdef DEBUG_COMMAND
420        if ( radio.comdata[command] != data ){
421            syslog(LOG_NOTICE, "pri_ch : %8x, sec_ch : %8x, Command : %d, Data : %d", pri_ch, sec_ch, command, data );
422        }
423 #endif
424         radio.comdata[ command ] = data;
425             // IQデータが無効であると通知する
426         *valid_iq = FALSE;
427     }
428 }
429
430
431 /**
432  * \brief SPORT0 受信割り込みハンドラ
433  * \details このルーチンはcfgファイルで宣言され、SPORT0 RX 割り込みハンドラとして登録される。
434  * SPORT0 RX DMAがバッファの受信を終えるたびに呼び出される。
435  * 割り込み専有時間を小さくするため、実際には、割り込みのクリアと受信タスクへの通知しかしていない。
436  */
437 void sport0_rx_int_handler(void)
438 {
439         // DMA割り込みをクリアする。
440     *pDMA1_IRQ_STATUS = DMA_DONE;
441         // タスクにSPORT0受信DMAのバッファが埋まったと知らせる。
442     syscall(isig_sem(SEM_SPORT0_RX)); // デバッグとりあえずタスクは殺しておく。
443         // ペリフェラルへの書き込みを待つ。
444     ssync();
445
446 }
447
448 /**
449  * \brief SPORT0 送信割り込みハンドラ
450  * \details このルーチンはcfgファイルで宣言され、SPORT0 TX 割り込みハンドラとして登録される。
451  * SPORT0 TX DMAがバッファの送信を終えるたびに呼び出される。
452  * 割り込み専有時間を小さくするため、実際には、割り込みのクリアと送信タスクへの通知しかしていない。
453  */
454 void sport0_tx_int_handler(void)
455 {
456         // DMA割り込みをクリアする。
457     *pDMA2_IRQ_STATUS = DMA_DONE;
458
459         // タスクにSPORT0送信DMAのバッファが空いたと知らせる。
460      syscall(isig_sem(SEM_SPORT0_TX));
461          // ペリフェラルへの書き込みを待つ。
462      ssync();
463
464 }
465
466 /**
467  * \brief ペリフェラルの初期化
468  * \param p イニシャライザにコンフィギュレータから与えられる数値。使っていない。
469  * \details この関数はATT_INIによってコンフィギュレータによりイニシャライザとして
470  * 登録される。システムが起動すると、マルチタスク処理が始まる前にこの関数が一度だけ呼ばれる。
471  */
472
473 void init_peripherals(VP_INT p)
474 {
475         // ペリフェラルをディセーブルにする
476     *pSPORT0_TCR1 = 0;
477     *pSPORT0_RCR1 = 0;
478     *pDMA1_CONFIG = 0;
479     *pDMA2_CONFIG = 0;
480     *pSPI_CTL = 0;
481     *pSIC_IMASK = 0;
482     ssync();
483 }
484
485 /**
486  * \brief SPORT0 RX 関連の初期化
487  * \details この関数は、\ref rx_if_task から一度だけ呼び出される。呼び出されると、
488  * DMAバッファをクリアし、SPORT0 RX関係のレジスタを然るべき値で初期化する。
489  */
490
491 static void init_sport0_rx(void)
492 {
493     int i;
494
495         // DMAバッファを明示的にクリアする
496     for ( i = 0; i < RXIF_BUFSIZE; i++)
497     {
498         framework.rxif_buffer[0][i] = 0;
499         framework.rxif_buffer[0][i] = 0;
500     }
501
502         // 受信SPORTの設定。WORD長は30bitで、アーリー同期信号。外部クロック入力。
503     *pSPORT0_RCR1 =
504             0 << 14 |   // RCKFE,   0:sample at down edge, 1:sample at up edge
505             0 << 13 |   // LARFS,   0:early frame sync, 1:late frame sync
506             0 << 12 |   // LRFS,    0:Active high RFS, 1:Active low RFS
507             1 << 10 |   // RFSR,    0:RFS is not required every word, 1:RFS is required every word
508             0 << 9  |   // IRFS,    0:external RFS, 1:internal RFS
509             0 << 4  |   // RLSBIT,  0:MSB first transmission, 1:LSB first transmission
510             0 << 2  |   // RDTYPE   0:zero fill, 1:sign extend, 2:u-law, 3:a-law
511             0 << 1  |   // IRCLK,   0:external clock generation, 1:internal clock generation
512             0 << 0  ;   // RSPEN    0:Rx disable, 1:Rx enable
513
514     *pSPORT0_RCR2 =
515             0 << 10 |   // RRFST,   0:left streo ch first, 1:right stereo ch first
516             0 << 9  |   // RSFESE,  0:normal frame sync, 1:LR frame clock
517             1 << 8  |   // RXSE,    0:secondary ch disable, 1:secondary ch enable
518            29 << 0  ;   // SLEN     0-1:not allowed,2-31:Serial word length - 1
519
520     ssync();
521
522
523         // 受信DMAデスクリプタを作る
524     framework.rx_dma_dsc[0].next_descripter = &framework.rx_dma_dsc[1];
525     framework.rx_dma_dsc[1].next_descripter = &framework.rx_dma_dsc[0];
526
527     framework.rx_dma_dsc[1].start_address = framework.rxif_buffer[1];
528     framework.rx_dma_dsc[0].start_address = framework.rxif_buffer[0];
529
530     framework.rx_dma_dsc[0].x_count =
531     framework.rx_dma_dsc[1].x_count = RXIF_BUFSIZE;
532
533     framework.rx_dma_dsc[0].x_modify =
534     framework.rx_dma_dsc[1].x_modify = sizeof(framework.rxif_buffer[1][0]);
535
536     framework.rx_dma_dsc[0].config =
537     framework.rx_dma_dsc[1].config =
538             FLOW_LARGE      |   // FLOW,    0:Stop, 1:Auto buffer, 4:Desc array, 6:Desc List small, 7:Desc, List, Large
539             NDSIZE_7        |   // NDSIZE,  the # of element of the next descripter to fetch
540             1 << DI_EN_P    |   // DI_EN,   0:No interrupt at the end, 1:Interrupt at the end
541             0 << DI_SEL_P   |   // DI_SEL,  0:Interrupt at the end of outer loop, 1:Interrupt at the end of inter loop
542             0 << RESTART_P  |   // RESTART, 0:Keep DMA FIFO before start, 1:Purge DMA FIFO before start
543             0 << DMA2D_P    |   // DMA2D,   0:Linear DMA, 1:2D DMA
544             WDSIZE_32       |   // WDSIZE,  0:8bit, 1:16bit, 2:32bit,3:reserved
545             1 << WNR_P      |   // WNR,     0:Read from memory, 1:Write to Memory
546             1 << 0          ;   // DMA_EN,  0:Disable DMA, 1:Enable DMA
547
548
549         // SPORT0 受信DMAコントローラの初期状態設定
550         // ここではDMAをイネーブルにしない。また、バッファクリアする
551     *pDMA1_CONFIG =
552             FLOW_LARGE      |   // FLOW,    0:Stop, 1:Auto buffer, 4:Desc array, 6:Desc List small, 7:Desc, List, Large
553             NDSIZE_7        |   // NDSIZE,  the # of element of the next descripter to fetch
554             1 << DI_EN_P    |   // DI_EN,   0:No interrupt at the end, 1:Interrupt at the end
555             0 << DI_SEL_P   |   // DI_SEL,  0:Interrupt at the end of outer loop, 1:Interrupt at the end of inter loop
556             1 << RESTART_P  |   // RESTART, 0:Keep DMA FIFO before start, 1:Purge DMA FIFO before start
557             0 << DMA2D_P    |   // DMA2D,   0:Linear DMA, 1:2D DMA
558             WDSIZE_32       |   // WDSIZE,  0:8bit, 1:16bit, 2:32bit,3:reserved
559             1 << WNR_P      |   // WNR,     0:Read from memory, 1:Write to Memory
560             0 << 0          ;   // DMA_EN,  0:Disable DMA, 1:Enable DMA
561     *pDMA1_NEXT_DESC_PTR = &framework.rx_dma_dsc[0];
562
563
564 }
565
566 /**
567  * \brief SPORT0 TX 関連の初期化
568  * \details この関数は、\ref rx_if_task から一度だけ呼び出される。呼び出されると、
569  * DMAバッファをクリアし、SPORT0 RX関係のレジスタを然るべき値で初期化する。
570  */
571
572 static void init_sport0_tx(void)
573 {
574     int i;
575
576         // DMAバッファを明示的にクリアする
577     for ( i = 0; i < AF_BUFSIZE; i++)
578     {
579         framework.af_buffer[0][i] = 0;
580         framework.af_buffer[0][i] = 0;
581     }
582
583
584         // 送信SPORTの設定。WORD長は31bitで、アーリー同期信号。外部クロック入力。
585     *pSPORT0_TCR1 =
586             0 << 14 |   // TCKFE,   0:sample at down edge, 1:sample at up edge
587             0 << 13 |   // LATFS,   0:early frame sync, 1:late frame sync
588             0 << 12 |   // LTFS,    0:Active high TFS, 1:Active low TFS
589             0 << 11 |   // DITFS,   0:data dependent TFS generation, 1:data independent TFS generation
590             1 << 10 |   // TFSR,    0:TFS is not required every word, 1:TFS is required every word
591             1 << 9  |   // ITFS,    0:external TFS, 1:internal TFS
592             0 << 4  |   // TLSBIT,  0:MSB first transmission, 1:LSB first transmission
593             0 << 2  |   // TDTYPE   0:normal, 1:reserved, 2:u-law, 3:a-law
594             0 << 1  |   // ITCLK,   0:external clock generation, 1:internal clock generation
595             0 << 0  ;   // TSPEN    0:Tx disable, 1:Tx enable
596
597     *pSPORT0_TCR2 =
598             0 << 10 |   // TRFST,   0:left streo ch first, 1:right stereo ch first
599             0 << 9  |   // TSFESE,  0:normal frame sync, 1:LR frame clock
600             1 << 8  |   // TXSE,    0:secondary ch disable, 1:secondary ch enable
601            30 << 0  ;   // SLEN     0-1:not allowed,2-31:Serial word length - 1
602
603     *pSPORT0_TFSDIV = 255;  // TFS period -1 ( The period is 256 )
604
605
606         // 送信DMAデスクリプタを作る
607         // 注意:制御の都合上、最初はDMA割り込みをオフにしておく。これは
608         // DMA及びSPORT FIFOへの書き込みによるスタート後のラッシュで割り込みが
609         // 起きないようにするためである。ラッシュで送信されるのはダミーデータのみ
610         // である。rx_if_taskの初期化部でSPORT受信部を起動する際に、送信部の割り込みも
611         // 有効にする。
612     framework.tx_dma_dsc[0].next_descripter = &framework.tx_dma_dsc[1];
613     framework.tx_dma_dsc[1].next_descripter = &framework.tx_dma_dsc[0];
614
615     framework.tx_dma_dsc[0].start_address = framework.af_buffer[0];
616     framework.tx_dma_dsc[1].start_address = framework.af_buffer[1];
617
618     framework.tx_dma_dsc[0].x_count =
619     framework.tx_dma_dsc[1].x_count = AF_BUFSIZE;
620
621     framework.tx_dma_dsc[0].x_modify =
622     framework.tx_dma_dsc[1].x_modify = sizeof(framework.af_buffer[0][0]);
623
624     framework.tx_dma_dsc[0].config =
625     framework.tx_dma_dsc[1].config =
626             FLOW_LARGE      |   // FLOW,    0:Stop, 1:Auto buffer, 4:Desc array, 6:Desc List small, 7:Desc, List, Large
627             NDSIZE_7        |   // NDSIZE,  the # of element of the next descripter to fetch
628             0 << DI_EN_P    |   // DI_EN,   0:No interrupt at the end, 1:Interrupt at the end
629             0 << DI_SEL_P   |   // DI_SEL,  0:Interrupt at the end of outer loop, 1:Interrupt at the end of inter loop
630             0 << RESTART_P  |   // RESTART, 0:Keep DMA FIFO before start, 1:Purge DMA FIFO before start
631             0 << DMA2D_P    |   // DMA2D,   0:Linear DMA, 1:2D DMA
632             WDSIZE_32       |   // WDSIZE,  0:8bit, 1:16bit, 2:32bit,3:reserved
633             0 << WNR_P      |   // WNR,     0:Read from memory, 1:Write to Memory
634             1 << 0          ;   // DMA_EN,  0:Disable DMA, 1:Enable DMA
635
636
637         // SPORT0 送信DMAコントローラの初期状態設定
638         // ここではDMAをイネーブルにしない。また、バッファクリアする
639     *pDMA2_CONFIG =
640             FLOW_LARGE      |   // FLOW,    0:Stop, 1:Auto buffer, 4:Desc array, 6:Desc List small, 7:Desc, List, Large
641             NDSIZE_7        |   // NDSIZE,  the # of element of the next descripter to fetch
642             0 << DI_EN_P    |   // DI_EN,   0:No interrupt at the end, 1:Interrupt at the end
643             0 << DI_SEL_P   |   // DI_SEL,  0:Interrupt at the end of outer loop, 1:Interrupt at the end of inter loop
644             1 << RESTART_P  |   // RESTART, 0:Keep DMA FIFO before start, 1:Purge DMA FIFO before start
645             0 << DMA2D_P    |   // DMA2D,   0:Linear DMA, 1:2D DMA
646             WDSIZE_32       |   // WDSIZE,  0:8bit, 1:16bit, 2:32bit,3:reserved
647             0 << WNR_P      |   // WNR,     0:Read from memory, 1:Write to Memory
648             0 << 0          ;   // DMA_EN,  0:Disable DMA, 1:Enable DMA
649     *pDMA2_NEXT_DESC_PTR = &framework.tx_dma_dsc[0];
650
651 }
652
653 /**
654  * \brief デバッグ用モニタ・タスク
655  * \param exinf cfgファイルに記述されたパラメタを受け取る引数。使っていない。
656  * \details 一定時間ごとにシステム状態をモニターする。通常は使っていないが、
657  * 開発時に各種システム量を計算、取得するために動かす低順位タスクである。
658  */
659
660 void monitor_task(VP_INT exinf)
661 {
662
663     while(1)
664     {
665 #ifdef DEBUG_DSPLOAD
666         unsigned int cycle_start, cycle_end, total_idle_cycle, total_cycle;
667         {// DSP負荷の計算(前処理)
668
669             idle_cycle = 0;
670             asm volatile ("r0 = cycles;%0 = r0;" : "=d"(cycle_start) : : "R0");
671         }
672 #endif // DEBUG_DSPLOAD
673
674         tslp_tsk(1000);     // 1秒待つ
675
676 #ifdef DEBUG_DSPLOAD
677         {// DSP負荷の計算(後処理)
678             asm volatile ("r0 = cycles;%0 = r0;" : "=d"(cycle_end) : : "R0");
679
680                 // ここまでの通算時間を取得する
681             total_cycle = cycle_end - cycle_start;
682                 // ここまでの通算アイドル時間を取得する
683             total_idle_cycle = idle_cycle;
684
685
686                 // 計算しやすいようにスケーリング
687             total_cycle >>= 16;
688             total_idle_cycle >>=16;
689
690             syslog(LOG_NOTICE, "DSP Load : %d%%", (total_cycle - total_idle_cycle) * 100 / total_cycle);
691         }
692 #endif // DEBUG_DSPLOAD
693
694 #ifdef DEBUG_QUEUEDEPTH
695         { // AF TASK, RX IF TAXK間のキューの深さを報告する
696
697             syslog( LOG_NOTICE, "Queue depth max : %d, min : %d ", debug_queue_max, debug_queue_min);
698         }
699 #endif // DEBUG_QUEUEDEPTH
700
701     }
702 }