このところ「バイナリシーケンス」の操作に関する低レベルな関数を作製したりしてきておるのですが、ちょっと困ったことがあります。comm_tbx内のバイナリシーケンスの比較(ビットエラーの検出)をするための関数cmp_bits()がエラーで落ちます。今回はこの回避の仕方および「より低レベルな」代替関数作成。低レベル指向。
※「手習ひデジタル信号処理」投稿順 Indexはこちら
※Windows11上で、Scilab6.1.1およびScilab上のツールボックス Scilab Communication Toolbox 0.3.1(以下comm_tbx)を使用させていただいとります。
BER(ビットエラーレート)
デジタルな通信を評価する上で、BERはその一丁目1番地と言えましょう。どれだけの通信エラーが発生したのかその割合を%表示したものです。まあ実用的な通信では%どころか100万分率以下のコマケー数字となる筈ですが。
本シリーズでもScilabでのBERの計算関係の記事がございます。
手習ひデジタル信号処理(79) Scilab、BER(ビットエラーレート)をプロットしてみる
このときプロットは「成功」しておるのですが、それは「理論値」のプロットであって、実験したビット列から求めた数字ではありませぬ。
今回、生成したビット列の一致を確かめんとしてBERを求めることもできる関数cmp_bits()を呼び出してみたところ、まさかのエラー。
これ使えば良いや、と思ったら「ぎゃふん」(いつの時代だ?)であります。
まあ、手元のcomm_tbxではいつものことなんでありますが。。。
comm_tbxのcmp_bits()関数
cmp_bits()関数に比較対象となるバイナリシーケンス2つを渡すと、「リアラインド」されたバイナリシーケンス2個と、比較結果のエラービット数およびBERを返してくれることになっています。
「リアラインド」というのがクセものというか手厚いサービスです。複数渡したシーケンスの「コリレーションが最高になるように位置決め」してから計算しているみたいです。そのため元のシーケンスとはズレるのでズラしたシーケンスも返してくれると。それだけでなくPSKホニャララとか追加の引数もとれ、至れり尽くせり、みたいですが動きませぬ、手元の環境では。
エラーの原因を追究してみると、cmp_bits()内で呼び出しているpad()という関数が見つからないために落ちているようでした。pad()関数を調べてみるとcomm-tbx内の別カテゴリclock-recの中のfrac_delay関数内の片隅で定義されていました。一応comm-tbx全体をロードしてあるので、frac_delay関数もロード済の筈なのですが、動かしてみるとfrac_deay()関数自体 Undefined variableで落ちます。なんだかな~。負の連鎖だな。
とりあえず追及は打ち切って、別途pad()関数を定義してやったら、cmp_bits()関数は動作しました。とりあえずこの方法で元のcmp_bits()関数は動作させることが出来そうです。
しかし比較ポジションを「よきに計らってくれる」cmp_bitsに頼るのは低レベル指向としてはマズイかも。自分で比較ポジションを決めて、単純比較するやり方の方が明快。それであれば bitxor とれば良い。でもシーケンスの長さが異なったり、シーケンスにバイナリ以外が混入していたら引っかけたいデス。そこで単純だけれどシーケンスの検査機能を含めた自前関数を作製してみることにいたしました。
calcBER()
自前関数 calcBER()のコードが以下に
// calculate SIMPLE BER (by J.Halfmoon Nov. 9, 2023) // b1: binary sequence1 // b2: binary sequence2 // nerr: number of bit error // ber: bit error rate[%] // flag: Error flag if b1 and b2 is not binary or same length function [nerr, ber, flag]=calcBER(b1, b2) nerr = 0; ber = 0; flag = %F; L1 = length(b1); L2 = length(b2); if L1 <> L2 then return end B1 = members([0], b1) + members([1], b1); if B1 <> L1 then return end B2 = members([0], b2) + members([1], b2); if B2 <> L2 then return end comptemp = bitxor(b1, b2); flag = %t; nerr = sum(comptemp); ber = (nerr / L1) * 100; endfunction
引数のビット列2つの頭から比較するだけの関数です。相関最大等の操作をするのであれば、この関数を適用する前にしてね、という低レベルなもの。
そして以下のチェックも施します。
-
- ビット列の長さが異なるときはflagはFalse
- ビット列の筈なのに0と1以外の値が現れるときはflagはFalse
上記のエラーチェックに通った場合(flagはtrue)にのみ、ビットエラーの総数をnerrに関し、ついでにBER(%単位です。ppmとかではありませぬ)を計算して返します。こんな感じ。
低レベルな代替関数出来た、大丈夫か?