OSDN Git Service

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