LTE-Cell-Scanner LTE基地局スキャンプログラム

私はsrsLTEソフトウェアを使用してLTE基地局を実装しています。srsLTEはドキュメント化されているだけでなく、明確なコード構造も持っていますが、私が読んだコードは主にsdrとやり取りする部分です。実際の信号処理とデコードの部分は複雑すぎるため、詳しく調べていません。srsLTEには、cell_searchなどの基地局に加えていくつかの小さな例があることがわかりました。事業者の商用基地局を検索できます。つまり、LimeSDRは、FM放送を聞くだけでなく、通常の携帯電話のように実際の基地局信号を復調することができます。問題は、cell_searchプログラムが依然としてsrslte内の多くの関数を呼び出すことです。これは、開始するには複雑すぎて面倒です。

後で、LTE-Cell-Scannerと呼ばれる別のプログラムを見つけました。

https://github.com/Evrytania/LTE-Cell-Scanner

このプログラムの機能は非常にシンプルです。基地局を検索してブロードキャスト情報を取得するだけです(基地局を追跡して詳細情報を取得できるLTE-Trackerプログラムもありますが、それを見るつもりはありません)。このLTEセルスキャナーは、外国人によって最初に作成されました。使用されるハードウェアはrtlsdrです。これは、指定された周波数範囲内でLTE基地局を検索し、基地局であると決定された周波数ポイントをマークできます。各基地局は、詳細情報を取得できます。セルID、基地局電力、CPタイプ、アンテナ数、セル帯域幅、および一部のPHICH情報を取得でき、rtlsdrの周波数を調整するために使用することもできます。

原作者による紹介ページです

http://www.evrytania.com/lte-tools/78-default-category/77-lte-cell-scanner

私がそれを使用したとき、低ppmハードウェアを使用するか、最後のキャリブレーション値を使用してハードウェアをキャリブレーションすると、検索速度を上げることができるという概要を見ました。元々、ハードウェアが良くなければ解決されないので、検索時間には影響しないはずです。しかし、コードを注意深く読んだ後、私はこれがなぜ起こるか理解しています。

このプロジェクトに加えて、別の中国人がこのプログラムに変更を加えました。3つの主な変更があります。1。ハッカーをサポートするようにします(周波数範囲が広くなり、わが国の一部の基地局の周波数がrtlsdrのサポート範囲をはるかに超える2.6GHzになるようにします)。 、しかしhackrfはサポートできます)2. tddベースステーションをサポートします(元の外国人はfddベースステーションのみをサポートし、ベースステーションがfddまたはtddかどうかも判別できます)3. openclをサポートします(グラフィックカードを使用して操作を高速化できます)。

とりあえず、外国人向けプログラムのオリジナル版を読んだだけで、基本的な流れはわかった。

基地局の検出は、ダウンリンク信号のpssとsssを見つけることによって判断されます。手順は、最初にrtlsdrによって取得されたiqデータを取得し、次に相互相関アルゴリズムを直接使用して元のデータのpssを検出し、次に最尤アルゴリズムがsssを検出して、基地局を決定します。セルID、電力、中心周波数などの重要な情報も多く得られ、原則としてtdd基地局かfdd基地局かを判断でき、周波数偏差の推定も後で行います。

この後、MIB復調が必要になります。また、基地局の帯域幅など、MIBには多くの重要な情報があります。MIB復調の前に、ビデオグリッド(時間周波数グリッド、tfg)が取得され、その後、復調と復号化が実行されて、詳細情報が取得されます。

このプログラムは、itppなどのいくつかの外部パッケージを呼び出します。itppには、MATLABを模倣する関数や通信信号処理アルゴリズムが多数あります。LTEの復調とデコードは、実際にはitppの関数を呼び出すことによって行われます。

CellSearch.cpp searcher.cpp lte_lib.cppの3つのメインプログラムがあります。CellSearch.cppにはメイン関数があり、メイン関数はまずデータを取得してから、信号処理アルゴリズムを呼び出して段階的に検出を行います。基地局が検出されると、ターゲット周波数範囲全体が検索されるまで1つ出力され、要約情報が出力されます。searcher.cppも非常に重要で、main関数で呼び出されるいくつかのアルゴリズム関数がここに実装されています。最後に、itppのlte復調およびデコード関数のカプセル化であるlte_lib.cppがあり、メインプログラムはmibデコードを行うためにそれを呼び出し、次にitpp内の特定の関数を呼び出します。

