OSDN Git Service

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