#include <cdefBF533.h>
-#define PARAMDATA_NUM 16
static void init_sport0_rx(void);
static void init_sport0_tx(void);
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 );
+static void set_command_data( unsigned int command, unsigned int data );
} framework;
// ラジオアルゴリズムとのやりとりに使う変数
- struct {
- unsigned short flags;
- unsigned short smeter;
- unsigned short comdata[PARAMDATA_NUM];
-} radio;
+ struct RADIO radio;
-static int debug_counter = 0;
-static int debug_level = 0;
-static int debug_tx_counter = 0;
-static int debug_rx_counter = 0;
-
-#define DEBUGLOOP (31700)
+ // デバッグ用変数群
+#if defined (DEBUG_QUEUEDEPTH)
+static int debug_queue_level = 0;
+static int debug_queue_max = INT_MIN;
+static int debug_queue_min = INT_MAX;
+#endif
/**
pack_af_sample(0, 0, &af_pri_ch, &af_sec_ch);
syscall(psnd_dtq(DTQ_AF, (VP_INT)af_pri_ch));
syscall(psnd_dtq(DTQ_AF, (VP_INT)af_sec_ch));
- debug_level ++;
+#ifdef DEBUG_QUEUEDEPTH
+ debug_queue_level +=2;
+ if ( debug_queue_level > debug_queue_max)
+ debug_queue_max = debug_queue_level;
+#endif // DEBUG_QUEUEDEPTH
}
// AF送信を開始する。ただし、送信DMA割り込みはまだ発生しない。
*pDMA2_CONFIG |= DMAEN; // TX SPORT DMA Enable
- *pSPORT0_TCR1 |= RSPEN; // TX SPORT Enable
+ *pSPORT0_TCR1 |= TSPEN; // TX SPORT Enable
ssync();
+
+
tslp_tsk(1); // DMAがFIFOを充填するのに十分な時間待つ。
syscall(act_tsk(TASK_AF)); // AFデータ送信タスクをアクティブにする
ssync();
-
-
-
/*
* メインループ
* 受信DMA割り込み待ってから、DMAバッファ内部のデータを解析して然るべき受信処理を行う。
// パック済みオーディオサンプルをAFキューに送信する
// キューに空きがなければ、待たずにエラーをもって帰る
-#if 0
syscall(psnd_dtq(DTQ_AF, (VP_INT)af_pri_ch));
syscall(psnd_dtq(DTQ_AF, (VP_INT)af_sec_ch));
-#endif
- debug_level += 2;
+#ifdef DEBUG_QUEUEDEPTH
+ debug_queue_level += 2;
+ if ( debug_queue_level > debug_queue_max)
+ debug_queue_max = debug_queue_level;
+#endif // DEBUG_QUEUEDEPTH
}
}
pack_af_sample( left, right, &af_pri_ch, &af_sec_ch);
// パック済みオーディオサンプルをAFキューに送信する
// キューに空きがなければ、待たずにエラーをもって帰る
-#if 0
syscall(psnd_dtq(DTQ_AF, (VP_INT)af_pri_ch));
syscall(psnd_dtq(DTQ_AF, (VP_INT)af_sec_ch));
-#endif
- debug_level += 2;
+#ifdef DEBUG_QUEUEDEPTH
+ debug_queue_level += 2;
+ if ( debug_queue_level > debug_queue_max)
+ debug_queue_max = debug_queue_level;
+#endif // DEBUG_QUEUEDEPTH
}
} // 非ワイドFMの場合
// AFキューから送信すべきデータを取り出す
// SVCにポーリングを使用しているため、取り出すべきデータがなければ待ちに入らずに
// エラーコードを返す
-#if 0
syscall(prcv_dtq( DTQ_AF, (VP_INT)&data));
-#endif
// DMAバッファに書き込み
filled_buffer[i] = data;
-
- debug_level --;
- }
-#if 0
- debug_counter ++;
- if ( debug_counter > DEBUGLOOP ){
- syslog( LOG_NOTICE, "AF LENGTH %d", debug_level);
- debug_counter =0;
+#ifdef DEBUG_QUEUEDEPTH
+ debug_queue_level --;
+ if ( debug_queue_min > debug_queue_level)
+ debug_queue_min = debug_queue_level;
+#endif // DEBUG_QUEUEDEPTH
}
-#endif
}while (1);
}
}
// プライマリ・チャンネルの組み立て
- *pri_ch = (right << 16) | left;
+ *pri_ch = ((unsigned int)right << 16) | (unsigned short)left;
framework.index = ! framework.index; // indexの論理反転
*/
static void unpack_wide_fm ( unsigned int pri_ch, unsigned int sec_ch, int* idata, int* qdata )
{
+ int command, data, exp, i, q;
+
// iデータとqデータを抽出する。両者とも16bitで、bit14からbit29に格納されている
- *idata = ( pri_ch << 2 ) & 0xFFFF0000;
- *qdata = ( sec_ch << 2 ) & 0xFFFF0000;
+ i = ( pri_ch << 2 ) & 0xFFFF0000;
+ q = ( sec_ch << 2 ) & 0xFFFF0000;
+ // ブロック浮動小数点処理。expでスケーリングする。
+ exp = ( pri_ch >> 10 ) & 0x0F;
+ *idata = i >> exp;
+ *qdata = q >> exp;
+
+#ifdef DEBUG_BLOCK_FLOAT
+ {
+ static int tested = 0;
+ if ( (i & 0x80000000) && ! tested )
+ {
+ tested = 1;
+ syslog( LOG_NOTICE, "i: %8x, exp: %d, idata:%8x", i, exp, *idata);
+ }
+ }
+#endif
// パラメータ・データを配列に格納する。
- // 配列インデックスは comaddr、データはcomdataから。comdataはpri/secに分散している。
- radio.comdata[ ( pri_ch >> 6 ) & 0x0F ] =
- (( pri_ch << 6 ) & 0xF000) | //
+ // 配列インデックスは comaddr、データはcomdataから。
+ // comdataはpri/secに分散している。
+
+ command = ( pri_ch >> 6 ) & 0x0F;
+ data =
+ (( pri_ch << 10 ) & 0xF000) | //
(( sec_ch >> 2 ) & 0x0FFF);
+ // パラメータ・データをrx_parameter.data配列に格納する。
+ // 配列インデックスは comaddr、データはcomdataから。
+
+ set_command_data( command, data);
+
+ radio.comdata[ command ] = data;
}
/**
* \param sec_ch セカンダリ・チャンネルからのデータ
* \param idata 抽出したIデータ。[-1,1.0)の固定小数点形式。valid_iqが真の時のみ有効
* \param qdata 抽出したQデータ。[-1,1.0)の固定小数点形式。valid_iqが真の時のみ有効
- * \param valid_iq IQデータが有効の時真、向こうの時は偽
+ * \param valid_iq IQデータが有効の時真、無効の時は偽
* \detail
*/
if ( sec_ch & 0x02 ) // bit1が1ならindex = 1
{
// IQデータはbit[29:2]に格納されている
- *idata = (pri_ch << 2); // プライマリ・チャンネルの場合はマスク不要
+ *idata = (pri_ch << 2) & 0xFFFFFFF0;
*qdata = (sec_ch << 2) & 0xFFFFFFF0;
// IQデータが有効であると通知する
*valid_iq = TRUE;
}
else // index = 0
{
+ // ラジオパラメータ
+ int command, data;
+
+ command = ( pri_ch >> 6 ) & 0x0F;
+ data = ( sec_ch >> 2 ) & 0xFFFF;
// パラメータ・データをrx_parameter.data配列に格納する。
// 配列インデックスは comaddr、データはcomdataから。
- radio.comdata[ ( pri_ch >> 6 ) & 0x0F ] =
- ( sec_ch >> 2 ) & 0xFFFF;
+
+ set_command_data( command, data);
+
// IQデータが無効であると通知する
*valid_iq = FALSE;
}
}
+/**
+ * \brief SHからのコマンドとパラメタを保存する
+ * \param command コマンド種別
+ * \param data コマンドパラメータ
+ * \details このルーチンはSHからFPGA経由で受け取ったコマンドとそのデータを内部変数に格納する。
+ * 格納されたデータはユーザーが実装した復調アルゴリズムから、API経由で利用される。
+ */
+static void set_command_data( unsigned int command, unsigned int data )
+{
+#ifdef DEBUG_COMMAND
+ if ( radio.comdata[command] != data ){
+ syslog(LOG_NOTICE, "Command : %d, Data : %d", command, data );
+ }
+#endif
+ radio.comdata[ command ] = data;
+
+}
+
/**
* \brief SPORT0 受信割り込みハンドラ
{
// DMA割り込みをクリアする。
*pDMA1_IRQ_STATUS = DMA_DONE;
-
// タスクにSPORT0受信DMAのバッファが埋まったと知らせる。
- syscall(isig_sem(SEM_SPORT0_RX));
-
+ syscall(isig_sem(SEM_SPORT0_RX)); // デバッグとりあえずタスクは殺しておく。
// ペリフェラルへの書き込みを待つ。
ssync();
- debug_rx_counter++;
-
}
/**
// タスクにSPORT0送信DMAのバッファが空いたと知らせる。
syscall(isig_sem(SEM_SPORT0_TX));
-
// ペリフェラルへの書き込みを待つ。
ssync();
- debug_tx_counter++;
- if ( debug_tx_counter > 31000)
- {
- syslog( LOG_INFO, "TX, SIC_ISR:x08", *pSIC_ISR );
- debug_tx_counter = 0;
- }
}
/**
0 << 9 | // RSFESE, 0:normal frame sync, 1:LR frame clock
1 << 8 | // RXSE, 0:secondary ch disable, 1:secondary ch enable
29 << 0 ; // SLEN 0-1:not allowed,2-31:Serial word length - 1
+
ssync();
0 << 12 | // LTFS, 0:Active high TFS, 1:Active low TFS
0 << 11 | // DITFS, 0:data dependent TFS generation, 1:data independent TFS generation
1 << 10 | // TFSR, 0:TFS is not required every word, 1:TFS is required every word
- 0 << 9 | // ITFS, 0:external TFS, 1:internal TFS
+ 1 << 9 | // ITFS, 0:external TFS, 1:internal TFS
0 << 4 | // TLSBIT, 0:MSB first transmission, 1:LSB first transmission
0 << 2 | // TDTYPE 0:normal, 1:reserved, 2:u-law, 3:a-law
0 << 1 | // ITCLK, 0:external clock generation, 1:internal clock generation
*pSPORT0_TCR2 =
0 << 10 | // TRFST, 0:left streo ch first, 1:right stereo ch first
0 << 9 | // TSFESE, 0:normal frame sync, 1:LR frame clock
- 0 << 8 | // TXSE, 0:secondary ch disable, 1:secondary ch enable
+ 1 << 8 | // TXSE, 0:secondary ch disable, 1:secondary ch enable
30 << 0 ; // SLEN 0-1:not allowed,2-31:Serial word length - 1
+ *pSPORT0_TFSDIV = 255; // TFS period -1 ( The period is 256 )
+
// 送信DMAデスクリプタを作る
// 注意:制御の都合上、最初はDMA割り込みをオフにしておく。これは
*pDMA2_NEXT_DESC_PTR = &framework.tx_dma_dsc[0];
}
+
+/**
+ * \brief デバッグ用モニタ・タスク
+ * \param exinf cfgファイルに記述されたパラメタを受け取る引数。使っていない。
+ * \details 一定時間ごとにシステム状態をモニターする。通常は使っていないが、
+ * 開発時に各種システム量を計算、取得するために動かす低順位タスクである。
+ */
+
+void monitor_task(VP_INT exinf)
+{
+
+ while(1)
+ {
+#ifdef DEBUG_DSPLOAD
+ unsigned int cycle_start, cycle_end, total_idle_cycle, total_cycle;
+ {// DSP負荷の計算(前処理)
+
+ idle_cycle = 0;
+ asm volatile ("r0 = cycles;%0 = r0;" : "=d"(cycle_start) : : "R0");
+ }
+#endif // DEBUG_DSPLOAD
+
+ tslp_tsk(1000); // 1秒待つ
+
+#ifdef DEBUG_DSPLOAD
+ {// DSP負荷の計算(後処理)
+ asm volatile ("r0 = cycles;%0 = r0;" : "=d"(cycle_end) : : "R0");
+
+ // ここまでの通算時間を取得する
+ total_cycle = cycle_end - cycle_start;
+ // ここまでの通算アイドル時間を取得する
+ total_idle_cycle = idle_cycle;
+
+
+ // 計算しやすいようにスケーリング
+ total_cycle >>= 16;
+ total_idle_cycle >>=16;
+
+ syslog(LOG_NOTICE, "DSP Load : %d%%", (total_cycle - total_idle_cycle) * 100 / total_cycle);
+ }
+#endif // DEBUG_DSPLOAD
+
+#ifdef DEBUG_QUEUEDEPTH
+ { // AF TASK, RX IF TAXK間のキューの深さを報告する
+
+ syslog( LOG_NOTICE, "Queue depth max : %d, min : %d ", debug_queue_max, debug_queue_min);
+ }
+#endif // DEBUG_QUEUEDEPTH
+
+#ifdef DEBUG_COMMAND_API
+ syslog( LOG_NOTICE, "radio_api_getARM_mode() %d", radio_api_getARM_mode() );
+ syslog( LOG_NOTICE, "radio_api_getAIS_if_shift() %d", radio_api_getAIS_if_shift() );
+ syslog( LOG_NOTICE, "radio_api_getAAT_attack() %d", radio_api_getAAT_attack() );
+ syslog( LOG_NOTICE, "radio_api_getAFA_fade() %d", radio_api_getAFA_fade() );
+ syslog( LOG_NOTICE, "radio_api_getAST_noise_squelch_level() %d", radio_api_getAST_noise_squelch_level() );
+ syslog( LOG_NOTICE, "radio_api_getACP_cw_pitch() %d", radio_api_getACP_cw_pitch() );
+ syslog( LOG_NOTICE, "radio_api_getADN_denoiser() %d", radio_api_getADN_denoiser() );
+ syslog( LOG_NOTICE, "radio_api_getAAN_auto_notch() %d", radio_api_getAAN_auto_notch() );
+ syslog( LOG_NOTICE, "radio_api_getAGL_gain_level() %d", radio_api_getAGL_gain_level() );
+ syslog( LOG_NOTICE, "radio_api_getAIF_filter() %d", radio_api_getAIF_filter() );
+ syslog( LOG_NOTICE, "radio_api_getABN_noise_blanker_on() %d", radio_api_getABN_noise_blanker_on());
+ syslog( LOG_NOTICE, "radio_api_getARG_agc_on() %d", radio_api_getARG_agc_on());
+ syslog( LOG_NOTICE, "radio_api_getANE_noise_squelch_on() %d", radio_api_getANE_noise_squelch_on());
+ syslog( LOG_NOTICE, "radio_api_getAAF_hpf() %d", radio_api_getAAF_hpf() );
+ syslog( LOG_NOTICE, "radio_api_getAAF_lpf() %d", radio_api_getAAF_lpf() );
+ syslog( LOG_NOTICE, "radio_api_getAVP_voice_squelch_level() %d", radio_api_getAVP_voice_squelch_level() );
+ syslog( LOG_NOTICE, "radio_api_getAVS_voice_squelch_on() %d", radio_api_getAVS_voice_squelch_on() );
+#endif // DEBUG_COMMAND_API
+
+ }
+}