まず、CellSearchのメイン関数を確認し、parse_commandlineを呼び出して起動時に入力されたパラメーターを取得し、config_usbを呼び出してrtlsdrハードウェアを初期化します。次に、ユーザーが検索するために入力した周波数範囲であるfc_search_setを含む、いくつかの変数が初期化されます。f_search_set、これは、周波数ポイントの1つが基地局であるかどうかを検索するときの周波数オフセットです。detected_cellsによって検出されたすべての基地局情報は、この中に存在します。次に、forループに入ります。このforループは、ユーザーが入力した周波数範囲の0.1MHzごとの中心周波数ポイントを通過します。単一のループは、この周波数ポイントが基地局であるかどうかを判断することです。基地局である場合は、mib解決し、印刷してください。

次に、ループ内の操作を確認します。最初はcapture_dataです。この関数はcapbuf.cppに実装されています。入力パラメーターに基づいてこの読み取りの中心周波数を決定し、読み取り前にハードウェアを設定します。読み取りの使用方法は、rtlsdrを呼び出して非同期で読み取ることです。実際、これは前に見たkerberossdrと非常によく似ています。興味深いのは、capturedataのコールバック関数が呼び出され、capturedataのコールバック関数が終了したときに非同期読み取りをキャンセルし、非同期の読み取り関数が実際に同期的に読み取られることです。それはほとんど終わって、読んでいる間待って、そして読んだ後に戻る。それを読み込んだ後、型も変換され、最初に0から255までのデータが-1から1にマッピングされ、次に一連のiqiqiqiqが複素数に変換されてcapbufに格納されます。この機能は、オフライン分析用のファイルの読み取りまたはファイルからのサポートもサポートします。これは通常は使用されません。また、関数の冒頭の宣言を見ると、入力情報と出力情報に応じて、作者の各パラメータがコメントで書かれており、読みやすくなっています。

次に、メイン関数のメイン関数はxcorr_pss、peak_search、およびsss_detectです。(しきい値を計算し、peak_searchの基準として使用されるchi2cdf_inv関数もあります)。これらの3つの関数は、現在のサイクルで検出されたターゲット周波数に基地局があるかどうかを判断するために使用されます。

次はpss_sss_foeで、pssとsssの検出結果を使用して、2.5kHzの精度で周波数校正を行います。次に、time_frequency_gridを取得するために使用されるextract_tfgがあります。ハードウェアであるcapbufで受信したデータから、時間-周波数グリッドでデータを特定し、それを後続のデコードに使用します。このグリッドは、参照値と同じです。記事に対応。次はtfoecで、高精度の周波数校正と時間校正を行います。最後に、decode_mibは、MIBを復調します。

ここまででループの内部が終了しましたが、終了後は、引き続き範囲内の次の中心周波数ポイントの基地局かどうかを判断し、基地局の場合はMIBを解決します。

すべてを実行した後、重複除去機能を使用して重複を削除し、ベースステーションのすべての詳細情報を出力します。

 

次に、前述のメインループでより重要な関数のいくつかを見てみましょう。

1.xorr_pss、searcher.cppの入力は元のcapbufデータ、f_search_set、ds_comb_armによって検索されるオフセット周波数、fc_requestedユーザーによって設定された中心周波数、fc_programmedプログラムによって変換された中心周波数、fs_programmedプログラムによって変換されたサンプリングレート、この関数これは、xc_correlate、xc_combine、xc_delay_spread、xc_peak_freq、sp_estのいくつかのステップに分かれています。sp_estは独立したプログラムであり、出力量はデバッグ専用です。入力量は元のデータであるため、単独で見ると、実際には複素数モジュラス法を使用して元のデータサンプリングポイントのパワーが計算されます。注釈によれば、計算は2です。 ofdmシンボルのパワーの場合、周波数は12 rbsを使用して6 rbsのパワーを推定します。6rbsのパワーは、基地局が送受信するデータによって変化しません。12rbsにいくつかの変更があり、不正確になる可能性があります。

次に、xcで始まる他のいくつかの関数を見てみましょう。

