OSDN Git Service

Merge branch 'suikan_experimental2' into develop
[trx-305dsp/dsp.git] / hirado / 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 && 0x7FFF )<< 16  |
342                 1 << 15                          |
343                  radio.flags && 0x7FFF;          // flagsのbit15は0なので、indexも0になる
344     }
345
346         // プライマリ・チャンネルの組み立て
347     *pri_ch = ((unsigned int)right << 16) | (unsigned short)left;
348
349
350     framework.index = ! framework.index;  // indexの論理反転
351 }
352
353 /**
354  * \brief ワイドFMのRX-IFデータを解析する
355  * \param pri_ch プライマリ・チャンネルからのデータ
356  * \param sec_ch セカンダリ・チャンネルからのデータ
357  * \param idata 抽出したIデータ。[-1,1.0)の固定小数点形式
358  * \param qdata 抽出したQデータ。[-1,1.0)の固定小数点形式
359  * \detail
360  */
361 static void unpack_wide_fm ( unsigned int pri_ch, unsigned int sec_ch, int* idata, int* qdata )
362 {
363     int command, data, exp, i, q;
364
365
366         // iデータとqデータを抽出する。両者とも16bitで、bit14からbit29に格納されている
367     i = ( pri_ch << 2 ) & 0xFFFF0000;
368     q = ( sec_ch << 2 ) & 0xFFFF0000;
369
370         // ブロック浮動小数点処理。expでスケーリングする。
371     exp = ( pri_ch >> 10 ) & 0x0F;
372     *idata = i >> exp;
373     *qdata = q >> exp;
374
375 #ifdef DEBUG_BLOCK_FLOAT
376     {
377         static int tested = 0;
378         if ( (i & 0x80000000) && ! tested )
379         {
380             tested = 1;
381             syslog( LOG_NOTICE, "i: %8x, exp: %d, idata:%8x", i, exp, *idata);
382         }
383     }
384 #endif
385         // パラメータ・データを配列に格納する。
386         // 配列インデックスは comaddr、データはcomdataから。
387         // comdataはpri/secに分散している。
388
389     command = ( pri_ch >> 6 ) & 0x0F;
390     data =
391             (( pri_ch << 10 ) & 0xF000) |      //
392             (( sec_ch >> 2 ) & 0x0FFF);
393         // パラメータ・データをrx_parameter.data配列に格納する。
394         // 配列インデックスは comaddr、データはcomdataから。
395
396     set_command_data( command, data);
397
398     radio.comdata[ command ] = data;
399 }
400
401 /**
402  * \brief 非ワイドFMのRX-IFデータを解析する
403  * \param pri_ch プライマリ・チャンネルからのデータ
404  * \param sec_ch セカンダリ・チャンネルからのデータ
405  * \param idata 抽出したIデータ。[-1,1.0)の固定小数点形式。valid_iqが真の時のみ有効
406  * \param qdata 抽出したQデータ。[-1,1.0)の固定小数点形式。valid_iqが真の時のみ有効
407  * \param valid_iq IQデータが有効の時真、無効の時は偽
408  * \detail
409  */
410
411 static void unpack_non_wide_fm(  unsigned int pri_ch, unsigned int sec_ch, int* idata, int* qdata, int* valid_iq )
412 {
413         // インデックス分け
414     if ( sec_ch & 0x02 )    // bit1が1ならindex = 1
415     {
416             // IQデータはbit[29:2]に格納されている
417         *idata = (pri_ch << 2) & 0xFFFFFFF0;
418         *qdata = (sec_ch << 2) & 0xFFFFFFF0;
419             // IQデータが有効であると通知する
420         *valid_iq = TRUE;
421     }
422     else                    // index = 0
423     {
424             // ラジオパラメータ
425         int command, data;
426
427         command = ( pri_ch >> 6 ) & 0x0F;
428         data = ( sec_ch >> 2 ) & 0xFFFF;
429             // パラメータ・データをrx_parameter.data配列に格納する。
430             // 配列インデックスは comaddr、データはcomdataから。
431
432         set_command_data( command, data);
433
434             // IQデータが無効であると通知する
435         *valid_iq = FALSE;
436     }
437 }
438
439 /**
440  * \brief SHからのコマンドとパラメタを保存する
441  * \param command コマンド種別
442  * \param data コマンドパラメータ
443  * \details このルーチンはSHからFPGA経由で受け取ったコマンドとそのデータを内部変数に格納する。
444  * 格納されたデータはユーザーが実装した復調アルゴリズムから、API経由で利用される。
445  */
446 static void set_command_data( unsigned int command, unsigned int data )
447 {
448 #ifdef DEBUG_COMMAND
449        if ( radio.comdata[command] != data ){
450            syslog(LOG_NOTICE, "Command : %d, Data : %d", command, data );
451        }
452 #endif
453         radio.comdata[ command ] = data;
454
455 }
456
457
458 /**
459  * \brief SPORT0 受信割り込みハンドラ
460  * \details このルーチンはcfgファイルで宣言され、SPORT0 RX 割り込みハンドラとして登録される。
461  * SPORT0 RX DMAがバッファの受信を終えるたびに呼び出される。
462  * 割り込み専有時間を小さくするため、実際には、割り込みのクリアと受信タスクへの通知しかしていない。
463  */
464 void sport0_rx_int_handler(void)
465 {
466         // DMA割り込みをクリアする。
467     *pDMA1_IRQ_STATUS = DMA_DONE;
468         // タスクにSPORT0受信DMAのバッファが埋まったと知らせる。
469     syscall(isig_sem(SEM_SPORT0_RX)); // デバッグとりあえずタスクは殺しておく。
470         // ペリフェラルへの書き込みを待つ。
471     ssync();
472
473 }
474
475 /**
476  * \brief SPORT0 送信割り込みハンドラ
477  * \details このルーチンはcfgファイルで宣言され、SPORT0 TX 割り込みハンドラとして登録される。
478  * SPORT0 TX DMAがバッファの送信を終えるたびに呼び出される。
479  * 割り込み専有時間を小さくするため、実際には、割り込みのクリアと送信タスクへの通知しかしていない。
480  */
481 void sport0_tx_int_handler(void)
482 {
483         // DMA割り込みをクリアする。
484     *pDMA2_IRQ_STATUS = DMA_DONE;
485
486         // タスクにSPORT0送信DMAのバッファが空いたと知らせる。
487      syscall(isig_sem(SEM_SPORT0_TX));
488          // ペリフェラルへの書き込みを待つ。
489      ssync();
490
491 }
492
493 /**
494  * \brief ペリフェラルの初期化
495  * \param p イニシャライザにコンフィギュレータから与えられる数値。使っていない。
496  * \details この関数はATT_INIによってコンフィギュレータによりイニシャライザとして
497  * 登録される。システムが起動すると、マルチタスク処理が始まる前にこの関数が一度だけ呼ばれる。
498  */
499
500 void init_peripherals(VP_INT p)
501 {
502         // ペリフェラルをディセーブルにする
503     *pSPORT0_TCR1 = 0;
504     *pSPORT0_RCR1 = 0;
505     *pDMA1_CONFIG = 0;
506     *pDMA2_CONFIG = 0;
507     *pSPI_CTL = 0;
508     *pSIC_IMASK = 0;
509     ssync();
510 }
511
512 /**
513  * \brief SPORT0 RX 関連の初期化
514  * \details この関数は、\ref rx_if_task から一度だけ呼び出される。呼び出されると、
515  * DMAバッファをクリアし、SPORT0 RX関係のレジスタを然るべき値で初期化する。
516  */
517
518 static void init_sport0_rx(void)
519 {
520     int i;
521
522         // DMAバッファを明示的にクリアする
523     for ( i = 0; i < RXIF_BUFSIZE; i++)
524     {
525         framework.rxif_buffer[0][i] = 0;
526         framework.rxif_buffer[0][i] = 0;
527     }
528
529         // 受信SPORTの設定。WORD長は30bitで、アーリー同期信号。外部クロック入力。
530     *pSPORT0_RCR1 =
531             0 << 14 |   // RCKFE,   0:sample at down edge, 1:sample at up edge
532             0 << 13 |   // LARFS,   0:early frame sync, 1:late frame sync
533             0 << 12 |   // LRFS,    0:Active high RFS, 1:Active low RFS
534             1 << 10 |   // RFSR,    0:RFS is not required every word, 1:RFS is required every word
535             0 << 9  |   // IRFS,    0:external RFS, 1:internal RFS
536             0 << 4  |   // RLSBIT,  0:MSB first transmission, 1:LSB first transmission
537             0 << 2  |   // RDTYPE   0:zero fill, 1:sign extend, 2:u-law, 3:a-law
538             0 << 1  |   // IRCLK,   0:external clock generation, 1:internal clock generation
539             0 << 0  ;   // RSPEN    0:Rx disable, 1:Rx enable
540
541     *pSPORT0_RCR2 =
542             0 << 10 |   // RRFST,   0:left streo ch first, 1:right stereo ch first
543             0 << 9  |   // RSFESE,  0:normal frame sync, 1:LR frame clock
544             1 << 8  |   // RXSE,    0:secondary ch disable, 1:secondary ch enable
545            29 << 0  ;   // SLEN     0-1:not allowed,2-31:Serial word length - 1
546
547     ssync();
548
549
550         // 受信DMAデスクリプタを作る
551     framework.rx_dma_dsc[0].next_descripter = &framework.rx_dma_dsc[1];
552     framework.rx_dma_dsc[1].next_descripter = &framework.rx_dma_dsc[0];
553
554     framework.rx_dma_dsc[1].start_address = framework.rxif_buffer[1];
555     framework.rx_dma_dsc[0].start_address = framework.rxif_buffer[0];
556
557     framework.rx_dma_dsc[0].x_count =
558     framework.rx_dma_dsc[1].x_count = RXIF_BUFSIZE;
559
560     framework.rx_dma_dsc[0].x_modify =
561     framework.rx_dma_dsc[1].x_modify = sizeof(framework.rxif_buffer[1][0]);
562
563     framework.rx_dma_dsc[0].config =
564     framework.rx_dma_dsc[1].config =
565             FLOW_LARGE      |   // FLOW,    0:Stop, 1:Auto buffer, 4:Desc array, 6:Desc List small, 7:Desc, List, Large
566             NDSIZE_7        |   // NDSIZE,  the # of element of the next descripter to fetch
567             1 << DI_EN_P    |   // DI_EN,   0:No interrupt at the end, 1:Interrupt at the end
568             0 << DI_SEL_P   |   // DI_SEL,  0:Interrupt at the end of outer loop, 1:Interrupt at the end of inter loop
569             0 << RESTART_P  |   // RESTART, 0:Keep DMA FIFO before start, 1:Purge DMA FIFO before start
570             0 << DMA2D_P    |   // DMA2D,   0:Linear DMA, 1:2D DMA
571             WDSIZE_32       |   // WDSIZE,  0:8bit, 1:16bit, 2:32bit,3:reserved
572             1 << WNR_P      |   // WNR,     0:Read from memory, 1:Write to Memory
573             1 << 0          ;   // DMA_EN,  0:Disable DMA, 1:Enable DMA
574
575
576         // SPORT0 受信DMAコントローラの初期状態設定
577         // ここではDMAをイネーブルにしない。また、バッファクリアする
578     *pDMA1_CONFIG =
579             FLOW_LARGE      |   // FLOW,    0:Stop, 1:Auto buffer, 4:Desc array, 6:Desc List small, 7:Desc, List, Large
580             NDSIZE_7        |   // NDSIZE,  the # of element of the next descripter to fetch
581             1 << DI_EN_P    |   // DI_EN,   0:No interrupt at the end, 1:Interrupt at the end
582             0 << DI_SEL_P   |   // DI_SEL,  0:Interrupt at the end of outer loop, 1:Interrupt at the end of inter loop
583             1 << RESTART_P  |   // RESTART, 0:Keep DMA FIFO before start, 1:Purge DMA FIFO before start
584             0 << DMA2D_P    |   // DMA2D,   0:Linear DMA, 1:2D DMA
585             WDSIZE_32       |   // WDSIZE,  0:8bit, 1:16bit, 2:32bit,3:reserved
586             1 << WNR_P      |   // WNR,     0:Read from memory, 1:Write to Memory
587             0 << 0          ;   // DMA_EN,  0:Disable DMA, 1:Enable DMA
588     *pDMA1_NEXT_DESC_PTR = &framework.rx_dma_dsc[0];
589
590
591 }
592
593 /**
594  * \brief SPORT0 TX 関連の初期化
595  * \details この関数は、\ref rx_if_task から一度だけ呼び出される。呼び出されると、
596  * DMAバッファをクリアし、SPORT0 RX関係のレジスタを然るべき値で初期化する。
597  */
598
599 static void init_sport0_tx(void)
600 {
601     int i;
602
603         // DMAバッファを明示的にクリアする
604     for ( i = 0; i < AF_BUFSIZE; i++)
605     {
606         framework.af_buffer[0][i] = 0;
607         framework.af_buffer[0][i] = 0;
608     }
609
610
611         // 送信SPORTの設定。WORD長は31bitで、アーリー同期信号。外部クロック入力。
612     *pSPORT0_TCR1 =
613             0 << 14 |   // TCKFE,   0:sample at down edge, 1:sample at up edge
614             0 << 13 |   // LATFS,   0:early frame sync, 1:late frame sync
615             0 << 12 |   // LTFS,    0:Active high TFS, 1:Active low TFS
616             0 << 11 |   // DITFS,   0:data dependent TFS generation, 1:data independent TFS generation
617             1 << 10 |   // TFSR,    0:TFS is not required every word, 1:TFS is required every word
618             1 << 9  |   // ITFS,    0:external TFS, 1:internal TFS
619             0 << 4  |   // TLSBIT,  0:MSB first transmission, 1:LSB first transmission
620             0 << 2  |   // TDTYPE   0:normal, 1:reserved, 2:u-law, 3:a-law
621             0 << 1  |   // ITCLK,   0:external clock generation, 1:internal clock generation
622             0 << 0  ;   // TSPEN    0:Tx disable, 1:Tx enable
623
624     *pSPORT0_TCR2 =
625             0 << 10 |   // TRFST,   0:left streo ch first, 1:right stereo ch first
626             0 << 9  |   // TSFESE,  0:normal frame sync, 1:LR frame clock
627             1 << 8  |   // TXSE,    0:secondary ch disable, 1:secondary ch enable
628            30 << 0  ;   // SLEN     0-1:not allowed,2-31:Serial word length - 1
629
630     *pSPORT0_TFSDIV = 255;  // TFS period -1 ( The period is 256 )
631
632
633         // 送信DMAデスクリプタを作る
634         // 注意:制御の都合上、最初はDMA割り込みをオフにしておく。これは
635         // DMA及びSPORT FIFOへの書き込みによるスタート後のラッシュで割り込みが
636         // 起きないようにするためである。ラッシュで送信されるのはダミーデータのみ
637         // である。rx_if_taskの初期化部でSPORT受信部を起動する際に、送信部の割り込みも
638         // 有効にする。
639     framework.tx_dma_dsc[0].next_descripter = &framework.tx_dma_dsc[1];
640     framework.tx_dma_dsc[1].next_descripter = &framework.tx_dma_dsc[0];
641
642     framework.tx_dma_dsc[0].start_address = framework.af_buffer[0];
643     framework.tx_dma_dsc[1].start_address = framework.af_buffer[1];
644
645     framework.tx_dma_dsc[0].x_count =
646     framework.tx_dma_dsc[1].x_count = AF_BUFSIZE;
647
648     framework.tx_dma_dsc[0].x_modify =
649     framework.tx_dma_dsc[1].x_modify = sizeof(framework.af_buffer[0][0]);
650
651     framework.tx_dma_dsc[0].config =
652     framework.tx_dma_dsc[1].config =
653             FLOW_LARGE      |   // FLOW,    0:Stop, 1:Auto buffer, 4:Desc array, 6:Desc List small, 7:Desc, List, Large
654             NDSIZE_7        |   // NDSIZE,  the # of element of the next descripter to fetch
655             0 << DI_EN_P    |   // DI_EN,   0:No interrupt at the end, 1:Interrupt at the end
656             0 << DI_SEL_P   |   // DI_SEL,  0:Interrupt at the end of outer loop, 1:Interrupt at the end of inter loop
657             0 << RESTART_P  |   // RESTART, 0:Keep DMA FIFO before start, 1:Purge DMA FIFO before start
658             0 << DMA2D_P    |   // DMA2D,   0:Linear DMA, 1:2D DMA
659             WDSIZE_32       |   // WDSIZE,  0:8bit, 1:16bit, 2:32bit,3:reserved
660             0 << WNR_P      |   // WNR,     0:Read from memory, 1:Write to Memory
661             1 << 0          ;   // DMA_EN,  0:Disable DMA, 1:Enable DMA
662
663
664         // SPORT0 送信DMAコントローラの初期状態設定
665         // ここではDMAをイネーブルにしない。また、バッファクリアする
666     *pDMA2_CONFIG =
667             FLOW_LARGE      |   // FLOW,    0:Stop, 1:Auto buffer, 4:Desc array, 6:Desc List small, 7:Desc, List, Large
668             NDSIZE_7        |   // NDSIZE,  the # of element of the next descripter to fetch
669             0 << DI_EN_P    |   // DI_EN,   0:No interrupt at the end, 1:Interrupt at the end
670             0 << DI_SEL_P   |   // DI_SEL,  0:Interrupt at the end of outer loop, 1:Interrupt at the end of inter loop
671             1 << RESTART_P  |   // RESTART, 0:Keep DMA FIFO before start, 1:Purge DMA FIFO before start
672             0 << DMA2D_P    |   // DMA2D,   0:Linear DMA, 1:2D DMA
673             WDSIZE_32       |   // WDSIZE,  0:8bit, 1:16bit, 2:32bit,3:reserved
674             0 << WNR_P      |   // WNR,     0:Read from memory, 1:Write to Memory
675             0 << 0          ;   // DMA_EN,  0:Disable DMA, 1:Enable DMA
676     *pDMA2_NEXT_DESC_PTR = &framework.tx_dma_dsc[0];
677
678 }
679
680 /**
681  * \brief デバッグ用モニタ・タスク
682  * \param exinf cfgファイルに記述されたパラメタを受け取る引数。使っていない。
683  * \details 一定時間ごとにシステム状態をモニターする。通常は使っていないが、
684  * 開発時に各種システム量を計算、取得するために動かす低順位タスクである。
685  */
686
687 void monitor_task(VP_INT exinf)
688 {
689
690     while(1)
691     {
692 #ifdef DEBUG_DSPLOAD
693         unsigned int cycle_start, cycle_end, total_idle_cycle, total_cycle;
694         {// DSP負荷の計算(前処理)
695
696             idle_cycle = 0;
697             asm volatile ("r0 = cycles;%0 = r0;" : "=d"(cycle_start) : : "R0");
698         }
699 #endif // DEBUG_DSPLOAD
700
701         tslp_tsk(1000);     // 1秒待つ
702
703 #ifdef DEBUG_DSPLOAD
704         {// DSP負荷の計算(後処理)
705             asm volatile ("r0 = cycles;%0 = r0;" : "=d"(cycle_end) : : "R0");
706
707                 // ここまでの通算時間を取得する
708             total_cycle = cycle_end - cycle_start;
709                 // ここまでの通算アイドル時間を取得する
710             total_idle_cycle = idle_cycle;
711
712
713                 // 計算しやすいようにスケーリング
714             total_cycle >>= 16;
715             total_idle_cycle >>=16;
716
717             syslog(LOG_NOTICE, "DSP Load : %d%%", (total_cycle - total_idle_cycle) * 100 / total_cycle);
718         }
719 #endif // DEBUG_DSPLOAD
720
721 #ifdef DEBUG_QUEUEDEPTH
722         { // AF TASK, RX IF TAXK間のキューの深さを報告する
723
724             syslog( LOG_NOTICE, "Queue depth max : %d, min : %d ", debug_queue_max, debug_queue_min);
725         }
726 #endif // DEBUG_QUEUEDEPTH
727
728 #ifdef DEBUG_COMMAND_API
729         syslog( LOG_NOTICE, "radio_api_getARM_mode() %d",  radio_api_getARM_mode() );
730         syslog( LOG_NOTICE, "radio_api_getAIS_if_shift() %d",  radio_api_getAIS_if_shift() );
731         syslog( LOG_NOTICE, "radio_api_getAAT_attack() %d",  radio_api_getAAT_attack() );
732         syslog( LOG_NOTICE, "radio_api_getAFA_fade() %d",  radio_api_getAFA_fade() );
733         syslog( LOG_NOTICE, "radio_api_getAST_noise_squelch_level() %d",  radio_api_getAST_noise_squelch_level() );
734         syslog( LOG_NOTICE, "radio_api_getACP_cw_pitch() %d",  radio_api_getACP_cw_pitch() );
735         syslog( LOG_NOTICE, "radio_api_getADN_denoiser() %d",  radio_api_getADN_denoiser() );
736         syslog( LOG_NOTICE, "radio_api_getAAN_auto_notch() %d",  radio_api_getAAN_auto_notch() );
737         syslog( LOG_NOTICE, "radio_api_getAGL_gain_level() %d",  radio_api_getAGL_gain_level() );
738         syslog( LOG_NOTICE, "radio_api_getAIF_filter() %d",  radio_api_getAIF_filter() );
739         syslog( LOG_NOTICE, "radio_api_getABN_noise_blanker_on() %d",  radio_api_getABN_noise_blanker_on());
740         syslog( LOG_NOTICE, "radio_api_getARG_agc_on() %d",  radio_api_getARG_agc_on());
741         syslog( LOG_NOTICE, "radio_api_getANE_noise_squelch_on() %d",  radio_api_getANE_noise_squelch_on());
742         syslog( LOG_NOTICE, "radio_api_getAAF_hpf() %d",  radio_api_getAAF_hpf() );
743         syslog( LOG_NOTICE, "radio_api_getAAF_lpf() %d",  radio_api_getAAF_lpf() );
744         syslog( LOG_NOTICE, "radio_api_getAVP_voice_squelch_level() %d",  radio_api_getAVP_voice_squelch_level() );
745         syslog( LOG_NOTICE, "radio_api_getAVS_voice_squelch_on() %d",  radio_api_getAVS_voice_squelch_on() );
746 #endif // DEBUG_COMMAND_API
747
748     }
749 }