3 #include <t_services.h>
4 #include <s_services.h>
10 static void init_sport0_rx(void);
11 static void init_sport0_tx(void);
12 static void pack_af_sample( short left, short right, int * pri_ch, int * sec_ch1);
13 static void parse_wide_fm ( unsigned int pri_ch, unsigned int sec_ch, int* idata, int* qdata );
14 static void parse_non_wide_fm( unsigned int pri_ch, unsigned int sec_ch, int* idata, int* qdata, int* valid_iq );
18 struct dma_descripter{
19 struct dma_descripter * next_descripter;
20 unsigned int * start_address;
21 unsigned short config;
22 unsigned short x_count;
23 unsigned short x_modify;
27 struct dma_descripter rx_dma_dsc[2];
28 struct dma_descripter tx_dma_dsc[2];
30 unsigned int rxif_buffer[2][RXIF_BUFSIZE];
31 unsigned int af_buffer[2][AF_BUFSIZE];
37 unsigned short smeter;
41 * \brief RX_IF受信データの処理タスク
42 * \param cfgファイルから値を渡すための引数。使っていない
43 * \details 受信データをDMAバッファから取り出して復調し、データキューに
44 * 書き込む。データキューは \ref af_task との共用である。
46 * また、受信DMA内のRX-IFデータにはコマンドが含まれている。これらの
47 * コマンドを内部変数に記録して復調器がりようできるようにしておく。
49 void rx_if_task(VP_INT exinf)
52 vmsk_log(LOG_UPTO(LOG_INFO), LOG_UPTO(LOG_EMERG));
53 syslog(LOG_NOTICE, "Sample program starts (exinf = %d).", (INT) exinf);
55 syscall(serial_ctl_por(TASK_PORTID,
56 (IOCTL_CRLF | IOCTL_FCSND | IOCTL_FCRCV)));
62 // SPORT0の送受割り込みを可能にする
63 syscall(ena_int(INTNO_SPORT0_RX));
64 syscall(ena_int(INTNO_SPORT0_TX));
67 init_sport0_tx(); // 送信DMA開始。割り込みはまだ生成しない
68 init_sport0_rx(); // 受信DMA開始。割り込みイネーブル。
70 // AF送信を開始する。ただし、送信DMA割り込みはまだ発生しない。
71 *pDMA2_CONFIG |= DMAEN; // TX SPORT DMA Enable
72 *pSPORT0_TCR1 |= RSPEN; // TX SPORT Enable
75 tslp_tsk(1); // DMAがFIFOを充填するのに十分な時間待つ。
76 syscall(act_tsk(TASK_AF)); // AFデータ送信タスクをアクティブにする
78 // 頃合いなので送信DMA割り込みを開始する。
79 // CPUロックするのは割り込みにより、タイミングがずれるのを嫌って。
81 sport_ctl.tx_dma_dsc[0].config |= 1 << DI_EN_P;
82 sport_ctl.tx_dma_dsc[1].config |= 1 << DI_EN_P;
86 *pDMA1_CONFIG |= DMAEN; // RX SPORT DMA Enable
87 *pSPORT0_RCR1 |= RSPEN; // RX SPORT Enable
103 // SPORT0受信DMAがバッファを埋めるのを待つ。
104 syscall(wai_sem(SEM_SPORT0_RX));
107 if ( count > 31500/(RXIF_BUFSIZE/4))
110 // FIFOにデータがたまったはずである。
111 // FIFOデータを読みだして下位2bitのみ表示する
112 rx[0] = sport_ctl.rxif_buffer[1][0]; // 下位2bitのみ抽出
113 rx[1] = sport_ctl.rxif_buffer[1][1]; // 下位2bitのみ抽出
114 rx[2] = sport_ctl.rxif_buffer[1][2]; // 下位2bitのみ抽出
115 rx[3] = sport_ctl.rxif_buffer[1][3]; // 下位2bitのみ抽出
117 syslog( LOG_NOTICE, "RX word : %08x,%08x,%08x,%08x", rx[0], rx[1], rx[2], rx[3] );
127 syslog(LOG_NOTICE, "Sample program ends.");
133 * \brief AF送信データの処理タスク。
134 * \param exinf cfgファイルに記述されたパラメタを受け取る引数。使っていない。
135 * \details データキューから取り出したAF信号をDMAバッファに転送する。
136 * このタスクは受信データ処理タスクより優先順位が高い。これは、DMAの送信割り込みへの
137 * 応答が遅れると、バッファを埋め終わる前に送信が始まってしまうからである。
139 * このタスクではあまり多くの時間を割くべきではなく、そのため、データキューへデータを
140 * 送り込む段階でAFデータの組み立ては終わっている。また、データの初期化などは全部
143 void af_task(VP_INT exinf)
145 syslog( LOG_NOTICE, "TASK_AF activatred!" );
150 syscall(wai_sem(SEM_SPORT0_TX));
156 syslog( LOG_NOTICE, "AF Interrupt" );
164 * \brief AFサンプルをパックしてデータキューに書き込みできる形式に変換する
165 * \param left 左チャンネルのオーディオデータ。[-1,1.0)の固定小数点形式
166 * \param right 右チャンネルのオーディオデータ。[-1,1.0)の固定小数点形式
167 * \param pri_ch パック済みオーディオデータ。最初にデータキューにコピーする。
168 * \param sec_ch パック済みオーディオデータ。2番めにデータキューにコピーする。
170 * 与えられたステレオ・データから、データキュー書き込み用のデータを組み立てる。
171 * 書き込みデータはSPORTのプライマリ・チャンネル用、セカンダリ・チャンネル用がある。
172 * さらに、これらがindex ==0 および 1の場合に別れる。
174 * この関数はindexを af_ctrl.index で管理しており、その値に応じて適切な
175 * プライマリ・チャンネル、セカンダリ・チャンネル用のデータを組み立てる。
177 * なお、セカンダリ・チャンネルはindex = 1の時にサブ・オーディオを伝送するが、
178 * TRX-305はサブ・オーディオを使わないためこのルーチンは常に値を0としている。
180 static void pack_af_sample( short left, short right, int * pri_ch, int * sec_ch)
182 // オーディオデータは15bitしか使わない。Rchの16bit目は0に固定する
183 right >>= 1; // 15bitに変換
184 right &= 0x7FFF; // 本当はMSBは無視されるのだが、念の為0にする
186 left >>= 1; //15bitに変換
190 left |= 0x8000; // MSBを1にする
192 // indexが1のとき、セカンダリチャンネルはサブオーディオとなっている。
193 // TRX-305はサブオーディオを使わないのでindexデータのみ送る
194 *sec_ch = 0x00008000;
198 left &= 0x7FFF; // MSBを0にする
200 // indexが0のとき、セカンダリオーディオはDSPからSH2へのデータ回線である
202 af_ctl.smeter << 16 |
203 af_ctl.flags; // flagsのbit15は0なので、indexも0になる
207 *pri_ch = (right << 16) | left;
210 af_ctl.index = ! af_ctl.index; // indexの論理反転
214 * \brief ワイドFMのRX-IFデータを解析する
215 * \param pri_ch プライマリ・チャンネルからのデータ
216 * \param sec_ch セカンダリ・チャンネルからのデータ
217 * \param idata 抽出したIデータ。[-1,1.0)の固定小数点形式
218 * \param qdata 抽出したQデータ。[-1,1.0)の固定小数点形式
221 static void parse_wide_fm ( unsigned int pri_ch, unsigned int sec_ch, int* idata, int* qdata )
227 * \brief 非ワイドFMのRX-IFデータを解析する
228 * \param pri_ch プライマリ・チャンネルからのデータ
229 * \param sec_ch セカンダリ・チャンネルからのデータ
230 * \param idata 抽出したIデータ。[-1,1.0)の固定小数点形式。valid_iqが真の時のみ有効
231 * \param qdata 抽出したQデータ。[-1,1.0)の固定小数点形式。valid_iqが真の時のみ有効
232 * \param valid_iq IQデータが有効の時真、向こうの時は偽
236 static void parse_non_wide_fm( unsigned int pri_ch, unsigned int sec_ch, int* idata, int* qdata, int* valid_iq )
243 * \brief SPORT0 受信割り込みハンドラ
244 * \details このルーチンはcfgファイルで宣言され、SPORT0 RX 割り込みハンドラとして登録される。
245 * SPORT0 RX DMAがバッファの受信を終えるたびに呼び出される。
246 * 割り込み専有時間を小さくするため、実際には、割り込みのクリアと受信タスクへの通知しかしていない。
248 void sport0_rx_int_handler(void)
251 *pDMA1_IRQ_STATUS = DMA_DONE;
253 // タスクにSPORT0受信DMAのバッファが埋まったと知らせる。
254 syscall(isig_sem(SEM_SPORT0_RX));
262 * \brief SPORT0 送信割り込みハンドラ
263 * \details このルーチンはcfgファイルで宣言され、SPORT0 TX 割り込みハンドラとして登録される。
264 * SPORT0 TX DMAがバッファの送信を終えるたびに呼び出される。
265 * 割り込み専有時間を小さくするため、実際には、割り込みのクリアと送信タスクへの通知しかしていない。
267 void sport0_tx_int_handler(void)
270 *pDMA2_IRQ_STATUS = DMA_DONE;
272 // タスクにSPORT0送信DMAのバッファが空いたと知らせる。
273 syscall(isig_sem(SEM_SPORT0_TX));
282 * \param p イニシャライザにコンフィギュレータから与えられる数値。使っていない。
283 * \details この関数はATT_INIによってコンフィギュレータによりイニシャライザとして
284 * 登録される。システムが起動すると、マルチタスク処理が始まる前にこの関数が一度だけ呼ばれる。
287 void init_peripherals(VP_INT p)
300 * \brief SPORT0 RX 関連の初期化
301 * \details この関数は、\ref rx_if_task から一度だけ呼び出される。呼び出されると、
302 * DMAバッファをクリアし、SPORT0 RX関係のレジスタを然るべき値で初期化する。
305 static void init_sport0_rx(void)
310 for ( i = 0; i < RXIF_BUFSIZE; i++)
312 sport_ctl.rxif_buffer[0][i] = 0;
313 sport_ctl.rxif_buffer[0][i] = 0;
316 // 受信SPORTの設定。WORD長は30bitで、アーリー同期信号。外部クロック入力。
318 0 << 14 | // RCKFE, 0:sample at down edge, 1:sample at up edge
319 0 << 13 | // LARFS, 0:early frame sync, 1:late frame sync
320 0 << 12 | // LRFS, 0:Active high RFS, 1:Active low RFS
321 1 << 10 | // RFSR, 0:RFS is not required every word, 1:RFS is required every word
322 0 << 9 | // IRFS, 0:external RFS, 1:internal RFS
323 0 << 4 | // RLSBIT, 0:MSB first transmission, 1:LSB first transmission
324 0 << 2 | // RDTYPE 0:zero fill, 1:sign extend, 2:u-law, 3:a-law
325 0 << 1 | // IRCLK, 0:external clock generation, 1:internal clock generation
326 0 << 0 ; // RSPEN 0:Rx disable, 1:Rx enable
329 0 << 10 | // RRFST, 0:left streo ch first, 1:right stereo ch first
330 0 << 9 | // RSFESE, 0:normal frame sync, 1:LR frame clock
331 1 << 8 | // RXSE, 0:secondary ch disable, 1:secondary ch enable
332 29 << 0 ; // SLEN 0-1:not allowed,2-31:Serial word length - 1
337 sport_ctl.rx_dma_dsc[0].next_descripter = &sport_ctl.rx_dma_dsc[1];
338 sport_ctl.rx_dma_dsc[0].start_address = sport_ctl.rxif_buffer[0];
339 sport_ctl.rx_dma_dsc[0].x_count = RXIF_BUFSIZE;
340 sport_ctl.rx_dma_dsc[0].x_modify = sizeof(sport_ctl.rxif_buffer[0][0]);
341 sport_ctl.rx_dma_dsc[0].config =
342 FLOW_LARGE | // FLOW, 0:Stop, 1:Auto buffer, 4:Desc array, 6:Desc List small, 7:Desc, List, Large
343 NDSIZE_7 | // NDSIZE, the # of element of the next descripter to fetch
344 1 << DI_EN_P | // DI_EN, 0:No interrupt at the end, 1:Interrupt at the end
345 0 << DI_SEL_P | // DI_SEL, 0:Interrupt at the end of outer loop, 1:Interrupt at the end of inter loop
346 0 << RESTART_P | // RESTART, 0:Keep DMA FIFO before start, 1:Purge DMA FIFO before start
347 0 << DMA2D_P | // DMA2D, 0:Linear DMA, 1:2D DMA
348 WDSIZE_32 | // WDSIZE, 0:8bit, 1:16bit, 2:32bit,3:reserved
349 1 << WNR_P | // WNR, 0:Read from memory, 1:Write to Memory
350 1 << 0 ; // DMA_EN, 0:Disable DMA, 1:Enable DMA
352 sport_ctl.rx_dma_dsc[1].next_descripter = &sport_ctl.rx_dma_dsc[0];
353 sport_ctl.rx_dma_dsc[1].start_address = sport_ctl.rxif_buffer[1];
354 sport_ctl.rx_dma_dsc[1].x_count = RXIF_BUFSIZE;
355 sport_ctl.rx_dma_dsc[1].x_modify = sizeof(sport_ctl.rxif_buffer[1][0]);
356 sport_ctl.rx_dma_dsc[1].config =
357 FLOW_LARGE | // FLOW, 0:Stop, 1:Auto buffer, 4:Desc array, 6:Desc List small, 7:Desc, List, Large
358 NDSIZE_7 | // NDSIZE, the # of element of the next descripter to fetch
359 1 << DI_EN_P | // DI_EN, 0:No interrupt at the end, 1:Interrupt at the end
360 0 << DI_SEL_P | // DI_SEL, 0:Interrupt at the end of outer loop, 1:Interrupt at the end of inter loop
361 0 << RESTART_P | // RESTART, 0:Keep DMA FIFO before start, 1:Purge DMA FIFO before start
362 0 << DMA2D_P | // DMA2D, 0:Linear DMA, 1:2D DMA
363 WDSIZE_32 | // WDSIZE, 0:8bit, 1:16bit, 2:32bit,3:reserved
364 1 << WNR_P | // WNR, 0:Read from memory, 1:Write to Memory
365 1 << 0 ; // DMA_EN, 0:Disable DMA, 1:Enable DMA
367 // SPORT0 受信DMAコントローラの初期状態設定
368 // ここではDMAをイネーブルにしない。また、バッファクリアする
370 FLOW_LARGE | // FLOW, 0:Stop, 1:Auto buffer, 4:Desc array, 6:Desc List small, 7:Desc, List, Large
371 NDSIZE_7 | // NDSIZE, the # of element of the next descripter to fetch
372 1 << DI_EN_P | // DI_EN, 0:No interrupt at the end, 1:Interrupt at the end
373 0 << DI_SEL_P | // DI_SEL, 0:Interrupt at the end of outer loop, 1:Interrupt at the end of inter loop
374 1 << RESTART_P | // RESTART, 0:Keep DMA FIFO before start, 1:Purge DMA FIFO before start
375 0 << DMA2D_P | // DMA2D, 0:Linear DMA, 1:2D DMA
376 WDSIZE_32 | // WDSIZE, 0:8bit, 1:16bit, 2:32bit,3:reserved
377 1 << WNR_P | // WNR, 0:Read from memory, 1:Write to Memory
378 0 << 0 ; // DMA_EN, 0:Disable DMA, 1:Enable DMA
379 *pDMA1_NEXT_DESC_PTR = &sport_ctl.rx_dma_dsc[0];
385 * \brief SPORT0 TX 関連の初期化
386 * \details この関数は、\ref rx_if_task から一度だけ呼び出される。呼び出されると、
387 * DMAバッファをクリアし、SPORT0 RX関係のレジスタを然るべき値で初期化する。
390 static void init_sport0_tx(void)
395 for ( i = 0; i < AF_BUFSIZE; i++)
397 sport_ctl.af_buffer[0][i] = 0;
398 sport_ctl.af_buffer[0][i] = 0;
402 // 送信SPORTの設定。WORD長は31bitで、アーリー同期信号。外部クロック入力。
404 0 << 14 | // TCKFE, 0:sample at down edge, 1:sample at up edge
405 0 << 13 | // LATFS, 0:early frame sync, 1:late frame sync
406 0 << 12 | // LTFS, 0:Active high TFS, 1:Active low TFS
407 0 << 11 | // DITFS, 0:data dependent TFS generation, 1:data independent TFS generation
408 1 << 10 | // TFSR, 0:TFS is not required every word, 1:TFS is required every word
409 0 << 9 | // ITFS, 0:external TFS, 1:internal TFS
410 0 << 4 | // TLSBIT, 0:MSB first transmission, 1:LSB first transmission
411 0 << 2 | // TDTYPE 0:normal, 1:reserved, 2:u-law, 3:a-law
412 0 << 1 | // ITCLK, 0:external clock generation, 1:internal clock generation
413 0 << 0 ; // TSPEN 0:Tx disable, 1:Tx enable
416 0 << 10 | // TRFST, 0:left streo ch first, 1:right stereo ch first
417 0 << 9 | // TSFESE, 0:normal frame sync, 1:LR frame clock
418 0 << 8 | // TXSE, 0:secondary ch disable, 1:secondary ch enable
419 30 << 0 ; // SLEN 0-1:not allowed,2-31:Serial word length - 1
423 // 注意:制御の都合上、最初はDMA割り込みをオフにしておく。これは
424 // DMA及びSPORT FIFOへの書き込みによるスタート後のラッシュで割り込みが
425 // 起きないようにするためである。ラッシュで送信されるのはダミーデータのみ
426 // である。rx_if_taskの初期化部でSPORT受信部を起動する際に、送信部の割り込みも
428 sport_ctl.tx_dma_dsc[0].next_descripter = &sport_ctl.tx_dma_dsc[1];
429 sport_ctl.tx_dma_dsc[0].start_address = sport_ctl.af_buffer[0];
430 sport_ctl.tx_dma_dsc[0].x_count = RXIF_BUFSIZE;
431 sport_ctl.tx_dma_dsc[0].x_modify = sizeof(sport_ctl.af_buffer[0][0]);
432 sport_ctl.tx_dma_dsc[0].config =
433 FLOW_LARGE | // FLOW, 0:Stop, 1:Auto buffer, 4:Desc array, 6:Desc List small, 7:Desc, List, Large
434 NDSIZE_7 | // NDSIZE, the # of element of the next descripter to fetch
435 0 << DI_EN_P | // DI_EN, 0:No interrupt at the end, 1:Interrupt at the end
436 0 << DI_SEL_P | // DI_SEL, 0:Interrupt at the end of outer loop, 1:Interrupt at the end of inter loop
437 0 << RESTART_P | // RESTART, 0:Keep DMA FIFO before start, 1:Purge DMA FIFO before start
438 0 << DMA2D_P | // DMA2D, 0:Linear DMA, 1:2D DMA
439 WDSIZE_32 | // WDSIZE, 0:8bit, 1:16bit, 2:32bit,3:reserved
440 0 << WNR_P | // WNR, 0:Read from memory, 1:Write to Memory
441 1 << 0 ; // DMA_EN, 0:Disable DMA, 1:Enable DMA
443 sport_ctl.tx_dma_dsc[1].next_descripter = &sport_ctl.tx_dma_dsc[0];
444 sport_ctl.tx_dma_dsc[1].start_address = sport_ctl.af_buffer[1];
445 sport_ctl.tx_dma_dsc[1].x_count = RXIF_BUFSIZE;
446 sport_ctl.tx_dma_dsc[1].x_modify = sizeof(sport_ctl.af_buffer[1][0]);
447 sport_ctl.tx_dma_dsc[1].config =
448 FLOW_LARGE | // FLOW, 0:Stop, 1:Auto buffer, 4:Desc array, 6:Desc List small, 7:Desc, List, Large
449 NDSIZE_7 | // NDSIZE, the # of element of the next descripter to fetch
450 0 << DI_EN_P | // DI_EN, 0:No interrupt at the end, 1:Interrupt at the end
451 0 << DI_SEL_P | // DI_SEL, 0:Interrupt at the end of outer loop, 1:Interrupt at the end of inter loop
452 0 << RESTART_P | // RESTART, 0:Keep DMA FIFO before start, 1:Purge DMA FIFO before start
453 0 << DMA2D_P | // DMA2D, 0:Linear DMA, 1:2D DMA
454 WDSIZE_32 | // WDSIZE, 0:8bit, 1:16bit, 2:32bit,3:reserved
455 0 << WNR_P | // WNR, 0:Read from memory, 1:Write to Memory
456 1 << 0 ; // DMA_EN, 0:Disable DMA, 1:Enable DMA
458 // SPORT0 送信DMAコントローラの初期状態設定
459 // ここではDMAをイネーブルにしない。また、バッファクリアする
461 FLOW_LARGE | // FLOW, 0:Stop, 1:Auto buffer, 4:Desc array, 6:Desc List small, 7:Desc, List, Large
462 NDSIZE_7 | // NDSIZE, the # of element of the next descripter to fetch
463 0 << DI_EN_P | // DI_EN, 0:No interrupt at the end, 1:Interrupt at the end
464 0 << DI_SEL_P | // DI_SEL, 0:Interrupt at the end of outer loop, 1:Interrupt at the end of inter loop
465 1 << RESTART_P | // RESTART, 0:Keep DMA FIFO before start, 1:Purge DMA FIFO before start
466 0 << DMA2D_P | // DMA2D, 0:Linear DMA, 1:2D DMA
467 WDSIZE_32 | // WDSIZE, 0:8bit, 1:16bit, 2:32bit,3:reserved
468 0 << WNR_P | // WNR, 0:Read from memory, 1:Write to Memory
469 0 << 0 ; // DMA_EN, 0:Disable DMA, 1:Enable DMA
470 *pDMA2_NEXT_DESC_PTR = &sport_ctl.tx_dma_dsc[0];