OSDN Git Service

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