1.1 xc_correlateは、xorr_pssのすべてのパラメーターを渡し、3つのZadoff-Chuシーケンスに対応するROM_TABLES.pss_td、25、29、34から3種類のpss値を取得します(https:// blog.csdn.net/m_052148/article/details/51273636)、これら3つのシーケンスのセット(テーブル)の周波数領域形式は、lte_lib.cppのpss_fd_calc関数で生成されます。これは、pss_fd_calcのコードです。

const int zc_map_donotuse[3]={25,29,34};
const vector <int> zc_map(zc_map_donotuse,zc_map_donotuse+3);
//zc_map里就是25,29,34
cvec r=exp((complex<double>(0,-1)*pi*zc_map[t]/63)*elem_mult(ivec("0:62"),ivec("1:63")));
//zc_map[t]就是公式里的root index(u)
//后面的elem_mult(ivec("0:62"),ivec("1:63")))就是n(n+1)或者(n+1)(n+2)
//总之就是连着的两个整数,0:62和1:63代表整数取值范围
//剩下的左边complex<double>(0,-1)就是=0+(-1)*j=-j,然后放在e的指数上,跟公式一样的
r.del(31);
//公式是分段函数实现的,代码里没分段而是去掉了31对应的情况,就是31*32

生成が完了したら、idftを使用して時間領域に転送し、最後に一時領域に保存します。変換プロセスの前に、0配列も接続しました。変換後、自分のセクションを自分自身に接続しました。それでも理解できませんか?とにかく、これら3つのシーケンスの時間領域の値はテーブルに格納され、長さはグループあたり137です。

xc_correlateがこれらの3つのシーケンスを取得した後、それらの1つを毎回取り出してtempに配置します。ハードウェアに周波数エラーがある可能性があるため、周波数オフセットを実行し、エラーの可能性を排除し、fshift関数を使用してf_offのサイズだけこのシーケンスを移動します。周波数、つまり、この周波数誤差を補正し、取得した元のデータcapbufと畳み込み、tempはconjを取り、次のループでは、capbufをスライドして乗算し、合計と正規化はすべて畳み込みですが、畳み込み式とは少し違いますが、質問はありますか?

計算結果はxcに保存されます。xcのパラメーターxc [t] [k] [foi] = acc tは3セットのシーケンスに対応し、kはcapbuf -136の長さ、foiはすべての周波数オフセットに対応します。

この136は一時的な長さに関連し、移動および乗算時に計算が範囲を超えないようにするためのたたみ込みに使用されます。

実際、推定周波数オフセットの範囲が広いほど、foiの値が大きくなり、実行される計算時間が長くなることがわかります。

1.2 xc_combineはxcを取得した後では不十分です。キャプチャは80ミリ秒なので、実際には多くのフレームが含まれています。これらの結果を組み合わせて平均化できます。これの利点は、周波数誤差を知ることができることです。マージするときに注意すべき1つのこと。エラーがない場合、各フレームは19200のサンプリングポイントで再表示されますが、エラーがある場合、次のフレームの始まりは19200の後ではありません。たとえば、中心周波数が740MHzでエラーが50kHzの場合、19200-50 * 10 ^ 3 /(740 * 10 ^ 6)= 19198.7になります。相互相関のピーク間隔も19198.7に変更されました。周波数誤差が0の場合のみ、19200のサンプリングポイントが分離されるため、基地局の正確な周波数と受信機の周波数誤差を判断できます。また、相互相関結果を組み合わせるときに考慮すべきこの点のためです。

Actual_start_indexは、この偏差を計算するために使用されます。なぜそうなのかはわかりません。n_comb_xcは、結合されたフレームの数を示します。

9600がコードで19200ではないのはなぜですか?複数形はiqを置き換えるため、長さは半分に減少します19200/9600 = 2

 for (uint16 m=0;m<n_comb_xc;m++) 
 {
       double actual_start_index=itpp::round_i(m*.005*k_factor*fs_programmed);
        for (uint16 idx=0;idx<9600;idx++) 
        {
          xc_incoherent_single[t][idx][foi]+=sqr(xc[t][idx+actual_start_index][foi]);
        }
 } 
 //xc_incoherent_single里存的是合并后的xc
 
 for (uint16 idx=0;idx<9600;idx++)
 {
        xc_incoherent_single[t][idx][foi]=xc_incoherent_single[t][idx][foi]/n_comb_xc;
 }
//把合并后的结果再除以frame的数量n_comb_xc就得到了平均值

1.3 xc_delay_spread、次はこの関数です。これは前のステップと少し似ていますが、今回は時間領域の5つの隣接点の結果がマージされてから平均化される点が異なります。これらの5つのポイントはプログラムの開始時に定義され、ds_comb_arm、ds_comb_arm = 2、現在のポイント、現在のポイントの2ポイント前、1ポイント前、1ポイント後、現在のポイント後の2ポイントを合計する必要があります。

 for (uint8 t=0;t<3;t++) 
 {
      for (uint16 idx=0;idx<9600;idx++) 
      {
        xc_incoherent[t][idx][foi]=xc_incoherent_single[t][idx][foi];
      }
 }
 //先把当前点存好

 for (uint8 t=1;t<=ds_comb_arm;t++)
 {
     for (uint8 k=0;k<3;k++) 
     {
        for (uint16 idx=0;idx<9600;idx++) 
        {
          xc_incoherent[k][idx][foi]+=xc_incoherent_single[k][itpp_ext::matlab_mod(idx-t,9600)][foi]+xc_incoherent_single[k][itpp_ext::matlab_mod(idx+t,9600)][foi];
          //t=1时把前1个点和后1个点的结果存进去
          //t=2时再把前2个点和后2个点的结果存进去
        }
     }
 }
    // Normalize
 for (uint8 t=0;t<3;t++)
 {
     for (uint16 idx=0;idx<9600;idx++)
     {
        xc_incoherent[t][idx][foi]=xc_incoherent[t][idx][foi]/(2*ds_comb_arm+1);
     } //全部存完了要除以(2*2+1=5), 求出平均值
 }

1.4 xc_peak_freq、すべての3つのPSSエンコーディング値、すべての時間オフセット、およびすべての周波数オフセットの中で最大のピークを見つけます。これは実際にはxc_incoherentの最大値であり、この最大値、周波数オフセット値、3レベルに対応するfoiループして最大値を見つけます。ただし、この方法で検出されるのは、依然として各グループのPSSコード、各時間でのピークの最高値に対応する周波数、PSSコードがどうあるべきか、および時間が不明であることです。

2.メイン関数のpeak_search、xcorr_pssがほぼ完了し、peak_searchがほぼ完了。最大相互相関ピークを見つけるだけでは十分ではありません。それ自体よりも大きいだけですが、標準に達するにはしきい値を超えている必要があります。このしきい値も、chi2cdf_invを使用して計算されますそれを理解したら、それを注意深く見ないでください。この関数は、最初に転置を使用し、max関数を2回使用して最も高いピークに対応するPSSコード値を見つけ、それをpeak_n_id_2に格納し、比較的近いピーク時間peak_indも見つけます。このmax関数は特定のライブラリのオーバーロードである可能性があるため、その使用法についてはわかりません。意味がわからないだけです。ピークパワーがしきい値を超えた場合、それは検出されますが、ピークはいくつかの時点で前の関数によって平均化されます。正確なピークの時点を見つけるには、最初に、既知の2つのピークに対応するパラメーター、PSSを使用します。ピークに対応する周波数xc_incoherent_collapsed_frq(peak_n_id_2、peak_ind)を見つけるためのコード化と近似時間ポイントをコーディングし、時間内にxc_incoherent_singleをトラバースして、ピークの最高時間を取得します。これらの計算がすべて完了したら、ピーク電力、ピーク対応時間、ピーク対応周波数、およびピーク対応PSSコードをすべてセルに格納し、最終的にメインプログラムの他の部分に出力できます。次に、検出から除外されたピークの一部を削除する必要があります。たとえば、同じpssコードの同じピークは、ピークの対応する時間の前後の274サンプル内に表示されなくなります。次に、PSCコードとこの時間の前後の274ポイントがxc_incoherent_workingに設定されます。は0です。次に、対応するピーク時間の前後の274サンプリングポイントの範囲内の他のPSS値、そのパワーと以前に検出されたパワーの差が8db未満の場合、xc_incoherent_workingで修飾されたパラメーターの値を見つけることができませんこのしきい値も直接0に設定されます。前回はわかりませんでしたが、おそらくこのように整理されています。

xc_incoherent_workingは他で使用されておらず、エクスポートされていないため、これらのクリーンアップの目的は不明です。この関数の出力は、単なるセルのリストです。

3. sss_detect、次にSSSを検出、前のセルの結果を使用してさらに検出します。sss_detect_getce_sssとsss_detect_mlを呼び出します。sss_detect_getce_sssでは、最初にpss位置を使用してsss位置を見つけ、次に対応する位置のデータをチャネル推定のためにcapbufから見つけます。sss_detect_mlは、最尤アルゴリズムを使用してcpタイプを推定します。これにより、フレームの開始位置がframe_startであることがわかります。このようにして、最尤結果がしきい値と比較され、一部のセルがフィルターで除外され、最新のframe_start、cpタイプ、およびn_id_1(これは、現在のsssコードに対応する可能性があるものは不明)に格納されます。セルのリスト。

4. pss_sss_foeを実行し、pssおよびsss情報を使用して、正確な周波数推定を再度実行します。pss情報しかない場合、推定誤差は2.5khzです。sssの使用はより正確になる可能性があり、正確な頻度が推定され、セルリストに格納されます。

5. extract_tfg、メイン関数はこれを使用して、次のステップで時間-周波数グリッドを取得します。

 cvec dft_out=dft(capbuf.mid(round_i(dft_location),128));
 tfg.set_row(t,concat(dft_out.right(36),dft_out.mid(1,36)));

これらの2つの文では、capbufから取得したデータはdft、つまり離散フーリエ変換であり、tfgデータとして使用されます。これがメインコードですが、実際には周波数、時間校正、フレームヘッダー検索などの操作が必要です。

6. tfoec、最も正確な周波数と時間の校正は、メイン機能で行う必要があります。TFGで取得したサンプリングポイントを使用して、さらにキャリブレーションを行います。低S / N比の大幅な改善。

7. decode_mib、メイン関数は最終的にこの関数を呼び出して、MIB情報を復調およびデコードします。これで、すべての情報が時間-周波数グリッドtfgにあります。最初に、関数はchan_est関数を使用してtfgからチャネル推定結果を取得し、それらをce_tfgに格納してから、pbch_extract関数を呼び出します。この関数は、tfgとce_tfgからpbch_symとpbch_ceを抽出します。つまり、pbchのシンボルとチャネルの推定、次にpbch_ceを使用してpbch_symの重みを計算し、最終的なsymsを取得します。これらのシンボル(syms)はlte_demodulateを使用して復調できます。復調後、decodeやcrcチェックなどがあります。操作、これらの関数はすべてlte_lib.cppに実装されており、すべてitppの関数を呼び出す必要があります。特に復調します。lte_demodulateを呼び出すときに渡される変調方式はqamです。mod_mapの最初の2行によって生成されるtable(0)に対応するlte_lib.cppでmod_map操作の実装を確認できます。これはqpsk 4のように見えますポイントの座標値。しかし、itppにはqamのdemodulate_soft_bits関数が見つかりませんでした。

おそらく同じプロジェクトでLTEトラッカーを見たことがありますが、違いは、すべてをスキャンするまで1つずつスキャンして次のベースステーションをスキャンするのではなく、同じ周波数ポイントの基地局を追跡することです。

さらに、中国人によって修正されたLTE-Cell-Scannerも見ました

https://github.com/JiaoXianjun/LTE-Cell-Scanner

1. Hackrfサポートは、rtlsdr呼び出しを模倣して、いくつかのhackrf api呼び出しを追加するだけで、bladerfもサポートします。原理は同様です。

2. tddによってサポートされる実装方法は、最初にtdd_flagを作成し、次にそれがtdd基地局(主にsssに関連するフレームオフセットとは異なる)であると想定し、次に、仮説に従って、sssの可能性がしきい値より大きいかどうか、成功します。これは、それがtddであり、fdd基地局であると想定して、同じ手順を実行して、可能性を確認します(fdd基地局である場合)。

3. OpenCLアクセラレーションは、主にpssの相互相関計算に使用する必要があります。メインループで、xcorr_pssのxc_correlateをSampling_ppm_f_search_set_by_pssに置き換えます。

このサンプリング_ppm_f_search_set_by_pss関数を開いて見てください

#ifdef USE_OPENCL
lte_ocl.filter_mchn(s, pss_fo_set, corr_store);
#else
conv_capbuf_with_pss(s, pss_fo_set, corr_store);
#endif

//s是从硬件采集到的数据,也就是capbuf
//pss_fo_set是3种pss生成的序列
//corr_store是互相关结果
//这段代码先判断是否用opencl,然后使用两种不同方法生成互相关结果

 

おすすめ

転載: blog.csdn.net/shukebeta008/article/details/104195742