4 * \brief 復調器関連インクルードファイル
13 // Following mode macro can be used only the demodulator
15 /** \brief 受信機はワイドFMモードである */
16 #define radio_mode_WFM 2
17 /** \brief 受信機はナローFMモードである */
18 #define radio_mode_NFM 4
19 /** \brief 受信機は振幅変調モードである */
20 #define radio_mode_AM 5
21 /** \brief 受信機は振幅変調モードの同期復調モードである */
22 #define radio_mode_SAM 6
23 /** \brief 受信機はLSB復調モードである */
24 #define radio_mode_LSB 7
25 /** \brief 受信機はUSB復調モードである */
26 #define radio_mode_USB 8
27 /** \brief 受信機はCW復調モードである */
28 #define radio_mode_CW 9
32 * \defgroup radioAPI ラジオAPI
33 * \brief 復調器がSHマイコン/FPGAと情報の授受を行うためのAPI群
35 * このモジュールに含まれるAPIは、復調器の中でユーザー復調アルゴリズムが使うために
36 * 公開されている。制御情報取得用APIはTRX-305からの制御情報を受け取るためのものである。
38 * 制御情報は周期的に送られてくるため、必ずしも即座に反応する必要はない。具体的には
39 * TRX-305からは16種類の情報が16周期で送られてくる。これらは情報の中身に変更がない場合も
45 * \defgroup getInfo 制御情報取得API
46 * \brief 復調器がSHマイコン/FPGAから受け取る制御情報取得用のAPI
48 * ここに列挙されるAPIは、いずれも復調器内のユーザーアルゴリズムから自由に使ってよい。
50 * TRX-305から送られてくる制御情報は、ほとんどの場合TRX-305A基板にシリアルポートから
51 * 送られてくるコマンドに対応している。コマンドの一覧に関しては、トランジスタ技術誌
52 * 2014年11月号208ページの表を参照。なお、同記事のコマンドはTRX-305AのSHマイコンで
53 * 解釈後にDSPに送られるため、ここで使える命令とは必ずしも一対一対応していない。
55 * TRX-305Aが受け取るシリアル命令は、SHマイコンにより解釈されたあとにFPGA内部に
56 * 貯めこまれ、繰り返し送り出される。DSPはこの命令を受信し、制御情報として内部に
59 * なお、これらのAPIが返すのは、あくまで解釈のない「マイコンから送られてきた値」である。
60 * その値の物理的な解釈については、本プロジェクトは最小限に留める。言い換えると、
63 * 命令に関してはすべて実際に解析したものであり、参考とした文献は存在しない。
64 * 命令の解析は framework.h の DEBUG_COMMAND のコメントアウトを外すことによって、
65 * DSPからのシリアル出力を監視しながらSHにシリアルコマンドを投入して行う。
72 // These APIs are published for the demodulator programmer
74 * \def radio_api_getARM_mode
77 * このAPIは現在の受信モード(復調モード)を返す。シリアルコマンドARMに対応する。
79 * ユーザーに公開されているAPIであるが、2つの理由から使用を推奨しない。
81 * まず、復調器hののモード管理は radio_demodulate_wide_FM() および
82 * radio_demodulate_wide_FM() がフレームワークと強調する管理で行っており、
83 * プログラマは復調器がどのモードにあるかひと目でわかるようになっている。
84 * そのため、モード管理にこの関数を呼ぶ必要はない。
86 * また、USBとLSBの復調を概ね共用する場合も、radio_api_is_USB() を呼べば
87 * 事が足りる。したがって、この関数を呼ぶ必要はない。
89 * どうしてもこのAPIを呼び出すときには、 radio_mode_WFM() をはじめとする専用
90 * 定数と比較してモードを調べること。SHマイコンは外部のシリアルから与えられた
91 * パラメータと違う値を送ってくるため、この注意が必要となる。
93 #define radio_api_getARM_mode() (radio.comdata[1])
98 * シリアルコマンドのAIS命令に対応する。
99 * 16bitの符号付き整数でシフト量を返す。
101 #define radio_api_getAIS_if_shift() (signed short)(radio.comdata[2])
106 * シリアルコマンドのAAT命令に対応する。
107 * 16bitの符号無し整数でアタック値を返す。
109 #define radio_api_getAAT_attack() (radio.comdata[3])
114 * シリアルコマンドのAAT命令に対応する。
115 * 16bitの符号無し整数でフェード値を返す。
117 #define radio_api_getAFA_fade() (radio.comdata[4])
122 * シリアルコマンドのAAT命令に対応する。
123 * 16bitの符号無し整数でフェード値を返す。
125 #define radio_api_getAST_noise_squelch_level() (radio.comdata[5])
130 * シリアルコマンドのACP命令に対応する。
132 * SHマイコンはシリアルコマンド ACP hhhh (hは16進数)に対して、
133 * hhhhを十進数xに変換し x*16916/4096 の値をDSPに送り込む。
134 * このAPIが返すのは送り込まれてきた変換後の値である。
136 * 16bitの符号付き整数でピッチ値を返す。
138 #define radio_api_getACP_cw_pitch() (signed short)(radio.comdata[6])
143 * シリアルコマンドADN命令に対応する。
144 * 16bitの符号無し整数でデノイザー値を返す。
146 #define radio_api_getADN_denoiser() (radio.comdata[7])
151 * シリアルコマンドAAN命令に対応する。
152 * 16bitの符号無し整数でオートノッチ値を返す。
154 #define radio_api_getAAN_auto_notch() (radio.comdata[8])
159 * シリアルコマンドAGL命令に対応する。
160 * 16bitの符号無し整数でゲインレベル値を返す。
162 #define radio_api_getAGL_gain_level() (radio.comdata[11])
167 * シリアルコマンドAIF命令に対応する。
168 * 16bitの符号無し整数でフィルタ情報を返す。値の範囲は0から6である。
170 * (この情報がDSPへの命令なのか通知情報なのかは、現時点では不明である)
172 #define radio_api_getAIF_filter() ((radio.comdata[0]>>1)&0x7)
175 * \brief ノイズブランカ制御命令の取得
177 * シリアルコマンドABN命令に対応する。
178 * 16bitの符号無し整数でノイズブランカ制御値値を返す。
182 #define radio_api_getABN_noise_blanker_on() ((~radio.comdata[0]>>11)&0x1)
188 * シリアルコマンドARG命令に対応する。
189 * 16bitの符号無し整数でAGC制御情報値を返す。
194 #define radio_api_getARG_agc_on() (~(radio.comdata[0]>>13)&0x1)
199 * SSB復調時に必要に応じて参照する。。
200 * 16bitの符号無し整数でSSBのモードを返す。
205 #define radio_api_is_USB() ((radio.comdata[0]>>6)&0x1) // 1 if USB
209 * \brief ノイズスケルチ制御情報の取得
212 * 16bitの符号無し整数でスケルチ制御情報値を返す。
217 * なお、以上の設定はトランジスタ技術誌の2014年11月号の表に基づくが、
218 * この表には混乱があり、反転している可能性もある。
220 #define radio_api_getANE_noise_squelch_on() ((radio.comdata[10]>>1)&0x1)
224 * \brief オーディオHPF情報の取得
226 * シリアルコマンドAAF nm命令のnに対応する。
227 * 16bitの符号無し整数でオーディオHPF制御情報値を返す。
231 #define radio_api_getAAF_hpf() ((radio.comdata[10]>>4)&0x3)
234 * \brief オーディオLPF情報の取得
236 * シリアルコマンドAAF nm命令のmに対応する。
237 * 16bitの符号無し整数でオーディオLPF制御情報値を返す。
241 #define radio_api_getAAF_lpf() ((radio.comdata[10]>>2)&0x3)
247 * シリアルコマンドAVP命令に対応する。
248 * 16bitの符号無し整数でボイススケルチ値を返す。
251 * シリアルコマンドAVPの引数は0000-FFFF (65556)までの値をとるが、
252 * DSPに渡される値はbit7がAVSによって破壊される。したがって、
253 * AVPコマンドに渡す値は 0000から 007Fに制限すべきである。
255 #define radio_api_getAVP_voice_squelch_level() ((radio.comdata[12])&0x3F)
258 * \brief ボイススケルチ情報の取得
260 * シリアルコマンドAVS命令に対応する。
261 * 16bitの符号無し整数でボイススケルチ制御情報値を返す。
267 #define radio_api_getAVS_voice_squelch_on() ((~radio.comdata[12]>>7)&0x1)
269 /* end of defgroup getInfo */
272 * \defgroup setStat 状態報告API
273 * \brief DSPがFPGA/SHマイコンに情報を送るためのAPI群
278 * \def radio_api_set_S_meter
281 * このAPIはDSPからFPGA/SHマイコンに渡すSメータ値を設定する。値の範囲は
282 * 15bit符号なし整数である。APIは受け取った値をそのままFPGAに送信する。
284 #define radio_api_set_S_meter(s) radio.smeter = s
287 * \def radio_api_set_stereo
288 * \brief FMステレオ受信状態の報告
290 * FM復調がモノラルかステレオを報告する。引数は以下のように与える
294 #define radio_api_set_stereo(s) s ? radio.flags |= (1<<1) : radio.flags &= ~(1<<1)
297 * \def radio_api_set_voice_squelch
298 * \brief ボイススケルチ状態の報告
300 * 復調器がボイススケルチを持っている場合、その状態を報告する。
301 * \li 0 : ボイススケルチは開いていない
302 * \li 1 : ボイススケルチは開いている
304 #define radio_api_set_voice_squelch(s) s ? radio.flags |= (1<<2) : radio.flags &= ~(1<<2)
307 * \def radio_api_set_noise_squelch
308 * \brief ノイズスケルチ状態の報告
310 * 復調器がノイズスケルチを持っている場合、その状態を報告する。
311 * \li 0 : ノイズスケルチは開いていない
312 * \li 1 : ノイズスケルチは開いている
314 #define radio_api_set_noise_squelch(s) s ? radio.flags |= (1<<3) : radio.flags &= ~(1<<3)
318 /* end of defgroup setStat */
321 /* end of defgroup radioAPI */
324 * \defgroup callbacks 復調用コールバック関数
325 * \brief フレームワークが復調ように呼び出すコールバック関数群
327 * 復調器のためにフレームワークから呼び出すコールバック関数。復調アルゴリズムは全てこの中に記述する。
329 * 関数は大きく分けて2種類に分けられる。ひとつは初期化関数で \ref init_demodulator() がこれである。
330 * その他の関数は実際の復調を行う関数である。
339 * 復調アルゴリズムの初期化を行う。アルゴリズムが変数を初期化しなければならないようなときには、
340 * この関数の中に初期化プログラムを書く。
342 * この関数は、\ref radio_demodulate_wide_FM() や \ref radio_demodulate_non_wide_FM() が
346 void init_demodulator(void);
350 * \brief ワイドFMの復調コールバック関数
351 * \param idata 受信IFのI(in phase)データ配列。32bit符号付き固定小数点数。フォーマットはQ1.31
352 * \param qdata 受信IFのQ(Quadratural phase)データ配列。32bit符号付き固定小数点数。フォーマットはQ1.31
353 * \param left 復調オーディオ信号の左チャンネルデータ。16bit符号付き固定小数点数。フォーマットはQ1.15
354 * \param right 復調オーディオ信号の右チャンネルデータ。16bit符号付き固定小数点数。フォーマットはQ1.15
356 * ワイドFM以外の信号を復調するために呼ばれるコールバック関数。この関数と \ref radio_demodulate_non_wide_FM() の
357 * 切り替えはフレームワークが自動的に行うため、ユーザー側は気にしなくていい。
360 * IF入力(idata[], qdata[])、AF出力(*left, *right)ともFsは31.7kHzである(トランジスタ技術誌2015年5月号pp183)。
361 * 1サンプル毎に呼び出されるので、このコールバックは1秒間に31,700回呼び出される。
363 * IF入力はワイドFMではオーバーサンプルされた値が入力する。そのため、1サンプルあたりのデータ数は1ではない。
364 * 具体的なオーバーサンプル値は、マクロ WIDE_FM_OVERSAMPE で知ることができる。まとめると、この関数の中では
365 * idata/qdataそれぞれ WIDE_FM_OVERSAMPE 個のデータを復調処理して、1個のleft/right データを生成する。
367 * IF入力データとAF出力データの語長が違うことに注意。データのパック形式は固定小数点型であるため、いずれも
368 * データの値の範囲は[-1,1)となる。しかし、C言語としての取り扱いは整数なので、それぞれの最大値は異なる(IFデータの
373 void radio_demodulate_wide_FM( short idata[], short qdata[], short* left, short* right );
376 * \brief ワイドFM以外の復調コールバック関数
377 * \param idata 受信IFのI(in phase)データ。32bit符号付き固定小数点数。フォーマットはQ1.31
378 * \param qdata 受信IFのQ(Quadratural phase)データ。32bit符号付き固定小数点数。フォーマットはQ1.31
379 * \param left 復調オーディオ信号の左チャンネルデータ。16bit符号付き固定小数点数。フォーマットはQ1.15
380 * \param right 復調オーディオ信号の右チャンネルデータ。16bit符号付き固定小数点数。フォーマットはQ1.15
382 * ワイドFM以外の信号を復調するために呼ばれるコールバック関数。この関数と \ref radio_demodulate_wide_FM() の
383 * 切り替えはフレームワークが自動的に行うため、ユーザー側は気にしなくていい。
385 * 非ワイドFM以外のモードにはAM, SAM, LSB, USB, Narrow FM, CW の受信モードがある。これらの受信モードの
386 * 検出は、コールバック関数内部のスケルトンが自動的に切り分けているので、それぞれの場合ごとに復調アルゴリズムを
389 * LSBとUSBの復調コードの大半を共有したい場合には、一部でLSB/USBの判断を行われなければならない。この場合は
390 * \ref radio_api_is_USB() APIを使うことで判別を行う。
392 * なお、ワイドFMモードから非ワイドFMモードへの切り替えがSHマイコンから出された場合、実際のFMモードからの
393 * 復調器の切り替えは二段階になりうる。最初の段階では radio_demodulate_wide_FM() の呼び出しが終了し、
394 * radio_demodulate_non_wide_FM() の呼び出しへと切り替わる。次の段階では、\ref radio_demodulate_non_wide_FM()
395 * の中で正しい復調モードが検出され、スケルトンの動作が切り替わる。
397 * この二段階切り替えは必ず起こるというわけではなく、FPGAの実装形態に依存する。単にフレームワークは二段階切り替えにも
400 * IF入力(idata, qdata)、AF出力(*left, *right)ともFsは31.7kHzである(トランジスタ技術誌2015年5月号pp183)。
401 * 1サンプル毎に呼び出されるので、このコールバックは1秒間に31,700回呼び出される。
403 * IF入力データとAF出力データの語長が違うことに注意。データのパック形式は固定小数点型であるため、いずれも
404 * データの値の範囲は[-1,1)となる。しかし、C言語としての取り扱いは整数なので、それぞれの最大値は異なる(IFデータの
409 void radio_demodulate_non_wide_FM( int idata, int qdata, short* left, short* right );
412 /* end of defgroupt callbacks */
414 #endif /* _MACRO_ONLY */
416 #endif /* DEMODULATOR_H_ */