3 #include <t_services.h>
4 #include <s_services.h>
10 #define PARAMDATA_NUM 16
12 static void init_sport0_rx(void);
13 static void init_sport0_tx(void);
14 static void pack_af_sample( short left, short right, int * pri_ch, int * sec_ch1);
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 );
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;
29 struct dma_descripter rx_dma_dsc[2];
30 struct dma_descripter tx_dma_dsc[2];
32 unsigned int rxif_buffer[2][RXIF_BUFSIZE];
33 unsigned int af_buffer[2][AF_BUFSIZE];
34 int index; // パッカーが使う。現在のワードインデックスが0か1か
39 unsigned short smeter;
40 unsigned short comdata[PARAMDATA_NUM];
46 * \brief RX_IF受信データの処理タスク
47 * \param cfgファイルから値を渡すための引数。使っていない
48 * \details 受信データをDMAバッファから取り出して復調し、データキューに
49 * 書き込む。データキューは \ref af_task との共用である。
51 * また、受信DMA内のRX-IFデータにはコマンドが含まれている。これらの
52 * コマンドを内部変数に記録して復調器がりようできるようにしておく。
54 void rx_if_task(VP_INT exinf)
58 vmsk_log(LOG_UPTO(LOG_INFO), LOG_UPTO(LOG_EMERG));
59 syslog(LOG_NOTICE, "Sample program starts (exinf = %d).", (INT) exinf);
61 syscall(serial_ctl_por(TASK_PORTID,
62 (IOCTL_CRLF | IOCTL_FCSND | IOCTL_FCRCV)));
64 framework.index = FALSE; // パッカーのインデックスの初期値設定。実のところ、初期値はランダムでも構わない。
67 for ( i=0; i<PARAMDATA_NUM; i++)
73 // SPORT0の送受割り込み受付を可能にする
74 syscall(ena_int(INTNO_SPORT0_RX));
75 syscall(ena_int(INTNO_SPORT0_TX));
78 init_sport0_tx(); // 送信DMA開始。割り込みはまだ生成しない
79 init_sport0_rx(); // 受信DMA開始。割り込みイネーブル。
81 // AF送信を開始する。ただし、送信DMA割り込みはまだ発生しない。
82 *pDMA2_CONFIG |= DMAEN; // TX SPORT DMA Enable
83 *pSPORT0_TCR1 |= RSPEN; // TX SPORT Enable
86 tslp_tsk(1); // DMAがFIFOを充填するのに十分な時間待つ。
87 syscall(act_tsk(TASK_AF)); // AFデータ送信タスクをアクティブにする
89 // 頃合いなので送信DMA割り込みを開始する。
90 // CPUロックするのは割り込みにより、タイミングがずれるのを嫌って。
92 framework.tx_dma_dsc[0].config |= 1 << DI_EN_P;
93 framework.tx_dma_dsc[1].config |= 1 << DI_EN_P;
96 // RX受信を開始する。転送と同時に割り込みが始まる
97 *pDMA1_CONFIG |= DMAEN; // RX SPORT DMA Enable
98 *pSPORT0_RCR1 |= RSPEN; // RX SPORT Enable
114 // SPORT0受信DMAがバッファを埋めるのを待つ。
115 syscall(wai_sem(SEM_SPORT0_RX));
118 if ( count > 31500/(RXIF_BUFSIZE/4))
121 // FIFOにデータがたまったはずである。
122 // FIFOデータを読みだして下位2bitのみ表示する
123 rx[0] = framework.rxif_buffer[1][0]; // 下位2bitのみ抽出
124 rx[1] = framework.rxif_buffer[1][1]; // 下位2bitのみ抽出
125 rx[2] = framework.rxif_buffer[1][2]; // 下位2bitのみ抽出
126 rx[3] = framework.rxif_buffer[1][3]; // 下位2bitのみ抽出
128 syslog( LOG_NOTICE, "RX word : %08x,%08x,%08x,%08x", rx[0], rx[1], rx[2], rx[3] );
138 syslog(LOG_NOTICE, "rx_if_task ends.");
144 * \brief AF送信データの処理タスク。
145 * \param exinf cfgファイルに記述されたパラメタを受け取る引数。使っていない。
146 * \details データキューから取り出したAF信号をDMAバッファに転送する。
147 * このタスクは受信データ処理タスクより優先順位が高い。これは、DMAの送信割り込みへの
148 * 応答が遅れると、バッファを埋め終わる前に送信が始まってしまうからである。
150 * このタスクではあまり多くの時間を割くべきではなく、そのため、データキューへデータを
151 * 送り込む段階でAFデータの組み立ては終わっている。また、データの初期化などは全部
154 void af_task(VP_INT exinf)
156 syslog( LOG_NOTICE, "TASK_AF activatred!" );
161 syscall(wai_sem(SEM_SPORT0_TX));
167 syslog( LOG_NOTICE, "AF Interrupt" );
175 * \brief AFサンプルをパックしてデータキューに書き込みできる形式に変換する
176 * \param left 左チャンネルのオーディオデータ。[-1,1.0)の固定小数点形式
177 * \param right 右チャンネルのオーディオデータ。[-1,1.0)の固定小数点形式
178 * \param pri_ch パック済みオーディオデータ。最初にデータキューにコピーする。
179 * \param sec_ch パック済みオーディオデータ。2番めにデータキューにコピーする。
181 * 与えられたステレオ・データから、データキュー書き込み用のデータを組み立てる。
182 * 書き込みデータはSPORTのプライマリ・チャンネル用、セカンダリ・チャンネル用がある。
183 * さらに、これらがindex ==0 および 1の場合に別れる。
185 * この関数はindexを af_ctrl.index で管理しており、その値に応じて適切な
186 * プライマリ・チャンネル、セカンダリ・チャンネル用のデータを組み立てる。
188 * なお、セカンダリ・チャンネルはindex = 1の時にサブ・オーディオを伝送するが、
189 * TRX-305はサブ・オーディオを使わないためこのルーチンは常に値を0としている。
191 static void pack_af_sample( short left, short right, int * pri_ch, int * sec_ch)
193 // オーディオデータは15bitしか使わない。Rchの16bit目は0に固定する
194 right >>= 1; // 15bitに変換
195 right &= 0x7FFF; // 本当はMSBは無視されるのだが、念の為0にする
197 left >>= 1; //15bitに変換
199 if ( framework.index )
201 left |= 0x8000; // MSBを1にする
203 // indexが1のとき、セカンダリチャンネルはサブオーディオとなっている。
204 // TRX-305はサブオーディオを使わないのでindexデータのみ送る
205 *sec_ch = 0x00008000;
209 left &= 0x7FFF; // MSBを0にする
211 // indexが0のとき、セカンダリオーディオはDSPからSH2へのデータ回線である
214 radio.flags; // flagsのbit15は0なので、indexも0になる
218 *pri_ch = (right << 16) | left;
221 framework.index = ! framework.index; // indexの論理反転
225 * \brief ワイドFMのRX-IFデータを解析する
226 * \param pri_ch プライマリ・チャンネルからのデータ
227 * \param sec_ch セカンダリ・チャンネルからのデータ
228 * \param idata 抽出したIデータ。[-1,1.0)の固定小数点形式
229 * \param qdata 抽出したQデータ。[-1,1.0)の固定小数点形式
232 static void unpack_wide_fm ( unsigned int pri_ch, unsigned int sec_ch, int* idata, int* qdata )
235 // iデータとqデータを抽出する。両者とも16bitで、bit14からbit29に格納されている
236 *idata = ( pri_ch << 2 ) & 0xFFFF0000;
237 *qdata = ( sec_ch << 2 ) & 0xFFFF0000;
239 // パラメータ・データを配列に格納する。
240 // 配列インデックスは comaddr、データはcomdataから。comdataはpri/secに分散している。
241 radio.comdata[ ( pri_ch >> 6 ) & 0x0F ] =
242 (( pri_ch << 6 ) & 0xF000) | //
243 (( sec_ch >> 2 ) & 0x0FFF);
247 * \brief 非ワイドFMのRX-IFデータを解析する
248 * \param pri_ch プライマリ・チャンネルからのデータ
249 * \param sec_ch セカンダリ・チャンネルからのデータ
250 * \param idata 抽出したIデータ。[-1,1.0)の固定小数点形式。valid_iqが真の時のみ有効
251 * \param qdata 抽出したQデータ。[-1,1.0)の固定小数点形式。valid_iqが真の時のみ有効
252 * \param valid_iq IQデータが有効の時真、向こうの時は偽
256 static void unpack_non_wide_fm( unsigned int pri_ch, unsigned int sec_ch, int* idata, int* qdata, int* valid_iq )
259 if ( sec_ch & 0x02 ) // bit1が1ならindex = 1
261 // IQデータはbit[29:2]に格納されている
262 *idata = (pri_ch << 2); // プライマリ・チャンネルの場合はマスク不要
263 *qdata = (sec_ch << 2) & 0xFFFFFFF0;
269 // パラメータ・データをrx_parameter.data配列に格納する。
270 // 配列インデックスは comaddr、データはcomdataから。
271 radio.comdata[ ( pri_ch >> 6 ) & 0x0F ] =
272 ( sec_ch >> 2 ) & 0xFFFF;
280 * \brief SPORT0 受信割り込みハンドラ
281 * \details このルーチンはcfgファイルで宣言され、SPORT0 RX 割り込みハンドラとして登録される。
282 * SPORT0 RX DMAがバッファの受信を終えるたびに呼び出される。
283 * 割り込み専有時間を小さくするため、実際には、割り込みのクリアと受信タスクへの通知しかしていない。
285 void sport0_rx_int_handler(void)
288 *pDMA1_IRQ_STATUS = DMA_DONE;
290 // タスクにSPORT0受信DMAのバッファが埋まったと知らせる。
291 syscall(isig_sem(SEM_SPORT0_RX));
299 * \brief SPORT0 送信割り込みハンドラ
300 * \details このルーチンはcfgファイルで宣言され、SPORT0 TX 割り込みハンドラとして登録される。
301 * SPORT0 TX DMAがバッファの送信を終えるたびに呼び出される。
302 * 割り込み専有時間を小さくするため、実際には、割り込みのクリアと送信タスクへの通知しかしていない。
304 void sport0_tx_int_handler(void)
307 *pDMA2_IRQ_STATUS = DMA_DONE;
309 // タスクにSPORT0送信DMAのバッファが空いたと知らせる。
310 syscall(isig_sem(SEM_SPORT0_TX));
319 * \param p イニシャライザにコンフィギュレータから与えられる数値。使っていない。
320 * \details この関数はATT_INIによってコンフィギュレータによりイニシャライザとして
321 * 登録される。システムが起動すると、マルチタスク処理が始まる前にこの関数が一度だけ呼ばれる。
324 void init_peripherals(VP_INT p)
337 * \brief SPORT0 RX 関連の初期化
338 * \details この関数は、\ref rx_if_task から一度だけ呼び出される。呼び出されると、
339 * DMAバッファをクリアし、SPORT0 RX関係のレジスタを然るべき値で初期化する。
342 static void init_sport0_rx(void)
347 for ( i = 0; i < RXIF_BUFSIZE; i++)
349 framework.rxif_buffer[0][i] = 0;
350 framework.rxif_buffer[0][i] = 0;
353 // 受信SPORTの設定。WORD長は30bitで、アーリー同期信号。外部クロック入力。
355 0 << 14 | // RCKFE, 0:sample at down edge, 1:sample at up edge
356 0 << 13 | // LARFS, 0:early frame sync, 1:late frame sync
357 0 << 12 | // LRFS, 0:Active high RFS, 1:Active low RFS
358 1 << 10 | // RFSR, 0:RFS is not required every word, 1:RFS is required every word
359 0 << 9 | // IRFS, 0:external RFS, 1:internal RFS
360 0 << 4 | // RLSBIT, 0:MSB first transmission, 1:LSB first transmission
361 0 << 2 | // RDTYPE 0:zero fill, 1:sign extend, 2:u-law, 3:a-law
362 0 << 1 | // IRCLK, 0:external clock generation, 1:internal clock generation
363 0 << 0 ; // RSPEN 0:Rx disable, 1:Rx enable
366 0 << 10 | // RRFST, 0:left streo ch first, 1:right stereo ch first
367 0 << 9 | // RSFESE, 0:normal frame sync, 1:LR frame clock
368 1 << 8 | // RXSE, 0:secondary ch disable, 1:secondary ch enable
369 29 << 0 ; // SLEN 0-1:not allowed,2-31:Serial word length - 1
374 framework.rx_dma_dsc[0].next_descripter = &framework.rx_dma_dsc[1];
375 framework.rx_dma_dsc[0].start_address = framework.rxif_buffer[0];
376 framework.rx_dma_dsc[0].x_count = RXIF_BUFSIZE;
377 framework.rx_dma_dsc[0].x_modify = sizeof(framework.rxif_buffer[0][0]);
378 framework.rx_dma_dsc[0].config =
379 FLOW_LARGE | // FLOW, 0:Stop, 1:Auto buffer, 4:Desc array, 6:Desc List small, 7:Desc, List, Large
380 NDSIZE_7 | // NDSIZE, the # of element of the next descripter to fetch
381 1 << DI_EN_P | // DI_EN, 0:No interrupt at the end, 1:Interrupt at the end
382 0 << DI_SEL_P | // DI_SEL, 0:Interrupt at the end of outer loop, 1:Interrupt at the end of inter loop
383 0 << RESTART_P | // RESTART, 0:Keep DMA FIFO before start, 1:Purge DMA FIFO before start
384 0 << DMA2D_P | // DMA2D, 0:Linear DMA, 1:2D DMA
385 WDSIZE_32 | // WDSIZE, 0:8bit, 1:16bit, 2:32bit,3:reserved
386 1 << WNR_P | // WNR, 0:Read from memory, 1:Write to Memory
387 1 << 0 ; // DMA_EN, 0:Disable DMA, 1:Enable DMA
389 framework.rx_dma_dsc[1].next_descripter = &framework.rx_dma_dsc[0];
390 framework.rx_dma_dsc[1].start_address = framework.rxif_buffer[1];
391 framework.rx_dma_dsc[1].x_count = RXIF_BUFSIZE;
392 framework.rx_dma_dsc[1].x_modify = sizeof(framework.rxif_buffer[1][0]);
393 framework.rx_dma_dsc[1].config =
394 FLOW_LARGE | // FLOW, 0:Stop, 1:Auto buffer, 4:Desc array, 6:Desc List small, 7:Desc, List, Large
395 NDSIZE_7 | // NDSIZE, the # of element of the next descripter to fetch
396 1 << DI_EN_P | // DI_EN, 0:No interrupt at the end, 1:Interrupt at the end
397 0 << DI_SEL_P | // DI_SEL, 0:Interrupt at the end of outer loop, 1:Interrupt at the end of inter loop
398 0 << RESTART_P | // RESTART, 0:Keep DMA FIFO before start, 1:Purge DMA FIFO before start
399 0 << DMA2D_P | // DMA2D, 0:Linear DMA, 1:2D DMA
400 WDSIZE_32 | // WDSIZE, 0:8bit, 1:16bit, 2:32bit,3:reserved
401 1 << WNR_P | // WNR, 0:Read from memory, 1:Write to Memory
402 1 << 0 ; // DMA_EN, 0:Disable DMA, 1:Enable DMA
404 // SPORT0 受信DMAコントローラの初期状態設定
405 // ここではDMAをイネーブルにしない。また、バッファクリアする
407 FLOW_LARGE | // FLOW, 0:Stop, 1:Auto buffer, 4:Desc array, 6:Desc List small, 7:Desc, List, Large
408 NDSIZE_7 | // NDSIZE, the # of element of the next descripter to fetch
409 1 << DI_EN_P | // DI_EN, 0:No interrupt at the end, 1:Interrupt at the end
410 0 << DI_SEL_P | // DI_SEL, 0:Interrupt at the end of outer loop, 1:Interrupt at the end of inter loop
411 1 << RESTART_P | // RESTART, 0:Keep DMA FIFO before start, 1:Purge DMA FIFO before start
412 0 << DMA2D_P | // DMA2D, 0:Linear DMA, 1:2D DMA
413 WDSIZE_32 | // WDSIZE, 0:8bit, 1:16bit, 2:32bit,3:reserved
414 1 << WNR_P | // WNR, 0:Read from memory, 1:Write to Memory
415 0 << 0 ; // DMA_EN, 0:Disable DMA, 1:Enable DMA
416 *pDMA1_NEXT_DESC_PTR = &framework.rx_dma_dsc[0];
422 * \brief SPORT0 TX 関連の初期化
423 * \details この関数は、\ref rx_if_task から一度だけ呼び出される。呼び出されると、
424 * DMAバッファをクリアし、SPORT0 RX関係のレジスタを然るべき値で初期化する。
427 static void init_sport0_tx(void)
432 for ( i = 0; i < AF_BUFSIZE; i++)
434 framework.af_buffer[0][i] = 0;
435 framework.af_buffer[0][i] = 0;
439 // 送信SPORTの設定。WORD長は31bitで、アーリー同期信号。外部クロック入力。
441 0 << 14 | // TCKFE, 0:sample at down edge, 1:sample at up edge
442 0 << 13 | // LATFS, 0:early frame sync, 1:late frame sync
443 0 << 12 | // LTFS, 0:Active high TFS, 1:Active low TFS
444 0 << 11 | // DITFS, 0:data dependent TFS generation, 1:data independent TFS generation
445 1 << 10 | // TFSR, 0:TFS is not required every word, 1:TFS is required every word
446 0 << 9 | // ITFS, 0:external TFS, 1:internal TFS
447 0 << 4 | // TLSBIT, 0:MSB first transmission, 1:LSB first transmission
448 0 << 2 | // TDTYPE 0:normal, 1:reserved, 2:u-law, 3:a-law
449 0 << 1 | // ITCLK, 0:external clock generation, 1:internal clock generation
450 0 << 0 ; // TSPEN 0:Tx disable, 1:Tx enable
453 0 << 10 | // TRFST, 0:left streo ch first, 1:right stereo ch first
454 0 << 9 | // TSFESE, 0:normal frame sync, 1:LR frame clock
455 0 << 8 | // TXSE, 0:secondary ch disable, 1:secondary ch enable
456 30 << 0 ; // SLEN 0-1:not allowed,2-31:Serial word length - 1
460 // 注意:制御の都合上、最初はDMA割り込みをオフにしておく。これは
461 // DMA及びSPORT FIFOへの書き込みによるスタート後のラッシュで割り込みが
462 // 起きないようにするためである。ラッシュで送信されるのはダミーデータのみ
463 // である。rx_if_taskの初期化部でSPORT受信部を起動する際に、送信部の割り込みも
465 framework.tx_dma_dsc[0].next_descripter = &framework.tx_dma_dsc[1];
466 framework.tx_dma_dsc[0].start_address = framework.af_buffer[0];
467 framework.tx_dma_dsc[0].x_count = RXIF_BUFSIZE;
468 framework.tx_dma_dsc[0].x_modify = sizeof(framework.af_buffer[0][0]);
469 framework.tx_dma_dsc[0].config =
470 FLOW_LARGE | // FLOW, 0:Stop, 1:Auto buffer, 4:Desc array, 6:Desc List small, 7:Desc, List, Large
471 NDSIZE_7 | // NDSIZE, the # of element of the next descripter to fetch
472 0 << DI_EN_P | // DI_EN, 0:No interrupt at the end, 1:Interrupt at the end
473 0 << DI_SEL_P | // DI_SEL, 0:Interrupt at the end of outer loop, 1:Interrupt at the end of inter loop
474 0 << RESTART_P | // RESTART, 0:Keep DMA FIFO before start, 1:Purge DMA FIFO before start
475 0 << DMA2D_P | // DMA2D, 0:Linear DMA, 1:2D DMA
476 WDSIZE_32 | // WDSIZE, 0:8bit, 1:16bit, 2:32bit,3:reserved
477 0 << WNR_P | // WNR, 0:Read from memory, 1:Write to Memory
478 1 << 0 ; // DMA_EN, 0:Disable DMA, 1:Enable DMA
480 framework.tx_dma_dsc[1].next_descripter = &framework.tx_dma_dsc[0];
481 framework.tx_dma_dsc[1].start_address = framework.af_buffer[1];
482 framework.tx_dma_dsc[1].x_count = RXIF_BUFSIZE;
483 framework.tx_dma_dsc[1].x_modify = sizeof(framework.af_buffer[1][0]);
484 framework.tx_dma_dsc[1].config =
485 FLOW_LARGE | // FLOW, 0:Stop, 1:Auto buffer, 4:Desc array, 6:Desc List small, 7:Desc, List, Large
486 NDSIZE_7 | // NDSIZE, the # of element of the next descripter to fetch
487 0 << DI_EN_P | // DI_EN, 0:No interrupt at the end, 1:Interrupt at the end
488 0 << DI_SEL_P | // DI_SEL, 0:Interrupt at the end of outer loop, 1:Interrupt at the end of inter loop
489 0 << RESTART_P | // RESTART, 0:Keep DMA FIFO before start, 1:Purge DMA FIFO before start
490 0 << DMA2D_P | // DMA2D, 0:Linear DMA, 1:2D DMA
491 WDSIZE_32 | // WDSIZE, 0:8bit, 1:16bit, 2:32bit,3:reserved
492 0 << WNR_P | // WNR, 0:Read from memory, 1:Write to Memory
493 1 << 0 ; // DMA_EN, 0:Disable DMA, 1:Enable DMA
495 // SPORT0 送信DMAコントローラの初期状態設定
496 // ここではDMAをイネーブルにしない。また、バッファクリアする
498 FLOW_LARGE | // FLOW, 0:Stop, 1:Auto buffer, 4:Desc array, 6:Desc List small, 7:Desc, List, Large
499 NDSIZE_7 | // NDSIZE, the # of element of the next descripter to fetch
500 0 << DI_EN_P | // DI_EN, 0:No interrupt at the end, 1:Interrupt at the end
501 0 << DI_SEL_P | // DI_SEL, 0:Interrupt at the end of outer loop, 1:Interrupt at the end of inter loop
502 1 << RESTART_P | // RESTART, 0:Keep DMA FIFO before start, 1:Purge DMA FIFO before start
503 0 << DMA2D_P | // DMA2D, 0:Linear DMA, 1:2D DMA
504 WDSIZE_32 | // WDSIZE, 0:8bit, 1:16bit, 2:32bit,3:reserved
505 0 << WNR_P | // WNR, 0:Read from memory, 1:Write to Memory
506 0 << 0 ; // DMA_EN, 0:Disable DMA, 1:Enable DMA
507 *pDMA2_NEXT_DESC_PTR = &framework.tx_dma_dsc[0];