2015年5月29日金曜日

特小とデジ簡の周波数

SDR#のfrequencys.xmlにコピペできるデータ

特小では直接交信が20ch デジ簡では30chあります
広域レシーバや高級機になるとスキャンが出来ますが、あんまり便利じゃないですよね?
ですがSDR#などではスペクトラムを表示できるので、どのチャンネルで送信されているかを目で見て確認できます

デジ簡はSDR#ではデコード出来ないっぽいのでチャンネルの確認にしか使えませんが、特小であれば通常のNFMとして受信することが出来ます

ところでデジ簡ってどんなデータなんでしょう?
DPR-6には4FSKと書いてあるので、デジタル値への変換はできそうで、データフォーマットさえわかればデコードは簡単に出来そうな気がするんですけどねぇ SDRで聞けるようにならないかな


2015年5月18日月曜日

C#でNTPを使ってみる

C#のUDPでNTPにアクセスしてみました
今回使ったサーバーは ntp.nict.jp です(つまりStratum2以上のサーバーでの動作確認はしていません)

実行するとこんな感じになります

nictサーバーでStratumは1 クロックソース識別子は"NICT"です

5個の時間は上から
・サーバーがクロックソースと最後に同期した時間(サーバー時間)
・クライアントがリクエストを送信した時間(クライアント時間)
・サーバーがリクエストを受信した時間(サーバー時間)
・サーバーがレスポンスを送信した時間(サーバー時間)
・クライアントがレスポンスを受信した時間(クライアント時間)
となります
NTPでは2種類の時間系が存在することに注意してください

最初の1つを除いた4個の時間がそれぞれ ts, Tr, Ts, tr となり、サーバーから見たクライアントの遅延は ((Ts + Tr) / 2) + ((ts + tr) / 2) となります
クライアントの時間が進んでいる場合は負の値になります

NTP時間は整数32bit 小数点以下32bitの固定小数点形式です
C#で時間を計算する場合は、Math.Pow(2, -32)をNTPtime(UInt64)に掛けた積が秒となり、1900年1月1日0時0分0秒UTC±0からの経過時間です

C#ではシステム時間を変更することができるので、クライアント時間の遅延量がわかれば適切に修正できますが、気軽にシステム時間を変更するべきではありません
一気に時間を飛ばすと不都合が発生する可能性があるからです(もっとも、Windowsの標準機能でも一気に時間を飛ばしていますが。。。)

***

NTPと通信する場合は、リクエストを送信する直前に送信時間を記録し、レスポンスを受信した直後に受信時間を記録します
送信時間と受信時間の処理はNTPの精度に大きく影響しますが、その前後は精度にはさほど影響しません(もちろんレスポンスを受信してから何日もほっといてしまえば精度は劣化しますが、常識的な処理速度であれば問題ないでしょう)

今回のプログラムは送信前に時間を記録しておき、レスポンスが一定時間なければタイムアウトの例外を投げます
タイムアウトは初期値で2秒で、その間はブロッキングです
一応200ミリ秒程度でレスポンスが帰ってきますが、回線状態によってはもう少し必要な場合もあります

NTPのエンディアンはビッグエンディアンですから、C#のBitConverterのような簡単な処理方法は使えません そのためいちいちビットシフト等で計算しています

***

なぜシステム時間を変更するわけでもないのにNTPの時間を使うかというと、クライアントの遅延時間がわかれば、C#のAddSecondsなどで簡単に補正することが可能だからです

例えば人工衛星の位置を計算したい場合、相手は秒速8km前後で移動しているわけで、システム時間が30秒もズレていたら相手はおよそ250kmも移動してしまいます ISSなどは高度400km程度ですから、250kmというのは無視できません(35度くらい移動してしまいます)

ただNTPは常に使えるわけではなく、最低限何らかのインターネット接続できる環境が必要なので、できればPCの時間は常に構成しておくほうが望ましいです(Windowsって定期的にNTPと同期するはずなのにかなりズレてますよね。。。)

WindowsでNTPと同期した直後に以下のプログラムを走らせても数十ミリ秒位のズレがあるので、あんまり高精度は期待しない方がいいです

それと、最近のNTPでは「64bitNTPtimeの最上位bitが0の場合は2036年以降として処理する」みたいな約束がありますが、以下のプログラムでは未対応なので、あと20年くらいで使えなくなります
ま、20年後にこのコードを使う人もいないと思いますが、注意してください

2015年5月6日水曜日

ftoa関数(ひたすらループする)

浮動小数点数を指定した精度で文字列化する関数です

ftoaが本体です
第1引数:変換する値
第2引数:結果を入れる文字配列
第3引数:指定した長さに足りない場合に0を入れるか(偽で0x20埋め 真で0x30埋め)
第4引数:変換結果の最短長さ
第5引数:小数点以下の長さ

またftoafは第1引数にフォーマットの文字列を取り、第2引数に変換する値を取ります
このフォーマットはprintfの%fに使用するフォーマットに近い書式を設定できます

現在のところNaNやInf等の処理は行っていません
またいくつかのフォーマットを指定してsprintfと同じ結果になるように作っていますが、正しく実装されていない部分や、そもそも実装依存で環境によって違うなどの場合があるかもしれません
ループを多用しているので、コンパイラの最適化に依存しているコードでもあります
また内部で浮動小数点を割ったり掛けたりしているので、その間の演算誤差も無視できない場合があります  とりあえず「sprintfとか使えない環境で臨時に使う」程度で


追記:2015-05-06 15-07
一番最後にp--からp++までの間に入っている四捨五入処理ですが、最後の桁が9で切り上げるときに数字がコロンになってしまう問題があります
一番手っ取り早い対策はこのコードをコメントアウトすることです(もちろん四捨五入はされず、小数点以下切り捨てとされます)
数字が9だった場合は上の桁をインクリメントすればいいのですが、例えば999.96を小数点以下1桁まで表示した場合、繰り上げをすると先頭に1桁増やす必要があります
ということで小さな修正では対応できないので、近いうちにちゃんと作りなおそうと思います
追記ここまで