static void init_sport0_rx(void);
static void init_sport0_tx(void);
-static void pack_af_sample( short left, short right, int * pri_ch, int * sec_ch1);
+static void pack_af_sample( short left, short right, unsigned int * pri_ch, unsigned int * sec_ch);
static void unpack_wide_fm ( unsigned int pri_ch, unsigned int sec_ch, int* idata, int* qdata );
static void unpack_non_wide_fm( unsigned int pri_ch, unsigned int sec_ch, int* idata, int* qdata, int* valid_iq );
unsigned int rxif_buffer[2][RXIF_BUFSIZE];
unsigned int af_buffer[2][AF_BUFSIZE];
int index; // パッカーが使う。現在のワードインデックスが0か1か
+ short wide_fm_i[WIDE_FM_OVERSAMPE];
+ short wide_fm_q[WIDE_FM_OVERSAMPE];
+ int wide_fm_index;
} framework;
struct {
* 書き込む。データキューは \ref af_task との共用である。
*
* また、受信DMA内のRX-IFデータにはコマンドが含まれている。これらの
- * コマンドを内部変数に記録して復調器がりようできるようにしておく。
+ * コマンドを内部変数に記録して復調器が利用できるようにしておく。
*/
void rx_if_task(VP_INT exinf)
{
syscall(serial_ctl_por(TASK_PORTID,
(IOCTL_CRLF | IOCTL_FCSND | IOCTL_FCRCV)));
- framework.index = FALSE; // パッカーのインデックスの初期値設定。実のところ、初期値はランダムでも構わない。
+ framework.index = FALSE; // パッカーのインデックスの初期値設定。実のところ、初期値はランダムでも構わない。
+
+ framework.wide_fm_index = 0; // 配列内部の有効データ数
// 受信機パラメタの初期化
for ( i=0; i<PARAMDATA_NUM; i++)
- int count = 0;
/*
* メインループ
+ * 受信DMA割り込み待ってから、DMAバッファ内部のデータを解析して然るべき受信処理を行う。
*/
do {
+ // DMA転送が完了した受信バッファ
+ unsigned int* filled_buffer;
+ // next_descriptor
+ struct dma_descripter * next;
+ // ループカウンタ
+ int i;
- long int rx[4];
// SPORT0受信DMAがバッファを埋めるのを待つ。
syscall(wai_sem(SEM_SPORT0_RX));
- count++;
- if ( count > 31500/(RXIF_BUFSIZE/4))
- {
- count = 0;
- // FIFOにデータがたまったはずである。
- // FIFOデータを読みだして下位2bitのみ表示する
- rx[0] = framework.rxif_buffer[1][0]; // 下位2bitのみ抽出
- rx[1] = framework.rxif_buffer[1][1]; // 下位2bitのみ抽出
- rx[2] = framework.rxif_buffer[1][2]; // 下位2bitのみ抽出
- rx[3] = framework.rxif_buffer[1][3]; // 下位2bitのみ抽出
-
- syslog( LOG_NOTICE, "RX word : %08x,%08x,%08x,%08x", rx[0], rx[1], rx[2], rx[3] );
+ // SPORT0受信DMAコントローラが次にロードするデスクリプタへのポインタを取得する。
+ // このデスクリプタは、「現在使われていない」DMAデスクリプタであり、逆に言うと
+ // 割り込みが完了したDMAのデスクリプタである
+ next = (struct dma_descriptor *) *pDMA1_NEXT_DESC_PTR;
- }
+ // 取得したデスクリプタから、割り込みを発生したバッファを割り出す。
+ filled_buffer = next->start_address;
+ // RX-IF DMAバッファ内部のデータを処理
+ for ( i= 0; i<RXIF_BUFSIZE; i+=2)
+ {
+ // アンパック済みIQデータ
+ int idata, qdata;
+ // デコード済みオーディオデータ
+ short left, right;
+ // オーディオ送信プライマリチャンネルとセカンダリチャンネルデータ
+ unsigned int af_pri_ch, af_sec_ch;
+
+ // Wide FMモードか否かを確認。
+ // Wide FMモードフラグはプライマリチャンネルでのみ確認可能である。
+ // プライマリ・チャンネルは必ずバッファの偶数番目に位置する。
+ if ( filled_buffer[i] & WIDE_FM_FLAG )
+ { // Wide FMの場合
+ // データはバッファにまとめて WIDE_FM_OVERSAMPE個ごとに処理する
+ // 同時にFPGAから送られてくるデータも紐解いて格納する
+ unpack_wide_fm(filled_buffer[i], filled_buffer[i+1], &idata, &qdata );
+ framework.wide_fm_i[framework.wide_fm_index] = idata;
+ framework.wide_fm_q[framework.wide_fm_index] = qdata;
+ framework.wide_fm_index++;
+
+ // IQデータが揃ったら、デコードする
+ if ( framework.wide_fm_index >= WIDE_FM_OVERSAMPE )
+ {
+
+ // FM受信アルゴリズムを呼び出す
+ radio_demodulate_wide_FM( framework.wide_fm_i, framework.wide_fm_q, &left, &right );
+ // バッファクリア
+ framework.wide_fm_index = 0;
+ // デコード済みオーディオサンプルを、DMAから送信できる形式にパックする
+ pack_af_sample( left, right, &af_pri_ch, &af_sec_ch);
+
+ // パック済みオーディオサンプルをAFキューに送信する
+ // キューに空きがなければ、待たずにエラーをもって帰る
+ syscall(psnd_dtq(DTQ_AF, (VP_INT)af_pri_ch));
+ syscall(psnd_dtq(DTQ_AF, (VP_INT)af_sec_ch));
+ }
+
+ }
+ else
+ { // 非Wide FMの場合
+ // IQデータが有効か否か
+ int is_valid_iq;
+
+ // 問答無用でWide FMのバッファ済みデータを消す
+ // これで変数の値が変わるのはシステム稼働中多くても1回である。
+ // 必要な場合だけ書き換えるとif文が増えるのでこうしている
+ framework.wide_fm_index = 0;
+ // 非ワイドFMデータをアンパックする
+ // 同時にFPGAから送られてくるデータも紐解いて格納する
+ unpack_non_wide_fm(filled_buffer[i], filled_buffer[i+1], &idata, &qdata, &is_valid_iq );
+ // IQデータが有効の場合だけデコードする
+ if ( is_valid_iq )
+ {
+ // 非ワイドFM受信アルゴリズムを呼び出す
+ radio_demodulate_non_wide_FM( idata, qdata, &left, &right);
+ // デコード済みオーディオサンプルを、DMAから送信できる形式にパックする
+ pack_af_sample( left, right, &af_pri_ch, &af_sec_ch);
+ // パック済みオーディオサンプルをAFキューに送信する
+ // キューに空きがなければ、待たずにエラーをもって帰る
+ syscall(psnd_dtq(DTQ_AF, (VP_INT)af_pri_ch));
+ syscall(psnd_dtq(DTQ_AF, (VP_INT)af_sec_ch));
+ }
+ }
+ }
{
syslog( LOG_NOTICE, "TASK_AF activatred!" );
- int i = 0;
-
do{
+ // DMA転送が完了した受信バッファ
+ unsigned int* filled_buffer;
+ // next_descriptor
+ struct dma_descripter * next;
+ // ループカウンタ
+ int i;
+
+
+ // 送信が終わるのを待つ
syscall(wai_sem(SEM_SPORT0_TX));
- // ここに送信処理を書く
- if ( i == 0)
+ // SPORT0送信DMAコントローラが次にロードするデスクリプタへのポインタを取得する。
+ // このデスクリプタは、「現在使われていない」DMAデスクリプタであり、逆に言うと
+ // 割り込みが完了したDMAのデスクリプタである
+ next = (struct dma_descriptor *) *pDMA2_NEXT_DESC_PTR;
+
+ // 取得したデスクリプタから、割り込みを発生したバッファを割り出す。
+ filled_buffer = next->start_address;
+
+ // ここに送信処理を書く
+ // AF DMAバッファに送信すべきデータを書く
+ for ( i= 0; i<AF_BUFSIZE; i++)
{
- i=8000;
- syslog( LOG_NOTICE, "AF Interrupt" );
+ unsigned int data;
+
+ // AFキューから送信すべきデータを取り出す
+ // SVCにポーリングをしているため、取り出すべきデータがなければ待ちに入らずに
+ // エラーコードを返す
+ syscall(prcv_dtq( DTQ_AF, (VP_INT)&data));
+ // DMAバッファに書き込み
+ filled_buffer[i] = data;
}
- i--;
+
+
}while (1);
}
* なお、セカンダリ・チャンネルはindex = 1の時にサブ・オーディオを伝送するが、
* TRX-305はサブ・オーディオを使わないためこのルーチンは常に値を0としている。
*/
-static void pack_af_sample( short left, short right, int * pri_ch, int * sec_ch)
+static void pack_af_sample( short left, short right, unsigned int * pri_ch, unsigned int * sec_ch)
{
// オーディオデータは15bitしか使わない。Rchの16bit目は0に固定する
right >>= 1; // 15bitに変換