2026年2月4日水曜日

小ネタ


“宇宙からの信号”解読ゲーム『Signal Station』発表。レトロ機材を駆使して波形分析、政府や陰謀論者も狙う秘密のシグナル - AUTOMATON

 時代設定が1984年だそうで、野辺山45mとほぼ同時期くらいの感じかな。新しい望遠鏡をSETI的に使うのは難しいだろうから、実際には古い施設を使っている可能性もあるけど。そうするとパークスくらいの時代かもしれない。プレイヤーが信号をトラッキングし続ける必要があるならパークス前、自動追尾してくれるならパークス後、位の時代か。実際に遊んでみればいろいろわかるんだろうけど、テザーだけではどうにも。



 用語解説:リレーのN0、NC、COMとは、なんですか?

 あの…… パナソニックさん…… その……



 興味本位でGoogle AIにモバイルバッテリーの発火確率(自然故障由来)を宝くじ換算してもらったところ、1000万円が当選する確率くらいだそうだ。うーん、よくわからないや。でもまあわりあいありえそうなふんいきではあるかな。



 某書のあとがきに書いてあった、量子コンピュータが普及した時代の量子ネイティブの人間は感覚的に量子論を理解できるはずだ、みたいな話、僕としてはそこまで楽観できるとは思えないんだよなぁ。現代の古典コンピュータネイティブの高校生や大学生で、スパコンやスマホの動作原理を適切に理解している人がどれくらいいるのか。理系の大学生でスパコンを使っているような人でも、全員がその仕組みまで理解しているというわけではないはず。もちろん古典コンピュータの動作原理を詳細に理解している大学生というのはいるだろうけど、そんなこと言ったら量子論をある程度正しく理解している大学生だって今の時代(非量子コンピュータネイティブ世代)でもいるはずだし。

 古典コンピュータで使われている信号は量子を統計的に見たものだから自由度が高い(ビットの表現が自由)、あるいはそれを扱う方法(半導体、真空管、機械式、etc)が大量にあるのに対して、量子コンピュータはQubitの自由度がかなり低い(少なくとも大量の量子を統計的に扱うようなことはしない)みたいな違いがあって、量子コンピュータのほうがより理論的だから理解がしやすい、みたいな可能性はあるけど。



 Gmail、署名&暗号化されたわりと重要なメールをフィッシングメール扱いして迷惑メールフォルダに突っ込むの、アホ。おまえが署名必須化で引っ掻き回したあげく署名を信用しないって、なんのために署名必須化させたんだよ。かと思えば迷惑メールを重要なメール扱いすることもあるし。


 去年の12月に急に話題になったような気がする、「Gmailが来年の1月から外部メールを受信できなくなる」騒動、「1月から受信できない」というのを「1月に入ってからは受信できない」と解釈していたのだけど、1月に入ってもまだ外部メールの受信が続いているし、じゃあ「1月中に受信できなくなる」or「1月末に受信できなくなる」という意味かと思っても、2月に入っても受信が続いているし、一体何だったんだ、という感じ。

 ビッグテックと呼ばれる企業(e.g. GAFAM)の中でもGoogleは頭一つ飛び抜けて広い範囲に迷惑をかけている(混乱を振りまいている)気がする。まるでバベルの塔にキレた神の如き。これがインターネットの神か……



 Webサイトの広告、基本的に目を引く(要するにウザい)広告が多いけど、最近は「数秒の広告を視聴すると24時間表示されなくなります」系の広告が結構普及している気がする。で、この広告の何がウザいかって、多くて1週間に2,3回しかアクセスしないサイトに設置されている場合に、毎回必ず見なきゃいけないという点。

 Webサイトの3秒ルールとか言われていたのは大昔の話だけど、5秒って。。。しかも読み物系とか報道機関みたいに一つの記事をある程度時間をかけて読むようなコンテンツなら5秒のロスも許容できるかもしれないけど、ちょっと気になってググって、しかもテキストを2,3秒流し見するだけで確認が終わるようなコンテンツに対して、5秒の待ち時間はさすがに無理。Ctrl-Wで閉じて別の検索結果を見るほうが早い。広告は見られないし、Webサイトのコンテンツも見られないし、読者は手間が増えるし、誰も得をしていない。

 特にそれがIT系の解説サイトだったりするとな。おまえなんのために高いカネ払ってレスポンスのいいサーバー使ってんだよ、クソみたいな広告出すくらいならページの表示に4秒くらいかかるような遅いサーバーでもいいから安いやつ使って広告減らせよ、という気になる。

 自分は基本的に検索結果から気になるサイトを2,3個新しいタブで開いてから、そのタブを確認する、みたいな見方だから、バックグラウンドで読み込んでくれる分には読み込みに5秒とかかかってもあまり気にならない。一方で必ずタブを5秒以上表示しないとメインコンテンツが見れない、みたいな広告はかなり苦しい。

 最近はサイト内リンクの枠を全部含めても面積比で広告のほうが多いWebサイトとかも目につくからなぁ。それに比例してコンテンツの内容も質素になっている気がするし。やはり資本主義は悪……ッ!!!



 厚さのあるガラスの両面にQRコードを印字して姿勢を高精度に求める、みたいなブツの空想。

 ガラスの両面に吸収スペクトルの違うQRコードを印字する。裏表で同じ位置にQRコードが貼り付けてある。このコードをカメラで読み取ると、2つのQRコードが重なった状態で認識される。ただし吸収スペクトルに差があるから、例えばRedとBlueで読み取ることで手前側と奥側を識別できる。

 QRコードを認識する際にドットの位置を精度よく認識することで、QRコードの姿勢を解析する。この方法の場合、上下左右の位置と奥行き軸の回転の3自由度は高い精度が得られるが、奥行方向の位置や上下左右軸の回転感度は低い。提案手法の場合、奥行方向にQRコードが重なっているから、ドットの位置関係を利用することで上下左右軸の回転に高い感度を持つ。同様にして奥行方向の位置にも比較的高い感度を持つ。

 QRコードの中身にはQRコード自身の物理量を入れておくことができる(例えばマーキング対象の物体に対する位置・姿勢を行列やベクトルの形で保存する)。他にも、マーキング対象の物体自身に関する情報(商品名や部品名、部品のロットやシリアル番号等)も保存できる。

 透明な媒体を画像認識するので、1回の撮影で非接触かつ高い精度で相対姿勢を把握することができる。という利点はあるが、具体的な用途として何があるかというと…… 大抵の場合は複数のコードや複数のカメラで解決できるからなぁ。


***


 RJ45の安い圧着工具を買ってみた。工具とテスタだけかと思ったら圧着端子とブーツも100組くらい入っていた。これでお値段3000円台前半。こわい。

 工具はオープンのスプリングが入っていて、閉じた状態で固定するラッチもないし、テスタもめちゃくちゃ安物っぽい雰囲気だけど。コネクタもどれくらい信用していいのかわからないけど、とはいえ今の時代LANケーブルの圧着端子なんてだいたい中国製の安物だろうしなぁ…… 練習のために組むなら問題なし。

 Cat5eはAmazonベーシックの50ft(15.2m)で1000円というめちゃくちゃ硬いやつを切って使用。単価66円/m程度なので激安の箱売り(30円台前半/m~)に比べて安いわけではないけど、普通の箱売り(80円/m前後)に比べれば安いし、そもそも1軒家にLANケーブルを引き回したいわけではないので、箱買いする必要もないし。


 ということで、適当に結線して遊んでみたり。

 ツイストレートは青、緑、橙、茶の順かな。青が2.9TPI、茶が1.5TPI、くらい。

 下においてある5本は、左から、4ペアストレート、2ペアストレート、2ペアクロス、4ペアクロス(2クロス2ストレート)、4ペアクロス(2クロス2クロス)、という感じ。普通の4ペアクロスは2クロ2スト(橙緑がクロス、青茶がストレート)で結線されている。


 568Bで結線する場合、コネクタを上に向けて爪側から見た場合(下段の5本の上側コネクタの状態)に、右端(1番ピン)から橙、その次が緑。ただし歴史的な事情?で中央の2ピンを飛ばすから、10BASE-Tや100BASE-Tのように2ペアだけ使う場合は1,2,3,6ピンを使う(下段の左から2本目)。1000BASE-Tのために4ペアが必要な場合は、飛ばした中央2ピンに青と残りに茶。

 被覆がストライプになっている線が正極で奇数番、ソリッドな線が負極で偶数番。緑が飛ぶので青は逆になるけど、基本的には右側にソリッドを入れる。

 コネクタを上に向けてコンタクト側から見て左が1番ピンだけど、コンタクト側から見ると金属で線が見づらくなるから、爪側から見たほうが見やすい気がする。あと、ちゃんと奥まで刺さっているかを見るには爪側から見たほうが確実。線を押し込んだと思ったら1本入ってなくてコネクタの中で折れ曲がっていた、みたいなこともある。この場合、2分の1の確率で100BASE-Tで接続できてしまうので、気が付かずに使っていると速度が出ないということになりかねない。

 568Aは橙緑がクロスする(青茶は基本的にクロスしない)。

 568のピンアサイン、橙緑青というのは覚えなきゃいけないけど、ストライプ/ソリッドの順番は奇偶で決まっているし、わりとわかりやすい気がする。10回くらい圧着すればだいぶ慣れてくる。橙緑青茶は色相で見ると順番に並んでいるから、それで覚えるという手も…… ちょっと厳しいか。

 緑が飛んでるのは、電話用のモジュラージャックみたいに中央を使っていたやつに配慮して、ということだと思うんだけど、帯域幅を広くして使おうとするとクロストークとか大変そうだなー。今更順番に並んだコネクタを作ろうという話にもならないだろうしな。


 2ペアのストレートケーブルをテスタで見てみたら、正しく親子機両方で1,2,3,6が結線されていると表示される。一方で、2ペアのクロスケーブルをテスタで見ると、2-6,3-1,6-2が表示され、1-3の結線が検出されない。

 普通のクロスケーブル(4ペア結線、橙緑だけクロス)では、1-3,2-6,3-1,4-4,5-5,6-2,7-7,8-8と、正しく表示される。

 橙緑と青茶をそれぞれクロスさせたケーブル(一般的ではない4ペアクロスケーブル)を作ってみると2-6,3-1,4-8,5-7,6-2,7-5,8-4として表示される(1-3の結線が検出されない)。

 2ペアおよび4ペアのストレートと4ペアの一般的なクロスの3種類は正しく見えるかな。安物のテスタなので、一般的ではないケーブルは適切に処理できないっぽい。あくまでも正しく結線されているかどうかを確認するためのもの。まあ、普通はそういう製品で十分だしな。


 上の写真に写っている5個のケーブルは、スイッチから4ペアストレートで引いてきて、Cat5e中継コネクタ経由でノートPCに接続して、オートネゴシエーションで認識させれば、正常に動作する。2ペアしかないものは100BASE-Tとして正常に動作するし、4ペアのものは1000BASE-Tとして正常に動作する。少なくとも、簡易的なスピードテストで見る限り、2ペアは100Mbpsギリギリまで出るし、4ペアのものも100Mbpsを超える速度は出る。といっても、回線があまり早くないので、せいぜい150Mbpsとかその程度だから、実は大量に不良パケットが発生していても、気付けないわけだが。


*


 ケーブルテスタの中身


 左側が親機、右側が子機。

 子機はRJ11とRJ45のコネクタに、LEDが9個、ダイオードが3個、というシンプルな構成。

 親機はRJ11とRJ45にLEDが10個、ダイオードが5個、抵抗が2個、スイッチが1個、COBが1個、という構成。面積広めのパターンがポツポツ膨らんでいるのが謎い。ベーキングせずにリフロー炉に入れて剥がれてきてるとか?


***


 STM32F1/W5500でNTPクライアント。割り込みをタイマで受けて送信時刻と受信時刻を高精度に(マイクロ秒程度で)計測。試しにCloudflare、AWS、Googleの3サーバー(IPアドレス固定)に対して10分程度の間隔(5-15分のランダム)で計測。

 マイコンが起動した時刻を原点として、θはNTPに対するマイコンの遅れ時間を、δは通信遅延を計測。いずれの軸も単位は秒、ただしθ-1次の右軸はミリ秒。

 θはマイコン起動時のNTP時刻に相当する量がオフセットされている。傾斜はマイコンのクロックエラー成分が見えているもの。傾きは12.8ppmで、通常の水晶のクロックエラーに矛盾はない。正の値から減少しているので、水晶が早い方向。

 θ - 1次はマイコン(水晶)の時刻ズレやクロックエラー成分を大雑把に除去したもので、クロックの変動を示している。ただしそれぞれ数msずつオフセットしている(平均値はオフセット無し)。基本的には温度特性だと思うけど、温度は未計測なので詳細は不明。やはりこういうものを測るときは温度計も必須だな。体感(&タイミング)的には温度が上がると減少幅が減るので、おそらくATカットの0℃付近から40℃付近までのカーブを見ているんだと思う。冬の北海道なので、もっと暖かい環境なら誤差はもう少し小さくなるはず。

 δは通信遅延成分。NTPサーバー内の遅延は除去済みだが、最近のNTPサーバーはほとんど遅延なしに応答を送ってくるので、基本的には送受信の間隔。遅延は国内サーバーと想定されるCloudflare/AWSは安定、おそらく海外サーバーのGoogleは若干不安定。


 θ - 1次を見ると、CloudflareやGoogleはノイズが見えるのに対して、AWSはノイズが少ない。

 平均値を見ると、AWSとGoogleはほぼ重なっているが、Cloudflareは明らかにバイアスがある(前にPCで複数のNTPサーバーを比較した際も、Cloudflareはバイアスがあった)。

 下の方にはAWSから見たCloudflareとGoogleの差を表示している。Cloudflareは2-3ミリ秒程度のバイアスがある。Googleは±1ms程度、大抵の時間は±0.5ms程度に収まっている。一方で、振幅を見ると、Coudflareは比較的狭い範囲で、Googleは若干広がって出ている。これはサーバーまでの経路の問題だと思う。AWSとかNICTみたいに国内にある信頼性が高いであろうサーバーを参照する場合、NTPの精度は頑張れば0.1ms程度までは期待できるかな。確度はまた別の話(AWSはスミアリングもあるし)。



 今回は高頻度にNTPサーバーに取りに行きたかったので、日系法人サーバーには触らなかったけど、気兼ねなく高頻度に叩けるNTPサーバーとしては、Cloudflareは明らかにバイアスがあり、Googleは海外サーバーであることを考えると、AWSが一番いいかもしれない。

 AWSはクラウドサービス大手として安定したシステムを構築したい、という前提があって、それのタイムスタンプを流用したNTPの性能も良い、と考えることもできそう。そう考えるとMicrosoftもAzureを提供しているので、それと比較しても面白そう。ただMicrosoftやAppleはあくまでも自社のOS向けのNTPサーバー起源だと思うので、時刻精度をどこまで追求しているかは怪しい気もする。

 NICTみたいに精度が高いであろうサーバーと比較したりするべきなんだろうけど、いちおう頻繁に叩くなよと明示されているからなぁ。1日480回以内だから10分間隔(1日150回程度)なら怒られることはないだろうけど。

 あとは、GPSモジュールのPPSで時刻決めしたさもある。タイマの外部入力ピンに1PPSを接続して、1秒の曖昧さは無視する、みたいなことをやるのが一番手軽ではあるけど、PPSを出せるGPSモジュールか。。。


 タイマを時刻基準にするとマイコンのリセットで原点が動く欠点がある。本来はRTCみたいにコアリセットには影響を受けない時刻系を使いたいんだけど、STM32F1のRTCは結構使いづらそうな感じ。でもF1のRTCは32bitカウンタとプリスケーラが入っているだけなので、読み書きに注意すれば、NTPみたいに元期からの経過秒数を扱うシステムとは相性がいい(ただし32kHz分解能)。F4とかだとカレンダ機能が載っているから、NTPと比較するなら年月日時分秒を変換する処理が必要になる。

 一番手っ取り早いのは、適当なマイコンで1MHzと1PPSのクロックを出して、適当なタイミングで次の1PPSの時刻をUART等で出して、時刻の基準はそれで決めて、NTPみたいにソフトウェアを書き換えたい(コアリセットをかけたい)用途のマイコンとは切り離して、みたいな感じかな。なんか冗長な感じではあるけど。


 10MHz+1PPSを出すようなクロックは色々な市販品があるから(e.g. GPS受信機)、それに組み合わせるタイムコードの標準とかも探せばあるんだろう。そういうのに従うのが楽だろうけど、STBeeMiniで10MHzは作れないのでな。。。STM32F1のPLLは大部分が2^Nで指定するので、12MHzのクロックを積まれると使いづらい。8MHzを積んでいてくれたらありがたかったなぁ。

 IRIGタイムコードは基本的に高周波(10MHzとか)とは無関係なはずだから、1MHz+IRIGみたいな組み合わせをやってもいいんだろうけど。


*


 DNSやNTPはanycastで実装されているものが多いので、例えば1.1.1.1や8.8.8.8で別の地域にあるNTPサーバーを調べることはできないし、別の国のISPが提供しているその地域向けのDNSサーバーに問い合わせても、time.google.comやtime.cloudflare.comは同じIPアドレスを返すから、そのNTPサーバー(IPアドレス)に問い合わせを行っても、やはりインターネット地理的に近いサーバーからの応答が帰ってしまう。

 time.aws.comはNTPサーバーごとにIPアドレスが別れているらしくて、おそらく別の国にあるであろうDNSサーバーに問い合わせを行うと、ユニークなIPアドレスが得られる(実際にNTP問い合わせを行って遅延を確認したわけではないけど)。

 GoogleやCloudflareはとにかくサービスを提供できればいい、そのためには1箇所のデータセンターが死んでもIPアドレスを変えずに別のデータセンターに到達できるanycastが良い、みたいなことなのかもしれない。IPアドレスの割当や管理の手間も省けるだろうし。

 対してAWSはそもそもAWS内で高精度な時刻が欲しい、という要求が先にあって、そのあとでNTPを公開したから、NTPに関しても問い合わせ先がIPアドレスに紐づけされていて、場合によっては勝手に別のデータセンターを参照してしまう(精度・確度が変動する可能性がある)anycastを避けた、みたいな理由があるのかな。


 海外のDNSサーバーも、例えばその地域で有力なISPのDNSのIPアドレスを調べても、nslookupでタイムアウトするということもある。自分たちがカバーしていない地域(or自分たちと契約していない回線)からのアクセスは捨てるみたいな処理があるのかも。


 ということで、大手IT企業が提供するNTPサービスで、他の地域のサーバーに取りに行くのは結構大変そう、という雰囲気。

 そもそもNTPは直近のサーバーを使うべきだという話なんだけども。


***


 Flightradar24から「おまえんとこのフィード止まってるけど?」とのメール。ここ数年は安定して稼働していたので、かなり久しぶりだ。

 古いRasPiで走らせていたやつで、microSDから工夫なしに常時起動なのでそろそろ寿命かな、ということで、別のmicroSDにOSを焼いて初期設定をいろいろやったのだが、どうにもうまく行かない。うーん、困った。結構前にも同様の事象があって、そのときはOSの入れ替え等で直ったんだが。

 なんか動作が遅い気がする(例えばログインIDを入力してからPassword:の文字が表示されるまでにかなり時間がかかる)ので、RasPi本体側もなにか不具合があるのかな、と当たりをつけつつ、どうしたものかと思いながら在庫を漁ったら、大昔に買ったRasPiがあったので、それにOSを入れ直し。10年以上前に買ったやつだと思うが、あの頃って何故か色々大量に買い込んでたのよな…… あの頃のバイタリティ(&金銭感覚)がかなり謎い。最近はマトモ(流通ルート含め)な電子部品は1個も買ってない気がする。

 別のRasPiにインストールした方はだいぶ軽い気がするけど、でも通常版RasPiOSとRasPiOS Lightの違いな気もする。とはいえ、前のRasPiはapt upgradeを何回やっても完了しなかったのが一発で終わったり、だいぶ安定に動いている気がする。GUI側と競合してただけでは?とか考えるとやっぱりOSの違いなだけのような気もするけど。

 しかし、OSの更新やらフィードの設定やらがすんなり終わっても、やはりステータスを見るとオフラインのまま。


 topで見るとfr24feedがS(Sleep)になっている。でもtopの説明だとSはイベント待機とかの状態らしいし、よくみるとまれにCPU使用率が0.0より大きくなるから、たぶん動いているはず。ではなぜfr24に上がらないのか……

 そもそも、大昔のRasPiでたかだか0.5%未満のCPU使用率でADS-Bがデコードできるとも思えない。fr24feedってdump1090のデコード結果を投げるようなものだと思うけど、topを見る限りdump1090が走っていない気がする。

 どうせaptで取れるやろ、と思って試してみるも、入らなかった。だからfr24feedも正常に動作していないのかな?


 ADS-B受信をdump1090-faに変更 | My Blog

 を参考にソースからビルド。ただしこのブログのコマンド列は順番が逆で、先に2個目のapt install(引数が少ない方)を打ってからget cloneで取って、ビルドとインストールを行う(少なくとも先にgitをインストールしておかないとgit cloneはできない)。

 systemctlでdump1090-faを開始して念の為にreboot。topを見るとdump1090-faのCPU使用率が50%超、PCからデバイス名.local:8080を開くとPiAwareの画面が表示されるので、少なくともサーバーは動いている。デコーダが動いているかどうかは不明。相変わらずオフラインのままだし。

 topでCPU使用率のusとsyの和がほぼ100でidがほぼ0なので、処理に余裕がない。処理に余裕がなくてfr24feedが正常に動作していないのかも。


 漁っていたときに見つけていた、一つ新しい版のRasPiに変えてみた(元々走っていたのと先に交換したのがRasPi1B+、新しいやつはRasPi2B)。

 先に上述の手順でdump1090-faを入れてから、Share your ADS-B data - Real-time flight tracker | Flightradar24 のコマンドでfr24feedをインストール。初期設定はメールアドレスとシェアリングキーを設定。先に入れたdump1090が認識されるので、それでフィードが始まる。はず。これによってtopが88.4 idと、かなりの余裕が見える。単純にクロックが2倍になっただけでなく、コアの効率も良くなったんだろう。

 Fr24のMy accountだとすぐにOnlineになったけど、Statisticsで見るとOfflineのまま。どうしたものか。

 その後数時間ほど放置してから確認すると、STATUSはOfflineのままだけど、10nm程度だけどいくつかレポートが上がっていたので、最低限デコードしてレポートは動いているはず。いくつかの方向にはレポートが全く出ていないとか、レンジが狭すぎる気もするけど、そもそも普段は定期便が数時間に1本通る程度しかトラフィックのない場所だから、その機体が家から10nm程度の場所を通過した、位の意味だと思う。長時間受信していればもう少し分散するはず。

 その後、航空機が通過しているときに再読込したらSTATUSもOnlineに戻っていた。fr24feedはUDPでパケットを投げているのかな? おそらく投げるデータがないときは何も投げていないんだと思う。ハートビートも無いだろうから、サーバー側からすると受信機側で航空機が見えない時間帯はOffline扱いになるんだと思う。世界中に大量のクライアントが置いてあるから、いちいちクライアントと全部コネクション作ってたら大変ってことなんだろう。

 さらに数日放置してみると、ちらほらとレポートが上がっているので、たぶん動作しているはず。相変わらず時々Feeder outage notificationのメールが届くのが謎。最近は全く届いていなかったんだけどな。メールを探してみると前に届いたのは2022年11月なので、5年以上安定して動作していたのか。すごい。その間に停電で1回止めているから、数十分止まっている程度なら通知は出ないんだな。

 最近になって急に届くようになったのが謎いけど、航空便の運用の変更で深夜帯にレポートが出なくなって、それでFr24側でタイムアウト判定された、みたいなことなのかな? そう考えると、最初のオフライン通知も実は誤報で、RasPi自体は正常に動作していた可能性もあるのか。まあ、今更気にしてもしょうがないし、更新のいい機会だったと考えよう。。。そんなこと言ったら10年以上使い続けているワンセグチューナーも更新しろよ、って話になるんだけど。気が向いたら安い受信機を1本注文しようと考えつつ、でもRTL-SDR blog v3ドングルも手持ちにあるので、イザとなればそれを使う方向で。どうせ必要になるまで買わないんだろうなー。


 ということで、おそらくfr24のフィーダは復旧。

 とりあえず、RasPi1B+で最近のdump1090を走らせるのは無理、RasPi2Bなら結構余裕、自分で古いRasPiでセットアップするならdump1090はgitからビルドする必要がある、fr24feedの初期設定はdump1090をインストールしてから、といったあたりが、今回得られた知見。

 そもそもRasPi3B+以降を使っていればFr24公式のイメージが使えるはずだから、イメージを焼いてシェアリングキーを設定するだけで使えるようになるんだろうけどな。でもRasPi4の値段高いよ。。。Fr24のGoldプラン約1年分(アンテナや電源等の周辺機器を含めれば約2年分)と考えれば、長期的に使えば元は取れる値段ではあるのだけども。


 topで表示すると、dump1090-faもfr24feedもS(Sleep)のまま、dumpは46%CPU程度、fr24は0.3CPU%程度の表示。基本的にイベントドリブンなのでtopでサンプリングするとSleepで固定らしい。idは88%程度の表示。topのタスクは1コア相当、Cpu(s)は全コアのトータルらしく、RasPi2Bのクアッドコア換算では1つのコアを45%使うと残りは88.75%になる、ということで、数値としては正しそう。dump1090-faは2倍程度重くなってもまだ耐えられるし、別のスレッドの処理は別のコアに割り振られるから、Webサーバーが走っていても問題なし、ということだと思う。


 試しにSkyAware(8080ポートのやつ)を見ていたら、自前のMark Xデコーダよりはるかに遠くから受信が始まっていた。Mark Xは誤り検出が無いから閾値を厳しめに設定していて、Mode-Sは誤り検出があるからアグレッシブにデコードできる、という違いなんだろう。無線みたいにダイナミックレンジが広い伝送媒体の場合、FECまでいかずとも、誤り検出があるだけでも伝送レートが格段に上がるな。

 Mark Xも適当なフィルタ(一定時間で一定個数受信しないと表示しないとか)で閾値を下げればもう少し遠くまで見えるんだろうけど。でもATCレーダの回転周期が数秒、ACASのインテロゲーションが1Hz程度であることを考えると、閾値は30秒で20個とかだろうから、最初に出てくるまでにかなり遅延がありそうだ。

 ADS-Bでは、頻度は低いけど、たまにほぼ200km先から受信していることもある。飛行高度2万ftとして電波の見通し距離は300kmくらいになるから、水平線まで障害物がなければ200kmくらいは届くのかもしれないけど、それにしてもチャチなアンテナ1本でアンプもなしにそんなに見えるものなのか。



 あまり関係ないだろうけど、RasPiがWiFi APのハブ経由でGbEハブに接続されていたので、以前使っていたGbEハブを追加してそれ経由で接続。8ポートのハブ1個じゃ足りない。。。2個のハブを重ねて置いたので、10cmに満たない短いパッチケーブルを作成。実用のケーブル作成には使わないから……と思ってたけど、工具があれば使うんだよな。

 Amazonベーシックのケーブルはさすがに被覆が硬すぎるので、もう少し柔らかいケーブルを買っておいたほうがいいかも(今回は超短距離なので外皮を剥がして使用)。長距離を引くわけじゃなくて、ハブ-機器間のせいぜい2mとかのケーブルを作るだけなら、10mくらいのケーブルをストックしておけば良さそう。


***


 fl2kを使おうとしてC#でDllImport経由で叩いているんだけど、fl2k_closeを呼ぶとExecutionEngineExceptionが出る。

 C#が悪いんかと思ってcygwinのdlsym経由で呼んでみても、やはりfl2k_closeでSegmentation faultが出る。

 fl2kからはバッファに突っ込んだ波形が出てくるから、fl2k自体の操作はできているはず。あくまでもfl2k_closeだけが正常に動作しない。デバイスが閉じられないだけであって、使えないことはないけど、ちょっと気持ち悪い。



 試しにWindows11/MinGW環境でビルド。pacmanでいろいろ入れて、buildの中でcmake ..やってninjaを実行。ただしgetopt周りがうまく動かない。今回はDLLが欲しいだけであって、実行ファイルは必要ないので、CMakeLists.txtの中のBuild utilityをすべてコメントアウト。

 libosmo-fl2k.dllが作成されるので、試しにdumpbinに突っ込んでみると、一通りの関数が見える。libsomo-fl2k.cに適当な関数を作って再度ninjaとdumpbinを叩くと、追加した関数が追加されるので、正しくビルドできているはず。


 試しにcygwinでもビルド。何を入れたか覚えてないけど、git, cmake, gcc, g++, libusb1.0-devel、あたりかな。cygwinだとCMakeLists.txtやソースコードの変更もなく、ただcmake ..とmakeだけでビルドできた。足りないライブラリがあればcmakeでエラーが出るからそれを入れる。出てくるdllがcygosmo-fl2k-0.dllという名前だから、cygwin用の最適化なり設定なりが入っている可能性もあるけど、少なくともdumpbinからは見えるから、大丈夫なはず。

 気まぐれに、というか、どっちもlibusbやろ、という短絡的な理由でairspyone_hostの開発環境にならってMinGWを最初に試してみたけど、最初からcygwinで試せば簡単だったな。

 cygwinのgccでlibosmo-fl2k.dll.aを指定して、exeと同じ場所にdllを置いてやれば、osmo-fl2k.hをインクルードして呼び出せるので、dlopenでパスを指定してdlsymでポインタを取ってキャストして、みたいな手間はない。ただ、今回の場合はosmo-fl2k.dll側をゴリゴリ書き換えたいので、dllをexe直下に置くのはちょっと面倒。

 Google AI曰く、-Wl,-rpathで探索ディレクトリを追加できるよ、とのことだけど、色々試してみても全く効果がない。Copilotに聞いてみたところ、-Wl,-rpathはELF用のオプションだからEXEには意味がないよ、とのこと。なるほどね。別件で使ったときも含めて、Google AIはハルシネーションが多い印象。

 今回の場合はPATHに一時的にDLLの置き場を追加するのが一番楽そう。/* あとから考えるとちょっとやり方ミスってただけっぽい気もするけど、今更掘り返すのも面倒だし、、、 */


 試しにfl2kから3chの正弦波を出すサンプルをC++で書いてcygwin/g++でビルドして走らせてみたら、なぜかfl2k_close含めて問題なく動作。あれれー? ただしlibusb error [31]が出る(正弦波は問題なく出るが)。

 ノートPCでビルドしていたので、試しにデスクトップPCに持ってきたら、DLLが見当たらないというエラー。なんでぇ。。。デスクトップ側のcygwinでビルドし直しても、相変わらずDLLが見当たらないまま。なぜだ。。。

 これらのDLLをC#から読み込んでみると、Cygwinでビルドした方もMinGWでビルドした方もDllNotFoundException 0x8007007Eが出て関数が呼べない。

 難しいねぇ。。。


2026年1月28日水曜日

小ネタ






 欧州のDMGって大きなイベントがあるとドローン映像を撮ってるけど、これってDMGの社員がやってるんだろうか? それとも外部の会社に発注してるんだろうか?

 欧州の映像だからか、25fpsでちょっとカクカクな感じが残念。せっかくドローンで取るなら50pとか60pで見たほうが綺麗だと思うのだが。



 京セラの自販機


 工場とかで必要な小さな消耗品の管理を行うためのソリューションらしい。

 日本だとミスミの自動販売機みたいなものがあるけど、京セラの自販機はあくまでも在庫管理や商品の提供を目的としているものであって、商品の補充や発注は顧客側(工場側)が行うのかな? あるいはそのあたりもなにかソリューションがあるのかもしれないけど。



 ロシア政府、“ロシア版『コール オブ デューティ』”の開発に「数百億円規模」の援助表明。「『CoD』はロシアを敵にしてばかりだ」として自前で作る - AUTOMATON

 プロパガンダ用に欧米で低価格でリリースして、陣営入れ替えModが作られて、セキュリティの欠陥で国家の尊厳に重大な損害を与えた、みたいな理由で開発会社に制裁金を課して、援助資金を回収、みたいな可能性。

 どんな内容のゲームを作るにしろ、「そっちが作るならこっちも作るよ」の口実になるだけな気がするけどな。でもCoDやBFみたいな巨大なフランチャイズがロシア政府や正規軍を敵にする作品を作れるとも思えないし、かといって完全新作で作るにもリスクがでかいし。政府がガッツリ資金提供するロシア版CoDは作られども、欧米側からそれに対抗できる作品が出るビジョンは見えん。ウクライナ政府が、という可能性もあるけど、それはそれでまたロシアが反発するだろうしなぁ。



 某レースゲーで建設できるらしい大型パラボラアンテナ、景観は野辺山っぽいけど、副鏡支持構造はあんまり日本の大型アンテナっぽくはないな。前作メキシコマップに置かれていたLMTモチーフの望遠鏡のアセットをそのまま使ったんだろうか?

 実物のLMTの副鏡支持構造はシンプルな棒状のフレームを斜めにクロスさせている。対してゲーム中のLMTはシンプルな棒状のフレームを垂直・水平にクロスさせている。大きさはだいぶ違うけど、三菱電機が作ったアタカマコンパクトアレイ(7m)は副鏡支持構造がシンプルな棒状を水平垂直に近い角度でクロスさせているから、FH5のLMTとは相似な感じ。

 結果として、次作FH6の巨大パラボラアンテナも、三菱電機のACA7mに近い形になっている。

 とはいえ、FH6の巨大アンテナはおそらく富士山とアルペンルートの中間付近に所在する野辺山がモチーフだろうし、いくらメーカーが同じとはいえ、ACA風ではなく45m風にしておいてくれると嬉しかったな。


 そういえば某VTuberが野辺山と関わってるな…… 「野辺山45mが出てくるらしいよ」って勧誘しよう(やめなさい

 45mはたぶん某アニメでも出てるだろうし、下手なモデルを使うと日本国内ではウケが悪そうだが。まあ、おそらく顧客層が違うから問題ないか。



https://www.hrr.mlit.go.jp/yukimirai-toyama/ouboronnbunn/30_tateyamayuuryo.pdf

 立山黒部アルペンルートの除雪作業に関して。H10年(1998年)以降はGPSも併用。それまでは、降雪前に路肩へ立てたポールを目印に作業していた。GPSを使う場合は除雪領域のセンターをGPS付きのブルドーザーでパイロットルートを作成し、それを掘り下げる作業要領。

 1998年のGPSはRTKを使っているかどうか悩ましいところだな。


https://www.giho.mitsubishielectric.co.jp/giho/pdf/2007/0701005.pdf

 三菱電機の高精度GPS測位サービス(PAS)を納入、2006年3月開通時の除雪に使用された。山間部なので補正データは衛星携帯電話経由で配布。

 ということは、その前の数年は通常のGPSを使っていたんだろうか?


https://jsurvey.jp/pcrg/kyougikai.files/m9.pdf

https://jsurvey.jp/pcrg/kyougikai.files/j23.pdf

 アルペンルート除雪に使った三菱電機のGPS受信機の説明。ネットワーク型RTK-GPSだそう。水平方向数cm、垂直方向10cm程度の精度。通常のRTK-GPSに比べて固定点を数kmおきに設置する必要がない、とアピールしているから、それまでは固定点を使ったRTK-GPSを使っていたのかな? そりゃまあ、S/A解除前のGPSで道路の除雪作業は無理か……


 準天頂衛星みたいに高仰角の衛星が増えて20mの壁の間でもRTKが使えるようになると、CADデータを入れたICT建機で綺麗に壁を削れるようになったりするんだろうか?



 会社の略称でCompanyの意味で後ろにCOとついてるところ、WebサイトのURLがhogeco.co.jpとかでなんか冗長な感じ。hoge.co.jpじゃだめなんか?

 co.jpならたいして変な場所にも飛ばんやろ、と思ってhoge.co.jpにアクセスしてみたらちゃんとタイムアウトするから、そのドメインは空いているはず。そっちを使えばいいのに。あるいはリダイレクトさせるとかでもいいけど。



 ユーザーアカウントの作成とかでパスワードを入力する画面、ランダムに配置したキーボードとか、タップするたびに配置が変わるキーボードとか、そういうのがあると嬉しい気がする。並んだキーをタップするとか、同じキーをタップするだけでランダムな文字列を作れる。入力した文字列を別途覚えておく不便さはあるけど、自分でランダムな文字列を作る場合は、ランダムなキーをタップして、それを覚えて、みたいな手間がかかるから、片側だけでも省略できるのは便利そう。ブラウザのパスワード生成機能を使えば両方とも省略できるから、それに対応していない場所でパスワードを考えるのが面倒、という話。



 ボルトを上から入れるか下から入れるか、という話の解説記事で、「ボルトを下から挿入した場合、下部に構造物があれば脱落することを防げます」とか書いてあって(完全には脱落せず、少なくとも多少のシアは耐えられる、みたいな表現)、いやいや、下に構造物がある場所でどうやって下からボルトを入れるんだよ、というツッコミ。

 ナットが下にあると重力で緩むから、みたいなことも書いてあるけど、なら重いボルトが下にあったほうが重力が効きそうな気がするが。上からボルトを挿入していれば完全にナットが脱落してもわずかなせん断力には耐えられるから、ナットの緩み(張力ゼロ)を許容するなら上から入れるべきじゃねって気がする。そもそも軸力ゼロを許容できるならボルト・ナットよりもっといい方法があるだろ、という話だけど。

 下からボルトを入れて、ボルト・ナット・部材に合いマークを書いておけば、ナットとボルトがズレていたときに一発で分る、というのに関しては、上から見た場合にしか適用されないから、例えばインフラ設備みたいに下から確認することがある場所ではむしろ上から入れるべき理由になりそう。

 こういう記事を書いてる人って、自分の記事が矛盾してるって気が付かないんだろうか? 気が付かないんだろうなぁ(身に覚え)。


 ボルトを下から入れなければならない理由って、ネットの記事で見る範囲だと腑に落ちる説明はあんまり無い気がする。実際に正しいことが書かれているのかもしれないけど、記事を見ただけではそれが判断できない(実際に試験してみないと判断できない)みたいな説明も含めて。

 ちゃんと根拠になりそうな理由でいうと、ワッシャ等を入れるときに、ボルトを上から入れるとワッシャ等を脱落させる恐れがあるけど、ボルトを下から入れておけば、ボルトが脱落しない限りはワッシャ等も脱落しない、くらいかな。

 建築物で高力ボルトを使う場合は重い工具を使いやすくするためにボルトを下から入れたほうがいいよ、ただし工具が干渉する場合は上から入れてね、とか、FAだと下からボルトを入れたら脱落したときにワークを破損させたり、食品ラインだと異物混入は対応コストが大きいからボルトの下からの挿入は絶対にNG(ナットも使用せず構造部材にボルトだけで締結)、とか、結局、TPOに合わせて選んでね、みたいな話になりそう。まあ、そりゃそうよな。あらゆるシチュエーションに完璧に答えられる銀の弾丸、なんてあるわけないし。



 某ロケットのアレ、1号機のときに第1/2段間分離で、衝撃が円錐で収束して第2段エンジンに過大な衝撃が、みたいな現象があったけど、このあいだのやつも円錐の構造破壊らしいけど、なんか現象が似てるような気がしないでもない。まあ、ちゃんと事前に解析してあるだろうから、正常であれば問題ないんだろうけども……



 Google Pixelのカメラ、設定で音量ボタンに割り当てる機能を設定できるんだな。デフォルトはシャッター。他にズーム(音量↓でワイド、音量↑でズーム)や音量(音量ボタンのデフォルト機能?)、OFF(音量操作も無効?)、が設定できる(もしかしたら音量は録音音量、OFFは出力音量?)。

 音量ボタンでズームを切り替えられるのは一見便利そうだけど、じゃあどうやってシャッターを切るんだ、という問題。せめてファンクションキーが1個あれば、音量ボタンと組み合わせて色々使えて便利だろうけどな。物理キーが増えると故障場所(壊れやすいメカ、水が入りやすい開口部)が増えるから作りたくないんだろうけど。でもAppleはiPhoneにアクションボタンを載せてるからな。やはりあると便利なんだろうし、多少のコストは気にせず実装できるAppleと、できるだけ価格競争力の欲しいAndroidの差もあるだろうし。



 RasPi PicoのMicroPhytonってもっと使いやすそうなものだと思ってたけど、意外と使い勝手悪そう。

 公式のインタプリタはUSB CDCとして認識されて、対話モードで動作する。なので、ターミナルで手書きする範囲においては、人間の認識能力やタイプ速度を超える動作はできない。あくまでもただのCDCなので、PC側でCDCにコマンドを送ったりするプログラムを書けば、オンボードフラッシュに入らないような巨大なスクリプトも処理できるけど、まあ、そんな事するやつはおらんやろ……

 BOOTSELを押しながら起動してMSCにmain.pyを入れればそれが走るらしいんだけど、なぜかウチのPicoは走らない。なんか、ウチのPico、調子悪くね??


 あと、MicroPythonはドキュメントが少ない気がする。C SDKは巨大なHTMLにメソッドの一覧と説明が書いてあるけど、Python版は見当たらない。

 結局BOOTSELでMSCとして認識させてスクリプトをコピーしなきゃいけないなら、BOOTSELでMSCとして認識させてuf2をコピーするのも手間としては変わらないし、スクリプトだとインタプリタで走らせてみないと結果がわからないけど、C/C++なら少なくともコンパイラが知る限りのエラーや警告は表示してくれる安心感がある。Pythonも多少の文法エラーくらいならIDEが警告は出してくれるだろうけど。


 電子工作をやったことがない人に対して、MicroPhytonインタプリタを焼いたRasPiPicoを配布して、USBで接続してターミナルから対話型でGPIOのインスタンスを確保してLEDをチカチカさせて、みたいなことは楽にできるだろうけど、その後ってどうするんだろうか。最初から専用のIEDを使うのかな。



 RP2040が2個乗ったボードってないんだろうか。STM32 Nucleoみたいに、1個はSWDブリッジ、もう1個がターゲット。コスト的にちょっと厳しそうだけど、買ってすぐUSBで接続してフル機能のデバッグができるのは便利そうな気がするが。



 イーサネットフレーム、ヘッダにデータ長が書かれていないのが結構謎い気がする。乗っているプロトコル(IPv4とか)を知っているなら内側のプロトコルを見てイーサフレームの全長を把握できるけど、そういう仕組ではないはずだし。

 ja.wikipediaの書き方を見ると、フレームチェックシーケンス(FCS)を見れば末端を把握できるから、可変長で長さが不明でもここで終了させればいいとわかる、みたいなことが書いてある。活線挿抜を考えると、自分がネットワークを最初に見たときに通信中だった場合に、ヘッダを見ていなくても末端を知る必要があるとか、あるいはパケット(イーサフレーム)が衝突してビット列の同期が取れなくなったときに末端を探す必要があるから、みたいなことなんだろうか。

 とはいえ、FCSってただの4バイトデータだし、ここに入っているのはCRC32だから、これを見てパケットの末尾を知ることは不可能なはず。例えばヘッダを見逃した場合やメッセージが衝突した場合、あるいはノイズでビットが化けた場合に、CRC32が一致することで末尾を判断することはできない。

 とすると、イーサネットフレームの末尾を判断するのは、イーサネットフレーム自体ではなく、その下のプロトコルで判断しなきゃいけない、ということになるはず。

 100BASE-TXならTRを受信したらそこで終了、みたいなわかりやすい基準があるけど、10BASE-Tにはそういう基準は無いはず。強いて言えばマンチェスタ符号として正しくないシンボルが出る、くらい。まあ、じゃあそれで判断すればいいだろ、と言われればそこまでなんだけど。


 wikipediaの記事だとFCSの後のEOFで、10BASEはキャリア消失で終了を検知する、みたいな事が書いてある。キャリア消失で終了を判定して、それまでに受信したビット列をFCSのCRCで確認して、OKなら上に投げて、NGなら握りつぶして、みたいな感じなのかな。

 正しくないマンチェスタ符号を検出して通信を終了、だと、通信途中でLANケーブルが抜かれたときに困るから、やはりキャリア消失で検出するのが安心なのかな? 少なくともPHY層では。MIIで上げる信号はマンチェスタ符号で切るとしても。

 とすると、FCSの「ペイロード長がわからなくてもFCSでフレームの末尾がわかる」という説明がニュアンス的に正しくない、ということなんだろうか。



 イーサネットってSPIみたいに送受信でコヒーレントである必要はないわけだから、TXとRXで変調方式を分けるみたいな使い方って無いんだろうか。

 例えばイーサネット接続のセキュリティカメラで、普段は動きが少ないけど場合によっては10Mbpsを大きく超えるから100BASE-TXで送るが、コマンドはほとんど無いから125Mbaudを常に出すのは電気の無駄なので10BASE-Tで接続する、みたいな用途。

 オートネゴシエーションで特定の通信方式だけ有効な情報を出して、自分がそれとは違う方式で出す場合、自分は10BASE-Tで送って相手はそれ以外の方式(100BASE-TX)で送らせる、みたいなことはできるかもしれないけど、自分が100BASE-TXを出した場合、相手も100BASE-TXで送ってくるはず。自分は100で出すが相手は10で出してもらう、みたいなことはできないはず。


 適当なEtherTypeを定義して、最初に10BASE-Tで接続して、そのパケットで32bit32個(128byte)とかのフラグテーブルを投げて、そのマトリクスから双方が対応できる最も高速な転送速度を決定して、リンクアップしたあとも定期的に投げ合って、高レートで送りたい時は100BASE-TXや1000BASE-Tに切り替えて、必要なくなったらまたビットレートを下げて、みたいなことはできそうだけどな。

 イーサネットフレームをPHYで読むのはWoLみたいに可能なわけだし、それと同じような感じで。MACで転送されると困る(ハブを超えて別の機器に影響が出る)から、それを防ぐためにFCS(CRC32)に固定値をxorしてMAC層から見ると常に壊れたパケットを飛ばす、みたいな対応は必要だけど。

 今のところ、電線を使うイーサネットの規格は20ちょっとあるらしいから、32bitテーブルでカバーできるはず。これ以上の高速化は電線ではやらないだろうから、車載とかFAとか特定用途を除けば増えないはずだし、そういう部分では特定のプロトコルしか使わないだろうからオートネゴシエーション的な機能では無視できるはずだし。FCSで壊すなら専用のEtherTypeを割り当てる必要はないけど、専用のEtherTypeが割り当てられていればデコーダが簡単になる利点がある。

 受信側は自動判別するとして、相手に送信してもらう方式だけ指定するなら、32bitとか64bitのビットフィールドを投げるだけでもいいけど、どうせパケットを切り詰めたってイーサフレームの最小長があるからパケットはあまり短くならないのよな。ロジックが楽になる利点はあるけど(PHYでキャッシュするメモリも少なくて済むし)。

 これくらいの仕様は過去に提案されていても良さそうな気がするけど、そういう規格が存在しないということは、需要がなかったんだろうな。まあ、昔はIoTみたいに非対称かつ省電力化が重要な用途もあまりなかっただろうしな。かといって今の時代に100BASE-TXの数百mW程度を削減したいみたいな理由で規格を新しく作って普及させられるとも思えないし。


 そもそも建前は置いておいて何をやるためにそういう機能が欲しいのかというと、変調するのは楽だけど復調するのは大変、100BASE-TXは足の早いマイコンならソフト実装で出せそうだけど、受信するのは10BASE-Tのほうが楽だよね、ちょっと多めの測定データを流すときに100BASE-TXで出したり、各種設定を10BASE-Tで受信できたら便利だよね、みたいな方向性。

 外付けMAC/Phyでなく、パルストランスだけ外付けで使えたら面白そうじゃね、と。まあ、実際にやろうとすると変調でリソースの大半を食われたりして実用にはならないだろうけど。そもそも125MBdの信号をプログラムが走るデバイスから真面目に出そうとしたら少なくとも250MHzで動くロジックが必要だしな。スクランブルも考えればさらにその数倍のクロックが必要になるし。

 プログラムが走らないプログラマブルなデバイスを想定すると、例えばShrike-liteに乗っているForgeFPGAはGPIO2本をパラでドライブすると、min120MHzが出せるそうだ。ここまで早いGPIOが使えるなら、100BASE-TXの波形は出せてもいい気がする。FPGAならLFSRだって組めるだろうし…… でもまあ、わざわざ4B5B/MLT-3変調のためだけにForgeFPGAを乗せるかというと。。。いや、そのためのグルーロジックだろ、という話ではあるんだけど。でも25Mbps程度でいいならW5500でいいし、少し上のチップ(例えばW6300、QSPIモード)なら90Mbps程度のスループットが出るそうだから、わざわざ汎用ロジックを載せて100BASE-TXに対応するくらいなら、専用のブリッジを積んだほうが楽だろうな。さすがにForgeFPGAで100BASE-TXの受信は難しいだろうし(3レベルアナログ信号のためにアナログ段を置かなきゃいけないとか、いろいろ)。



 ブレッドボードにジャンパワイヤで接続したW5500とFT232Hがいい加減じゃまになってきたので、ユニ基板に乗せてみた。


 ユニ基板使うの何年ぶりだ…… 計画性と躊躇のなさが明らか。プロに見られたらバチボコに殴られるけど、趣味の遊びだから許してッ!!

 とりあえず、DHCPでアドレスを取ることはできたので、たぶん動いているはず。

 オシロとかロジアナでプロービングしようとすると困るけど、必要になったときに考える。


 ストリナのFT232H基板はVer.2だと3.3V出力があるけど、手持ちはVer.1のVBUS出力オンリーなヤツなので、3.3VのLDOを載せている。あとは、FT232とW5500の出力が衝突すると嫌なので、100Ωを挟んでいる。せっかくなので、INTにLEDを配置している。とはいえ、W5500のINTを出しっぱなしにすることも無いけどな。あとはCSにもLEDをつけていれば、通信時に見えるので見た目が面白くはあるけど、面倒なので省略。


 FT232Hの固定穴がインチじゃなくてミリなのが絶妙な使いづらさ。最初はユニ基板にミリで穴を開けるジグを作ろうかと思ったけど、でもどうせ11mmのスペーサーが必要なので、基板側のネジ穴と合わせるブラケットを作ってみた。



 大昔に買ったCat.5eケーブル

 マーキングにELECOM Laneedと書いてあるのでエレコム製なんだろう。

 ツイストの様子がよく見える透明被覆のケーブルちょっと欲しいけど、探してもいまいち見当たらない。



 GitHub - steve-m/Pico-100BASE-TX: Bit-banged 100 MBit/s Fast Ethernet transmitter and UDP framer for Raspberry Pi RP2040/RP2350

 RasPiPico2で100BASE-TX送信。ADCでアナログ波形(AF)をサンプリングして、それをWFM変調して、そのIFデータをUDPでPCに転送する、というような処理をやっているらしい。スクランブルを正しく実装しようとすると計算コストが高すぎるはずだから、おそらくアイドル信号は出していないはず(コード未確認)。


 GitHub - kingyoPiyo/Pico-10BASE-T: 10BASE-T from Raspberry Pi Pico

 RasPiPicoで10BASE-T送信。受信は将来的に対応予定とのことだが。



 久しぶりにSTM32を使おうと思って、手始めにSTM32CubeMXをダウンロードしようと思ってゲストでダウンロードを試したのだが、一向にダウンロードができない。

 1つ目は、Gmailのエイリアスがだめだったっぽい。延々「メールアドレスはまだ認証されていません」みたいなエラーが出続ける。エイリアスなしのメールアドレスを入れてみるとそのエラーはでなくなった。が、今度は401エラーが出続けるようになった。なんでだよ。

 観念してSTのアカウントを作成。入力項目多すぎじゃねー?

 RP2040+VSCode(+拡張機能)みたいに比較的容易に開発環境を構築できる現在、STM32はあまり魅力的ではないかも。と思いつつ、機能面で言えばやはりSTM32のほうが強い気がする。必要に応じて様々なチップから選択できるという利点もあるし(RPは現状C-M0+とC-M33の2種類しかない)。

 気軽に電子工作を始めたいならRP、将来性を考えるならSTM32、とか? ただ、STM32は茨の道だぞぉ。あと、Arduinoプラットフォームで対応しているせいで玉石混交な情報がな。Arduino界隈は多くの初心者が自分のアウトプット用に色々な記事を書いているので、記事の質を判断できないうちにそういう記事を読むとちょっと大変なことになる。



 小さめのヤツを使いたかったので、STBee mini

 今回はUSB DFUファームを消して、SWDで書き込み(ST-Link v2は昔のNucleoのカケラ)。


 SPIペリフェラルでW5500を接続して、動作テスト。とりあえずDHCPでIPアドレスを取得。たぶん動いてる。

 今回はSPI2を使ったので、クロックは18MHz。コアクロックが72MHzだから、32クロックごとに2バイトをハンドリングする必要がある。キッチリ実装すれば足りそうな気もするけど、C++だとクロックに隙間が空いていて、処理が間に合わない。DMAなら隙間なく転送できる。DMAはDMAでいろいろ設定が必要だから2,3バイト程度の転送だと割に合わないけど。

 コードはC++で書いているので、色々と面倒。やはりC#は便利。特に、PCで走るC#コードを書いてUdpClientとかでロジックをテストして、それで動いたコードをほとんどコピペしてFT232H/MPSSEでW5500を叩いて、みたいなことをやっていると。



 Feature request: Programmable logic - STMicroelectronics Community

 STM32にグルーロジック用の小さいロジックセルがあったら便利だよねー、みたいな、白熱()した議論。


 RP2040に乗っているPIOって、実際に触ったことは無いしドキュメントもちゃんと読んでないけど、かなり「自由度の低いソフトウェア的な」機能な気がする(そもそも10命令に満たないアセンブリで書く時点で自由度が低いソフトウェア的なのは当たり前とはいえ)。FIFOで受け取ったビットストリームをSPIやUART、I2Cみたいなプロトコルで吐き出すことはできるけど、じゃあそれにm系列のPRBSをXORできますか?というと、おそらく不可能。現実的にPRBSが必要な状況なんて無いだろ、といえばそれまでだけど、あくまでもRPのPIOの柔軟性が低いということを言いたいのであって。

 極端な話、STM32と小規模なFPGAを貼り合わせて、STM32のIOをFPGAに取り込んだうえで自由にルーティングしたり簡単なビット演算を行って、FPGAのIOとして外に出す、みたいな感じの機能があって、FPGAを未初期化で使えばただのSTM32として、STM32から適当なビットストリームを吐いてFPGAをコンフィグすれば(マイコンに比べれば)複雑なロジックを処理できて、みたいな機能が欲しいわけだが。それこそShrikeみたいな感じになるんだろうけども。

 昔はWiznet W5200とSTM32F103CBを貼り合わせてパッケージングした製品とかも売ってたみたいだし、同じように小さいFPGA(e.g. ForgeFPGA)を貼り合わせてパッケージングした製品とかあっても良さそうな気がするけど、でもそんなもん作ってもコストが合わないから、どうしても必要なら各自PCBに載せろ、って話なんだろうなぁ。

 フォーラムの中でも書いてあるけど、そういう製品を作ったところでちょうどいい塩梅の製品にはならない(機能が過小or過大になる)だろうし。



 Wiresharkでデータ長0のDiscardパケットを受け取ると長さ0のUDPパケットとして表示されるの、期待した動作とは違うけど、これってどういう挙動なんだろうか。Discardってべつに1バイト以上無いとだめ、みたいな理由はないはずだし、0バイトのパケットでもDiscardとして表示されていいはずなんだけど。


https://www.ietf.org/rfc/rfc863.txt

 DISCARDプロトコルのRFC。めっちゃ短い。

「捨てるよ」としか書かれていないから、0バイトのパケットがDISCARDとして認識されないのはWireshark側のバグ的なものだと思うのだが。


2026年1月21日水曜日

小ネタ


 何日か前に届いた、ほぼ確実に迷惑メールであろう、プロバイダからの案内のメール、送信者がプロバイダの一般的なメール(実際のログイン通知とか)と同じなのは当然として、Gmailで見ると送信元や署名元も実際のメールと同じで、かつGmailが重要と判断したマークを付けている。ただし、通常のメールは送信先メールアドレスが自分のメールアドレスだが、このメールは正しくないアドレスになっている。それと、ログインして設定しろとURLが貼ってあるが、このURLはプロバイダのドメインではない(プロバイダから送られてくるメールはもちろんプロバイダのドメインのURLが貼られている)。

 送信元と署名元が実際のプロバイダと同じに見えるものが付属しているのも変だけど、それでころっと騙されるGoogleもGoogleよな。


 別の迷惑メール、普段迷惑メールなんて送信者名だけ見て関係のない会社(普段から迷惑メールで使われている社名)なら件名すら見ずに読み捨てるんだけど、たまたま目に止まった内容が面白かった。本文のフッターには社名や会社のWebサイトへのリンクが書いてあるんだけど、Example Companyという会社でURLはexample.comだそう。ちょっと面白い。

 迷惑メール用のサンプルデータをほとんど書き換えずにそのまま流用したのかな? メール本文の中に別のドメインのURLが書いてあるから、これが本体なんだろうけど。しかし、example companyとか書いてあるのも気にせず送るようなヤツが迷惑メール出してるのかぁ。そりゃまあ、一流企業の英語バリバリシゴデキ人間が業務or副業で出してるだけとも思わないけどさ。



「DXセミナーの案内がFAXで送られてきてガッカリ」みたいな話、むしろそれって正しいやり方なんじゃね?って気がするけどな。デジタルツールを使い込んでいる所にDXソリューションを売り込んだって意味ないだろうし、電話やFAXを現役で大規模に使っている組織こそDXするべきだろうし。適当なデータセットに乗ってるFAXの電話番号に一括して送信しているだけだろうし、大量の電話番号からその組織が十分にデジタルツールを使いこなしていて売り込む必要が無いと除外するのも面倒だろうし。



 主に人生の諸先輩方へ向けて作られているスマートフォン、UIが独特で使い方を聞かれても答えられないとか色々不満点はあるんだけど、タップ操作が感圧式になっているのはすごい羨ましい。

 PCのマウス操作みたいにクリック操作が明示的なHIDに慣れていると、普通のタッチ操作(含一般的なノートPCのトラックパッド)で「いや俺触ってねえんだけど!?」は結構フラストレーションになる。Mac系のトラックパッドはクリックが感圧なので、その誤入力が無い。スマホにもそういう機能が欲しい。

 一時期のiPhoneも感圧式のタッチパネルだったはずだけど、すぐに廃止された気がする。やはりタクタイルスイッチで計測できるトラックパッドと違って、スマホのタッチパネルで機械的なアナログ値を安定して取るのは難しいんだろうな。逆に言えば、意地でもその機能を削らない日本の端末メーカーの気力というか(今はレノボ傘下だから親企業は中国だけど)。キャリアやユーザーからの圧力もあるんだろうけど。



 文章を読みながら手持ち無沙汰でキートップを撫でながら思ったけど、FキーやJキーあたりに画像素子を埋め込んで、指紋認証やポインタ操作デバイスとして使うことってできないんだろうか。

 面積が小さいからポインタとしての操作範囲(ダイナミックレンジ)は狭いけど、ちょっとした文章の入力中に、数文字分離れた場所にカーソルを移動したい、というときに、右手を大きく動かして矢印キーを使うよりも、JキーやFキーを撫でてマウスカーソルを少し動かすくらいの操作ができたら便利そうだが。

 とはいえ、マウスカーソルの移動はできても、クリック操作をどこに割り当てるんだ問題が出てくるのだが。スペースバーの手前にボタンを追加する、あたりかなぁ。

 単にカーソルを動かしたい場合はViみたいな操作系は便利そう。今度はEscが遠いけど。



 ターボファンエンジンの発電能力増強のために高圧軸だけでなく低圧軸にも発電機を取り付ける、というやつ、実際のところどれくらい効果があるんだろう? 低圧軸は高圧軸で余ったエネルギーでブン回してるだけだから、高圧軸で発電しても、高/低圧軸の両方で発電しても、トータルで取り出せるエネルギーに差はない気がするんだけど。

 高圧軸の発電機が大きくなるとイナーシャも大きくなるから起動が大変……みたいな話は、そもそもその発電機に電力を突っ込んで回すんだから大して問題ないだろ、という気がするし。

 構造的に、高圧軸に大容量の発電機を取り付けるのが難しいから、比較的小型の発電機を2箇所に設置する、みたいな理由はありそうだけど。あとは、熱い場所に高効率な発電機を置くのは大変だから、メインは低圧軸で、でも起動用の電動機が必要だからついでに高圧部でも発電して、みたいなこともあるんだろうか。



 昆虫に過給器をつけたらどうなるんだろ、という空想。昆虫を巨大化させた設定がある創作物で、でも昆虫って巨大化すると呼吸できなくなりますよねー?みたいなツッコミに対して、サイバーパンク的な方向からのソリューション。エネルギーは外付けのLIBで、BLDCでブン回す方向で考えている。電池が切れたら(orリモートで停止させたりすれば)活動を止められるという利点もあるディストピア風味の味付け。



 気まぐれに読んでた中性子イメージングの資料で「核分裂で生じる高速中性子は使いづらいから水で冷やして使う」みたいなことが書いてあった。確かに水で減速する核分裂炉って、我々が日常的に「熱いものを水につけて冷やす」と全く同じ物理現象で高速中性子を冷やしてるんだよな。火で温めた石を水につけてお湯を作るのと同じ(マクロスケールでは核子が運動量を直接交換しているわけではないけど)。石がめちゃくちゃミクロになるし、トータルのエネルギーは非常に大きいので、日常のスケールとは全く違ってイメージが湧かないけど。でも水は沸くんだよね(ただし沸騰水炉に限る)。

 中性子イメージングの場合は水だけでなく液体水素を通して冷やしたりもするらしい。あまり冷やしすぎると波長が伸びて分解能が下がるんだろうけど、液体水素ならそこまで極端に冷えるわけでもなく、かといって早すぎもせず、値段も安いし、わりといい冷却剤なんだろうな。核分裂で生じた高速中性子や常温程度に近い熱中性子に対して、液体水素で冷やしたものは冷中性子というんだそうだ。熱中性子を通す場合、液体水素は厚さ3cm程度でいいらしい。極めて少量でも十分に冷却できるから、トリチウム化する量も少ないんだとか。たしかにあまり長く液体水素を通しているとそっちに吸収されてしまうのか。



http://www.spring8.or.jp/pdf/ja/SP8_news/no99_20/no99.pdf

 2020年。Spring-8でトリウム229の励起に必要なエネルギーを計測したい、みたいな話。

 トリウムの原子核は他の原子に比べて低いエネルギーで励起でき、原子核は電子雲よりも遥かに小さいし、電子雲がシールドの役目をしているので外部からの影響を受けづらいため、原子核を時計に使えば現在の原子時計よりもさらに精度の高いものが作れるはずだ、ということで、励起エネルギーの低いトリウム229で実験を行っているらしい。


https://www.jst.go.jp/kisoken/presto/evaluation/s-houkoku/sh-r03/JST_1112078_18070111_2021_Yamaguchi_PER.pdf

 トリウム229のトラップとかの話。

 冷却用のレーザとかで、結構大規模な装置が必要そうな感じだ。もっとも、応用の話で「「原子核時計」というテーブルトップサイズの装置による宇宙進化の解明という、新しい研究分野を創成する可能性も秘めている」と書いてあるから、実用化の暁には十分に小型化できると考えているんだろうけど。



***


 改めてRaspberry Pi Picoを触っている(比喩表現)。

 なぜか、Ras Pi PicoのRUN端子に触れる(物理)とリセットされる不思議な現象が起きている。内蔵プルアップ抵抗って100kΩ未満だろうし、そんなに簡単に動くものでもないと思うんだけど。それに、4.7kΩを追加で付けても、やはり指で触れると反応する。


 前に、BOOTSELを押してWDTを蹴ってUSB MSCで認識させるというやつ、あれ実は正常に動作していなかったらしい、という気がしてきた。

 定期的にキャッシュをオールクリアしたり、あるいはQSPI FlashからUIDを読むようなコードを書いてBOOTSELを押しても、正しく動作を続ける。そもそもQSPI Flashはデバイスが1個しか接続されていない場合はCSをGNDに落としてピンを1本省略するみたいな使い方ができるらしい? 軽くググっただけだとそういう使い方は見当たらなかったけど、SPIだとそういう動作ができるデバイスもあるし、QSPIでできても良さそう。ということで、そもそもRP2040のBOOTSEL(QSPI Flash nCS)を動作中にGNDに落としても、SSIの読み出しには影響はないようだ。

 BOOTSELでリセットしたい場合、自分でBOOTSELを読んでリセットするしかないらしい。その場合、BOOTSELをGPIOに変更する必要があるから、そのコードをRAMに置いたうえで、割り込みも停止して、とか、いろいろ手間がかかる。RP2040をリセットするのも、例えばCortex-M0+コアをリセットしても他のコアやペリフェラルは動作を続けるから、WDTを開始して待つ、みたいな方がいいらしい。QSPIがCSを使わないならGPIOに固定しても、キャッシュミスを含めて正常に動作するだろうけど、GPIOを読むときにBOOTSELの押下有無にかかわらずLOWでしか読めないし。


 RP2040のXIPはプログラム側からXIPに書き込みを行うとキャッシュライン(2040なら8byte単位)を無効化して次の読み出し時に強制的にFlashから取らせる機能があるらしいんだけど、軽く試した感じではうまく機能させられなかった(キャッシュラインを削除してBOOTSELをオシロで覗いても、VDDに張り付いていてQSPIで読みに行っている気配がない)。SDKラッパーのxip_cache_invalidate_rangeを使っても同様。


 結局、RasPiPicoを手軽に使いたいなら、2枚買ってJTAGアダプタとして使うのが一番確実っぽいなー。


 Ras Pi Picoはドキュメント(SDKが用意している関数やその機能)がHTML1ページで説明してあったりして情報を探すのが便利ではあるけど、いまいち釈然としない部分も多い。

 あと、当たり前だけど、STM32とはペリフェラル周りが全く違うので、自分がやりたいことをどうやったらできるのかを調べる必要もあるし。ある程度気合を入れて一気にいろいろ試していけば感覚も掴めるんだろうけど、そこまでのモチベも無いのでな…… STM32ならこの機能とこの機能を使えば楽に作れるんだけどなー、とか、いろいろ。


***


 PCでデータが通るところ、ぐぐると必ずオーディオ系のブログが出てくる。オーディオの人たち、どこにでもいるな。懇切丁寧に解説しているけど、でもその説明って……

 もちろん、データが通らない場所(e.g.純粋なパワーライン)も彼らの領分。


*


https://www.net.itc.nagoya-u.ac.jp/member/shimada/infoNW2025B/slide/lecture20250617slide_rev1.pdf

 イーサネットの特に物理に近い周りの話いろいろ。



https://www.fujitsu.com/downloads/JP/archive/imgjp/jmag/vol55-6/paper07.pdf

 2004年。1チップで10GbE12ポート240Gbpsのスイッチングハブ。25mの銅線をドライブできるIOを内蔵。


*


 DHCP、Wikipediaを見ながらざっくり実装してみた程度なのであまり詳しくは調べていないけど、最低限の機能だけならそれほど難しいものではない。300バイトくらいのUDPパケット(互換性目的で200バイトくらいゼロ埋め)を2往復+αで処理できる。NTPの数倍の手間、といった程度。10倍まではいかないかな。

 DHCPはMACアドレスと紐づけて処理される。ユニキャストで送ると送信したイーサネットフレームのMACアドレスに返答が帰るので、パケットでMACアドレスを偽装して実際には別のMACアドレスから送る場合は、ブロードキャストで送る必要がある。逆に言えば、実際にはネットワークに接続されていないデバイス(ネットワーク内に存在しないMACアドレス)に対してDHCPでIPアドレスを割り当てることもできる。

 攻撃らしい攻撃も思いつかないけど、攻撃者となる一つのデバイス(単一のMACアドレス)からDHCPサーバーにリクエストを投げれば、DHCPリソースを枯渇させるのは簡単にできそう。すでに接続されている端末に割り当てられたIPアドレスを横取りすることはできないけど、追加で接続される端末へIPアドレスが割り当てられるのを防ぐことはできそう。それで具体的になにか強烈に悪用できるかというと微妙だけど、迷惑ではある。

 DHCPサーバー側では、イーサフレームの送信者MACアドレスとDHCP DiscoverのMACアドレスが一致しないパケットは捨てる、みたいな方法で避けれるけど、少なくともうちのルーター内蔵のDHCPサーバーはそういう機能はないらしい。イーサフレームのMACアドレスまで偽装すればサーバから見れば偽造かどうか判断できないけど、そこまでされたらもうどうしようもないし。

 C#とかでMACアドレスを偽装してDHCPクライアントを作って遊ぶ程度なら、Discoverを送って、Offerを受け取って、Requestを投げて、Ackを受け取って、という手順でIPアドレスが得られる。W5500とかでDHCPクライアントを作る場合は、OfferとRequestの間に、割り当てられたIPアドレスに対してUDP SENDを挟むほうが良い。ARPが投げられるから、IPアドレスが存在していた場合はSEND_OKになるし、存在していない場合はTIMEOUTになる(不必要なパケットを投げるのでポート9とかあまり害がなさそうな場所に投げる)。

 DHCPでIPアドレスが割り当てられれば、パケットの中で指定するオプションでルータのIPアドレスやDNSサーバのIPアドレスも取れるから、DNSで名前解決したり、ルータを超えて外にパケットを投げたりもできる。ルータ超えもとりあえず問題はなさそう。少なくとも、適当なNTPサーバーにパケットを投げれば正しく返答が得られる。



 ということで、W5500からNTPサーバー(Cloudflare)にリクエスト


 ロジアナは送信割り込みと受信割り込みの時間を計測、オシロは10BASE-Tの適当な箇所(とりあえずプリアンブルの最初の立ち下がり)を計測。送信割り込みは送信開始前、受信割り込みは受信完了後だから、ロジアナの方は少し時間が長く計測される。


 NTPサーバーにCloudflareを選んだのは、違法コンテンツで荒稼ぎしているCDNなら頻繁に打っても迷惑かからんやろ、という理由。あとは、たぶんGoogleは日本国外のアジアサーバー、Cloudflareは日本国内のJPサーバーのはずだから、応答が早いというのもある(応答が遅いとオシロで見るのが面倒くさい)。応答速度で言えばNICTの小金井サーバーを指定すればCloudflareと同じ程度には早いはずだけど、カツカツの予算で運営しているであろう国立機関のサーバーをアホな遊びで負荷かけるのも忍びない(神戸サーバーは物理的に遠いのでレイテンシが若干増える)。awsはGoogleに比べれば応答は早いし、NICT神戸より若干早いので、おそらく国内サーバーだと思う。


 他のサーバーも含めて割り込み間隔を計測。何回か試すと、最初に比べて数ms程度短くなる。たぶん途中の経路が少しずつ最適化されて、その経路がキャッシュされるんだと思う。NTPで時刻精度が欲しいなら結構高頻度に(少なくとも途中で最適化された経路のキャッシュが消えない程度の頻度で)打たないとだめかも。でもそれをやるとルータのテーブルを占有することになるので、あまり良くなさそう(NTPサーバーへの負荷も大きいし)。数時間毎にバースト状に1秒間隔で5発くらい打ってRTTが一番短いものを採用する、あたりが落としどころかな。

 SEND_OKとRECVの間隔は、Cloudflareは28ms程度、AWSは30ms程度、Googleは55ms程度、かな。一旦経路が収束すれば、何回か送ってみてもほぼ安定した間隔が得られる。

 ちなみに、PC(C#)からソフト処理でCloudflareにNTPを打ってみると、RTTは172ms程度と計測される。実際は30ms程度で帰るはずだから、PC内部で150ms近い遅延が発生していることになる(ちょっと大きすぎるので、もう少し工夫すれば圧縮できそうな気もする)。


 そういえば、北海道にNTPサーバーってないのか?と思って、試しにさくらインターネットの公開NTPサーバーを叩いてみた。結果、23msで応答が帰った。Cloudflareを抜いてトップ。とはいえ、おそらく関東圏であろうCloudflareと比べて圧倒的に早いというわけでもない。もしかしたらONUあたりがボトルネックになっていて全体的に一定の遅延がかかっているだけかもしれないけど。

 北大にもNTPサーバーはあるらしくて、DNSで問い合わせれば正しそうなIPアドレスが得られるけど、試しにNTPパケットを投げても応答がないので、おそらく校外からは使えないんだと思う。



 NordVPNのIPアドレス検索に突っ込んでみると、AWSは大阪として表示されるけど、Cloudflareは結果なし、Googleはジョージア州、さくらは結果なし、になる。

 ジョージア州までは大圏航路で1.1万km、往復2.2万kmとして伝搬時間は最速でも73ms程度必要だから、普通に考えれば55msで帰るのは不可能。ニュートリノ通信とかで地球を貫通したとしても往復1.9万kmちょっとあるから、63ms程度かかる。ニュートリノ通信、あんまり早くないんだな。HFTで10ms早ければ大儲けできるだろうけど。/* 実際にニュートリノ通信が実用化されたとすれば、途中でルータを挟まずに直結できる分で差はもっと大きいだろうけど(※変復調のレイテンシは無視するものとする) */


***


 オシロでサンプリングした100BASE-TXを復元する遊び

 ↑オシロで取った波形(1Gsa/s)を1symbol(8samples)で折り返してグラフ化

 ↓1symbol分の平均値

 サンプリングした波形は主にオーバーシュートに起因するノイズが多いので、平均化するだけでアイがかなり広がる。


 平均値の微分値の絶対値の平均値

 1-8はラグのサンプル数、max/minはラグごとの最大値と最小値の比。ラグを大きくすれば微分値も大きくなるけど、最大/最小の比が下がってしまう。比はラグ1が一番大きいけど、とはいえ3割程度しか変わらないが。


 平均化したサンプルと、それの微分値の絶対値の平均値(ラグ1)

 ビットの位相と微分値の位相には関連性が認められる。

 微分値の適当な位置(最下点or最上点)を基準にして、そこからNポイント後をサンプリングに使う、みたいな感じにすれば、アイが開いているところのサンプルを取ることができる。


 ただ、今回のデータの場合は、微分の位相とビットの位相は微妙な位置関係になっている。サンプリングレートが数倍高ければ(数Gsa/sでサンプリングできれば)もっと綺麗な関係になるはず。もっと上のクラスのオシロが必要になるし、計算量もかなり増えるけど。

 あと、サンプルデータをざっと見た感じ、クロックエラーは十分に低そうな感じ。少なくとも、10kpts程度であれば十分にコヒーレント。短いパケットがどこにいるかがわかっていれば、クロックリカバリ無しで固定位相でサンプリングしても問題なさそう(今回の場合はW5500からUDPを投げて、SEND_OKでトリガしたので、その位置付近にパケットがあることはわかっている)。


 ということで、ビット位相は固定で、MLT-3の復調

 青と橙がMLT-3(NRZI)から復調したビット(青がビット0、橙がビット1)。PRBS(11bit)との相関値も緑で示している。

 100BASE-Xはアイドル時に正弦波状の信号が出しっぱなしになるので、31.25MHzの線スペクトルをばらまかないようにPRBSで拡散を行っている。接続初期はPRBS位相が不明なのでビット列は0と1がランダムに出ている。

 この乱数ビット列に対してPRBSを相関させる。一定の長さ(2047bit)のビット列が溜まると相関値が+1に安定して、2047bit周期で-2047のピークが出る(PRBSのアイドル信号は負論理なので相関値も負になる)。

 ピークを見つけたらそこをPRBSの基準として、ビット和を取る。以降はアイドル信号のビット1が出続ける。

 7000付近で短いUDPパケットを1個投げていて、相関値が暴れることで非アイドルであることがわかる(ビット0も出てくる)。

 ここのビットパターンを見ると頭にJKや末尾にTRがあるので、少なくとも100BASE-Xとしてそれなりに正しく復調できているはず。


 100BASE-TXでは10BASE-Tと違って常にデータが流れっぱなしになるのは、クロック同期だけでなく、PRBSの同期を維持する目的もありそう。そもそもPRBSを使わなければデータがない時は4B5Bビット列自体止めておけば線スペクトルは出ないのでは?という気もするが。それはそれでやはりクロックや4B5Bの同期が面倒なんだろうけども。



 拡散を解除した4B5Bから、過去10bit分のビットストリームを持っておいて、JKを見つけたら以降TRが出てくるまでをダンプすると、555555555555D550EBF6XXXXXX0008DC010203080045000020000A400080117633C0A80189C0A801B600440009000C76F3010203040000000000000000000000000000XXXXXXXXというようなバイト列が得られる。最初の55..D5はイーサネットフレームのプリアンブル(頭にJKが入るので、10BASEに比べて1バイト少ない)、50EBF6XXXXXXが送信先MACアドレス(PC宛で出したのでASUSのコードから始まる)、その次が送信元MACアドレス(WizNetの適当な番号を設定)、以降IPv4ヘッダやUDPヘッダ、ペイロード、パディング、CRC、と続く。CRCを計算すると正しく0x2144DF1Cが得られる。

 ということで、100BASE-TXも無事に復調を確認できた。


 わりと簡単に復調できた10BASE-Tに比べて、100BASE-TXは復調がかなり面倒くさい。当然だけど、ビットレートが上がると復調の難易度も上がる。もっとサンプリングレートの高いADCとか、それこそLSIみたいにリアルタイムでアナログ的な処理ができるのであれば、もっと特性よく受けられるんだろうけど。



 100BASE-TXは3値(+1V、0V、-1V)を使用して、NRZIでデータを送る。0を出すときは位相を維持、1を出すときは90度進める。アイドル時は1を出し続けるが、NRZI/MLT-3で125Mbaud/4=31.25MHzの3レベル正弦波が出続けるから、複数の100BASE-Tを引き回したりすると31.25MHzの強烈な線スペクトルが出る。これを抑圧するために11bitのm系列で拡散する。

 m系列の位相を決めるためには2047bitのアイドルが必要だから、少なくとも35マイクロ秒程度のアイドルが時々入る必要がある(まあ、イーサネットで帯域使用率を完全に100%フルで使うこともあるまいが)。

 なんか、ベースバンドと言いつつ、結局無線通信と似たようなことをやってるなぁ。10BASEはマンチェスタ符号だからどちらかといえば有線通信寄りだけど(ADS-Bとか、無線通信でもマンチェスタ符号の使用例はあるわけだが)、100BASE-Xはスペクトラム拡散とかしてて、普通に無線通信のベースバンド信号って感じだ。……だからベースバンド信号なのか。納得。

 10BASE-Tも100BASE-TXもツイストペア1本で送るから、適当なキャリアでFSK変調とかすればそのまま無線で飛ばせそう。もっとも、帯域幅がかなり広いから周波数使用効率は悪いし、変復調も面倒だろうけど。それに、有線用の規格だから誤り訂正とかは全く無いので、無線で飛ばそうとすると品質が厳しいだろうけど。だからわざわざWiFiを作ってるわけだし。



 100BASE-TXって平衡接続のプラスとマイナスを間違えるとどうなるんだろう? Google AI曰くリンクアップしないor極めて不安定になるとのことだけど、でもMLT-3って電圧レベルの変化が1、維持が0なわけだから、それがプラスに変わろうがマイナスに変わろうが関係なくね?

 10BASE-Tはマンチェスタ符号が逆転するので、ビット論理が逆になるから基本的に逆接続は駄目だろうけど。

 こういうのは実際に間違ったピンアサインのケーブルを作って試してみるのが確実なんだろうけどなー。気が向いたらEthernetのケーブルを作る工具類を買おう……とは思いつつ、頻繁に使うわけじゃないから圧着工具は安物でいいだろうけど、いかんせんCat.5eケーブルがな。。。100mとか買っても使わないわけで、1割使うかもわからないのに気軽に買える値段でもないし、かといってPCとかある程度信頼したい機器の接続に自作ケーブルを使う可能性があることを考えると極端に安いヤツを買うのも嫌なわけで。適当な長さのCat.5eAssyを買って切って使うのが現実的かな。切って使うことを考えてないであろうケーブルって切って使えるのかわからないけど。



 100BASE-TXって途切れずに(連続位相で)アイドル信号を出しっぱなしにするから、1対1が前提のはずなんだけど、最近のリピーターハブって100BASEや1000BASEに対応しているらしい。どういう原理なんだろう?

 他のデバイスから送られてきたパケットを一旦クロック復元して適当にバッファしてから再送する、みたいなことをやってるんだろうか? バカハブって実はスイッチングハブと同程度には複雑なことをやってる?? だとするとスイッチングハブと同じくらい複雑で、圧倒的に数が出ない分で、値段が高いってのは理解できる気もする(実際はどうかわからないけど)。

 というか、一旦復調して再クロッキングして配布するくらいなら、スイッチングハブのMACアドレスルーティングを省略して、入ってきたパケットを全部ブロードキャストとして解釈して出せばいいんじゃね、って気もするな。とするとスイッチングハブの小改造でリピーターハブとして使えそうな気もするが。

 でも最近のスイッチングハブなんてCPUやFPGAでなく、LSI/ASICで組んでるだろうし、それを改造しようとするとやっぱり製造コストが高くなるんだろうな。スイッチングハブのデバッグ用機能でMACアドレスルーティングをせずにブロードキャストする、みたいな実装がされているヤツがあれば、安くリピーターハブとして使えるんだろうけど、そういうふうに使えると知られている製品が有名でないってことは、無いんだろうな。

 スイッチングハブってMACアドレステーブルが空のときはブロードキャストするわけだから、強制的にテーブルをクリアするような(メモリで辞書引きしても結果を返さないような)機能があればいいんだろうけど。

 同じMACアドレスが複数のポートに接続されていたらそれぞれのポートにパケットを出す、みたいな機能を持ったスイッチングハブがあれば、監視したいデバイスのMACアドレスをPCから出して横流ししてもらう、みたいなこともできるだろうけど(MACアドレスをどうやって偽装するかはさておき)、実際のスイッチングハブは、MACアドレスは最初に登録されたポートを使って、一定時間(数分とか)で削除して、必要になったらブロードキャスト/学習で登録し直して、同じMACアドレスが複数存在する場合はテーブルから削除されたタイミングで新しく応答したほうが使われる、みたいな挙動らしい。



 10BASE-Tの10MHz(max20Mtoggle/sec)って、マイコンからすればSPI/UART/USB FSと同程度のGPIO速度なわけだし、変調方式だって極めて単純だし、10BASE-T Phyを内蔵したマイコンだってもっとあっても良さそうな気がするけど、Ethernet Phyを内蔵したマイコンってかなり少ない気がする。前回書いたSTM32はMACまでを内蔵していて、外付けしたPhyとはRMIIで接続する方式。

 別件で調べ物をしていたらルネサスのSHでPHY内蔵(パルストランスだけ外部に用意)というものが出てきた。BGAパッケージなので結構大規模なマイコン。

 平衡を扱わなきゃいけない(コンパレータで受けなきゃいけない)のが面倒、長距離を引き回して入ってくるノイズに耐えるのが大変、そもそも10BASEの需要が無い、みたいな理由なんだろうか。そりゃUSB FSと10BASEどっちを使いたいかというとUSBのほうが需要はありそうだけど、かといって10BASEもちょっとしたセンサやコントローラのネットワーク化とかでは便利そうな気がするけどな。USBは短距離のP2Pでしか使えないけど、10BASEなら比較的自由なトポロジで配置できるし。

 そういう機器を作りたいなら適当なPhyをSPIとかで外付けすればいいでしょ、みたいなことなのかもしれないけど。

 これからの時代だと、車載用の10BASE-T1Sや100BASE-T1を内蔵したマイコンは出てきそうだけど、マルチレベルを出さなきゃいけないからマイコン直結は面倒そうだ。結局RMII接続かな。ワンチップで(外付けPhy等無しに)10BASE-T1Sを接続できるマイコンは末端付近で便利そうだけどな。まあ、それが発売されたところで、家庭やオフィスの10BASE-T対応ネットワークに接続できるわけではないけども。



 Wikipediaのボーレートの説明を見ると、10BASE-Tは10Mbaudと書いてあるし、RS-232でもbpsとbaudは同じ値、みたいに書いてあって、ちょっと違和感。

 個人的には、ボーレートは1秒間で信号が変化する最大の回数、ビットレートはそれによって送ることができる実効データレート、の認識なので、例えば10BASE-Tはマンチェスタ符号化だから20Mbaudだし、9600baudのRS-232はスタートビットとエンドビットを除いて実効ビットレートは7680bps(Start1,Data8,Parity1,Stop2なら6400bps)、というイメージなんだけど。


2026年1月14日水曜日

小ネタ


 浜岡原発審査で過小評価疑い “データのねつ造 極めて重大” | NHKニュース | 静岡県、原発、原子力規制委員会

 そもそもなんで規制する根拠となる資料を規制される側に作成させているんだよ、という運用の問題な気がするけどなぁ。誰が好き好んで自分の首を絞める作業を馬鹿正直に行うんだよ。そういう問題が起きないようにするために、独立性を高めることを目的に作ったのが規制委員会だろ。せめて規制するための資料くらい自分で作れよ。まあ、規制するための数値を規制庁が用意しても、それに耐えられるという根拠を改ざんされたら意味ないじゃねーか、という話ではあるけど。


 経産省 浜岡原発の契約変更問題 中部電力に追加報告求める | NHKニュース | 原発、経済産業省

 別の問題も出てくると、体質の問題な感じもしてくるけど。あるいは長期間運転を止めているせいで緊張感が失われているみたいなこともあるのかもしれないけど。



 IT開発者向けの質疑応答(QA)サイト「Stack Overflow」で投稿数が激減、ユーザー戦慄 - やじうまの杜 - 窓の杜

 なんとなく個人的に感じている「昔のOSSって謎の活力があったよね」くらいの時期と相関していそうな気もするけど、でも2023年辺りまでは結構アクティブだからあんまり関係ないか。



 Shrike-lite: 開発ツール・ボード 秋月電子通商-電子部品・ネット通販

 ForgeFPGAとRP2040を載せたボード。

 オープンソースでGitHubに色々資料あるから参照してね、という方針。逆に言えば、まとまった資料が存在しない。LiteではないやつはRP2350が乗っているらしい。

 FPGAとRPは、RP側から転送するためのSPI接続等がある程度で、基本的には全部ピンに引き出して必要に応じて外部で接続する形かな。まあ、そのほうが使いやすいしな。



https://strawberry-linux.com/pub/ft232hx-v2-an001.pdf

 ストリナさん、手ハンダのクオリティがゲフンゲフン

 自分は基本的に共晶ハンダしか使ったことがないので、無鉛ハンダだときれいにつかないとかあるのかもしれないけど。



 半導体ウエハの見た目をしたウエハース(お菓子)って作れないものかな。8インチとか12インチとかちょっと大きめの円盤状の形で、表面に多少の模様をレーザー等で焼き込んだりして。必要に応じてカット(ダイシング)して提供してもいいし、丸いまま売ってもいいし。あるいはダイシングしたものをクリームで重ねてチップレットにしてもいいし。模様もレーザーで後から焼くだけじゃなくて、光ディスクみたいに焼いてもいいし。さすがにウエハース程度の引張強度だとあまり細かい模様は無理かもしれないけど。

 千歳あたりのお菓子屋さんで道産食材を使ったウエハースでそういうやつを作ってラピダスの話題に便乗して売ったら面白そうだけどな。

 ウエハースのレシピってググってもほとんど出てこない。IPコラボで買った大量のウエハースを消費するためのアレンジレシピとかばっかり出てくる。均質な内部構造を考えると材料や加工法がそれほど複雑とも思えないが、どうなんだろうか。


 熱で溶かした砂糖をチョクラルスキー法で引き抜いたらどうなるんだろう? 巨大な単結晶の砂糖とか作れるんだろうか? さすがに8インチとか12インチとかの砂糖の結晶を作っても取り回しが大変そうだけど、ミニマルファブで使うような0.5インチだと細めの金太郎飴くらいの径。産総研のミニマルファブの展示でお土産として半導体風の模様の金太郎飴とか配布しても面白そう。あるいは単色の砂糖の棒を0.25mmくらい(実際のウェハー厚程度)にうまく切断して、レーザーで半導体みたいな模様を焼き込むとか。同じ程度の厚さというよりは、同じ程度の曲げ強度で切断するべきかもしれないけど。

 理研が富嶽そうめんとか売ってるし、産総研も負けずに半導体ウエハースとかを売ろうぜ。研究者カードを入れてさ。


 メーカーによるグラニュー糖の加熱特性の違い|農畜産業振興機構

 いくつかのサンプルで融点を比較した結果とか。

 メーカーの違うグラニュー糖でカラメルソースを作るとかなり違うものが出来上がるらしい。微量な成分の差で大きな影響があるとかだいぶ半導体に近そうな感じがしてくるな。



 Google Pixelのカメラ、電源ボタン二度押しでカメラを起動して音量ボタンで静止画を撮影する機能、動画を撮影したいときに困ってたんだけど、音量ボタン長押しだと長押し中は録画されるんだな。長押し中に録画ボタンを左に移動して鍵アイコンに重ねるとボタンを離しても録画を継続して、録画ボタンをタップor音量ボタンで録画終了。タッチ操作ができない状況(厚手のタッチ非対応手袋を使っているとか)を考えると、物理ボタンだけでオルタネートに録画を開始できると便利なんだけど、ちょっと足りない。



 YouTube、デザインが変わってまた使いづらくなったな。

 YouTubeとかGoogleの機能やデザインの変更って「不便になった」と感じることは多いけど、「便利になった」と感じることってほとんど無い気がする。まあ、不便になったら目立つし、便利になっても無意識に使うだけだし、みたいなこともあるんだろうけど。

 それにしても、普通にスクロールやクリックができないUIって単純に不便だし、もっと言えばクソだろ。なんでそんなものがデプロイされるんだろう? Google系の会社、時々本当に変なことをやる。



 amazonみたいな大企業が作る防犯カメラみたいな製品にひどく反発しているレビュー系の仕事もやっている某有名企業、消費者のプライバシーを侵害して稼いでいるからみたいなのが理由らしいけど、彼らってどういう製品なら納得するんだろう。

 小さい会社が開発した製品ならいいの? そういう会社が開発したコネクティングデバイスが信頼できるとでも? セキュリティしかり、製品寿命しかり。あるいは小さな会社の製品がある程度普及したら簡単に買収されるリスクも有る。西側企業が買収するならともかく、家電企業が中国企業に買収されたりみたいなことも起きている昨今、下手に市場価値の低い会社が作る製品はそういう点でもリスクがあると思うが。AnkerやTP-LinkやiRobotの例もあるし。アメリカのビッグテックが消費者のプライバシーを侵害するのは許さないけど中国政府がアメリカ国民のプライバシーを侵害するのは問題ない、とでも思ってるの?


***


 ジャイロスコープのプリセッション、力学的に正しいかは別にして、感覚的に理解しやすいのは、人工衛星の軌道で考えてみることだと思う。

 人工衛星が円軌道を回っているときに、軌道面に対して垂直に力を加えると、垂直な方向の運動エネルギーが増える。元々持っていた運動エネルギーとベクトルが合成されるので、斜めの速度になる。あとはそのベクトルを面内に持つ軌道面を回転する。これだけ。

 これを十分に弱い力かつ長い周期で考えたときに、この人工衛星が例えば適当な間隔(10mとか)で大量に並んでいても、同じ動きをする。それらを紐でゆるくつなげても同じ動きをする。同様に、棒で比較的固くつなげても同じ動きをする。剛体(自転車の車輪とか)で考えた場合は、1周期未満の短い時間で力が加えられる前の箇所にもプリセッションが伝播する点が大きく異なる。

 大雑把にはそういう感じに見ておけばいい気がする。ただ、この方法でイメージするためには、人工衛星の軌道をある程度正しく認識しておく必要はあるので、例えば小学生にこのイメージを説明すれば全員が理解できるというようなものではないけれども。

 もう少し身近なもので近似したいなら、重りを付けた紐を振り回してもいい。ただし地球の重力は無視するものとする。


 質点に与えた力は時間積分して垂直方向の速度になるが、その力を受けた結果は元々持っていた運動エネルギー(接線速度)との合成だから、接線速度に対して垂直速度が小さければ角度の変化は小さくなる。接線速度が大きければベクトルの角度は小さくなるし、接線速度が小さければ角度は大きくなる。ジャイロ剛性はこれでおおよそイメージできる。もちろん、接線速度がゼロなら垂直に与えられた速度がそのまま出てくるから、歳差運動は発生しなくなる。どれほど小さくても接線速度がゼロでないなら、歳差運動が発生する。


***


 LAN内機器での時間同期の標準規格「PTPv1」こと「IEEE 1588-2002」【ネット新技術】 - INTERNET Watch

 累積誤差を排除した2代目PTP「IEEE 1588-2008」、LAN内機器での時間同期の精度を向上【ネット新技術】 - INTERNET Watch

 PTPv2の成功を受けて登場した「IEEE 1588-2019」は、広範な利用のためのオプションを追加した「PTPv2.1」【ネット新技術】 - INTERNET Watch

 PTPってちゃんと調べたことなかったけど、わりと簡単っぽい感じだな。UDPのパケットを投げるので、基本はNTPとほぼ同じ。

 NTPはクライアントから始めて1往復のやり取りを行う。パケットの中に送受信時刻を含めるが、送信時刻は送信する予定の時刻を入れてあるに過ぎないから、キューに積まれたりすると実際の時刻とずれることがある。

 PTPはサーバーから定期的に2つのパケットをブロードキャストする。2つ目のパケットには1つ目のパケットを送信した実際の時刻が記録される。クライアントは1つ目のパケットを受信した時刻を記録しておき、2つ目のパケットで時刻を決める。ただしこの1つ目の時刻には伝搬遅延分の遅れがある。

 正確な時間が必要になると、クライアントはサーバーに向けてパケットを送信する。クライアントはこれの送信時刻(含1way遅延)を記録しておく。サーバー側はそれを受信した時刻を記録し、これをクライアントへ返信する。クライアントが送った時刻とサーバーが受信した時刻を比較すると2way相当の伝搬遅延が得られるから、これを差っ引けば、サーバーとクライアントで時刻同期ができる。

 これがPTPv1の仕組み。

 PTPではパケットのどの部分を時刻の基準に使うかも定められているので、これと時刻を結合するために、PTP対応のハードウェアが必要になる。時刻の基準はあくまでもMAC層のパケットの頭が基準になるので、PTPに依存したものではないから、他にも汎用的に使える時刻基準ではあるから、汎用的に使える時刻基準としてPHYで対応して、それを流用してPTPにも使う、みたいなことは可能だろうけど。

 ただ、PTPv1ではブロードキャストのパケットにはPTPサーバーを選択するための情報(精度や確度など)を含めている関係で、パケットが大きくなり、これで輻輳が発生することで信頼性が低下する問題があった。そのため、PTPv2ではブロードキャストパケットを小さくすることで高頻度に放送できるようにした。これがv1とv2の互換性がない所以。

 v2.1ではCERNで得られた知見に基づいて精度改善を行ったり、曖昧さを除去する改定が行われた(その他色々なオプションの追加も)。例えばスイッチやルーターを通過する際に増える遅延(特に遅延に方向性がある場合)に対する改善など。PTPv2.1を使うためには対応したスイッチ/ルーターを使う必要がある。


 以上がPTPの簡単な仕組みだけど、この理解が正しいのかは不明。PTPの仕様はIEEEが決定・販売を行っているので、非会員が正規に買おうとすると250USD程度の値段になる。

 結局、規格が普及するかどうかは無料公開か有料公開かに関係なく、需要があるタイミングでタイムリーに規格を提案できるかどうかなんだろうな。よほど高価なプロプライエタリとかならともかくとして、200ドル程度でドキュメントが買えるならな。趣味で遊ぼうとかすると困るけども。


 PTPの要点はハードウェアでパケットの時刻決定ができる点と、パケットの送信時刻を別のパケットで送る点なので、やろうと思えばNTPの拡張でも対応できたような気がする。物理層の時刻決定は追加で必要として、残りはNTPのパケットだけでどうにでもできそう。ブロードキャストとか追加領域とか、一通り必要な機能はNTPにもあるし、124番ポートは特に使われていないようだから、これを追加でNTPに割り当ててもいいだろうし。

 例えばクライアントは124番を開いて、サーバーは124番に対してブロードキャストを行って、それを受信したクライアントは123番宛に追加でパケットを送って、従来のNTPは123番でそのまま使って、みたいな感じとか。

 PTP、わざわざ新しい規格を作るほどかなぁ、という気はする。下手に拡張するより作り直したほうがわかりやすいだろ、ってことかもしれないけど。

 PTPは100万分の1秒の精度がある、とかいったって、NTPだってパケットのフォーマット自体は数百ピコ秒程度の時間分解能があるわけだから、確度を改善すればいくらでも改善できるだろうし。

 ただ、上記の記事はあくまでもNTPに一番近い形態を解説しているだけであって、実際のPTPはもっと色々な設定が可能なので、柔軟に使おうとするとやはりNTPの発展では難しくて、PTPが必要だったんだろうな。


 PTPはイーサネットフレームのヘッダ開始点を基準に時刻を決めるので、自然にイーサネット内でしか使用できない。まあ、べつにルーターやWiFiを超えさせてもPTPパケットとしては問題ないはずだが、その間の遅延を確定(高精度に推定)できないので、PTPとしての精度は得られない。なので、パブリックPTPサーバーみたいなものも基本的には存在しない。

 将来的に広域通信網全体にPTP対応機器(ユーザーが見えないところはTCで、末端付近はBCで、とか)が配置されたらどうなるかはわからないけど。GNSSみたいにジャミング・スプーフィングのしやすい時刻でなく、有線で高い精度の時刻を配布できるPTPが普及すれば欲しい用途はあるだろうし。

 しかし、PTPは高頻度でパケットをブロードキャストしなきゃいけないから、広域に使うのは難しそうな気がする。BCとP2Pで通信するならNTPみたいにクライアントドリブンで使えるのかもしれないけど。/* PTPとP2Pの紛らわしさよ。。。 */


 PTPとしては、高い時刻確度が必要な場合はGNSS等で、そうでなく、あくまでもLANの中(例えばファクトリーオートメーションやテレビスタジオ)で機器間の同期を取りたい場合は絶対的なUTCとの同期は必要ないから、そういう場合はNTPで外部と同期すればいいらしい。

 もう少し厳密に言うと、PTPはUTC系ではなくTAI系+Leap情報を採用しているらしい。ので、GPS系とは相性が良さそうだし、閏秒を透過的に拡散する最近の公開NTPサーバーと組み合わせると問題が起きそう。特にホールドオーバー用に高精度なクロックをローカルにおいている場合。まあ、それくらい考えてるシステムならNTPサーバーの実装(LIを正しく返すかどうか)くらいは確認して使うだろうけど。あるいは、GNSSとかを使わない系ならむしろ閏秒は拡散してくれる方がありがたいって場合もあるのかもしれないけど。



 White Rabbit Project - Wikipedia

 CERNのPTP実装。白兎は『不思議の国のアリス』から。

 最長10kmの銅or光ケーブルを使ってナノ秒未満の精度が得られるらしい。

 1000BASE-Tなら125Msy/s、10GBASE-Tなら0.8Gsy/s程度だから、その逆数で8ns、1.25ns、クロックの真ん中でサンプリングするならその半分程度、PTPv2以降は数十~100Hz程度で同期信号を打つから平均化して数倍程度、と考えると、数ナノ秒からサブナノ秒くらいは行けそうではあるが、それにしても。


 確度で見ればGPSコモンビューと同程度で、線を引き回さなきゃいけない分導入コストが高いし距離とコストが比例するけど、外部からの攻撃が難しいとか外部システムに依存しないみたいな利点はありそう。あとは、Gbpsオーダーのデータを流すのにも使える。基本的にGPSはデータリンクには使えないからな。

 有線(ファイバーとか)に対してスプーフィングを仕掛ける難易度ってどれくらいあるんだろうか。十分に情報的なセキュリティを確保したネットワークに対しては、少なくともケーブルに物理的にアクセスする必要があるから、周囲の物理的なセキュリティ確保である程度は対策できるか。GPSならある程度離れた場所からでも受信アンテナに向けてうまい感じに電波を突っ込むだけでも偽装(あるいは妨害)できる可能性がある。物理的に接触する必要があるケーブルなら、建物の耐タンパー性で少なくとも偽装・妨害を試みた段階(物理的にネットワークへ触れる少し前)で検出できる。GPSだって信号自体の認証とかビームフォーミングでどうにかしようという話もあるけど、ビームフォーミングするとまたそれで時刻確度が悪化するとかもありそうだしな。ネットワークも完全に独立したシステムを作るのも難しいだろうし、電子的に外部から入ってどうにかしたりみたいなことも考えられない訳では無いにしても。



 電力保安用IPネットワークにおける高精度時刻同期方式の適用検討-PTP同期の精度評価とIP機器の同期機能割当て- 報告書 詳細情報 | 電力中央研究所

 ガチの研究所が自分たちの必要な精度(1us)を得られるかどうかを色々な条件で比較した結果。ネットワーク系の会社が技術ブログで概要を説明しているのとは異なって、かなり細かいところまで説明している。


 商用電源なんて50/60Hzだから対してタイミング確度あんまりいらんやろ、とか思ってたけど、60Hzを1度単位でサンプリングしようとすると45us程度になるし、マージンを考えると5us程度は必要になるのか。



 そういえばSTM32 Nucle-144でEthernetポートが乗ってるやつあるけど、あれどういうふうに使えるんだろ、と思って軽く検索。STM32自体はRMIIでインターフェースして、PHYはMicrochipのLAN8742Aが乗っているらしい。

 PHYのデータシートを見た感じ、割り込みに設定できるのはWoLとかA/Nとか、いかにもPHYが触りそうな部分だけで、イーサネットフレームの送信とか受信に関連しそうなものは見当たらない。

 そもそもPHYって電線から出てくる電圧レベルをデジタルデータに変換するまでが担当で、フレームを処理したりはもう一つ上の層(MAC?)でやるのかな。その割にWoLはPHYで検出できるから、少なくともWoLが入っているフレームを検出できる程度の機能はあるんだろうけど。


 STM32H7のEthernetはPTPにも対応しているらしい。PTPだけでかなりのページ数を割いて説明している。例によってパケットの内容とかの説明はないけど。

 PTPはMAC層で処理するから、EthernetのクロックとMIIのクロックの差とかもジッターに出てきそうだ。PHYでPTPを処理できれば一番いいんだろうけど、WoLみたいにシンプルなフレームと違って、もう少し上のレベルで動いているから、PHYで処理するのは難しそう。結局MACで処理するのが楽なんだろうな。それにしても、プリアンブルの末端(ヘッダの頭)で割り込みピンを駆動するくらいの機能はPHYにあっても良さそうな気もするけど。



 アメリカのエンティティリストに乗っている某社のドキュメントにPTPの詳しい説明が書いてある。パケットの内容とかも書いてあるので、とりあえず試しに投げてWiresharkで見たり程度はできそう。

 そもそもPTPの内容って有料販売だから気軽に無料公開しちゃだめだと思うんだけどな。グローバルに普及した一般公開されていない(有料販売されている)仕様書の類、このあたりの企業から無料で公開されがち。そういう信頼の置けない商売をやっているから西側から嫌われるんじゃないのか。まあ、ググれば他にもいくつかの企業(機微な製品を扱っているアメリカ企業を含む)が公開している情報にもパケット構造が断片的に書いてあったりするから、そこまで厳しく秘密にしているものでもないんだろうけど(それこそ現物があればWiresharkとかで見ればわかるわけだし)。


 PTPは仕様が無料公開されてないので自分で作ろうとすると大変そうな気がする。WiresharkはPTPv2に対応しているらしいので、適当なパケットを投げてみて試すという手はあるけど。あるいは、CERNのWhite Rabbitが「完全にオープンソース」だそうだから、それを追うという手もあるか。うさぎの巣穴へ真っ逆さま。


***


 W5500でポート9にUDPを投げて、オシロをSEND_OKの割り込みでトリガ

 ↑PCに4バイト投げたとき

 ↓ルーターに128バイト投げたとき

 10MbpsHD、黄色(ch1)がW5500から見たTX+、紫(ch2)がW5500から見たRX+。UDPを出す前にARPでアドレス解決をしているっぽい?

 ルーターからはなぜかエコーバック的なものが帰っている。ただ、W5500はこれを受信してもパケットが届いたとは認識していない(Socket.Int.RECVが立たず、Socket.RxReceivedSizeもゼロのまま)。PCから投げても応答を受信できないから、なんか変なパケットになっているんだと思う。波形を解析すればイーサフレームからパケットの内容を復元できるだろうけど、流石に面倒。。。

 SEND_OKのトリガは、実際には送信が終わる前に出ているらしい。メッセージが衝突したりした場合はどうなるんだろうか。トリガとプリアンブルのタイミングはかなり精密で、数回見た程度だと100ナノ秒未満のジッタ程度に見える。



 PCから同一のUDPパケットを4回送信してRecvで割り込み

 当然だが、パケットを受け取ったあとにRecv割り込みがかかる。2usくらいジッターがあるかな、という感じがする。やはりというか、送信よりも受信のほうが精度が出ない。そもそもW5500の割り込みってタイミングスペックあるのか知らないけど。

 パケットを長くするとフレーム末から割り込みまでの時間も伸びる。おそらくCRCの計算が10Mbpsより遅いんだろう(あるいは受信が終わってから計算しているのか)。受信した長さはRX Bufferを読めばわかるから、Recv割り込みからフレーム先頭の位置までの時間は計算である程度推定できるはずなんだけど、どの程度確実に決められるかは不明。


 W5500の送信割り込みジッタが0.1us、受信割り込みジッタが3usと仮定すると、多少余裕を見てトータルで5us程度になる(受信パケット長から十分な精度でパルス位置を推定できる場合)。NTPは送信時刻を決めるのが難しいけど、PTPのFollow_Upで投げるなら、W5500でPTPサーバ/クライアントを作れば、10us未満程度の同期精度が得られるはず(確度はまた別の問題)。PTPの理想的な状況と比べると4桁くらい悪いけど、ソフト実装のNTPに比べれば2,3桁くらい改善できるはず。そう考えるとNTPとPTPで6-8桁くらい違うのもすごいけど。



 ちなみに、W5500を100BASE-Tに設定すると常にビット列(100BASEのアイドル信号)が出続ける


 だいぶ波形がなまっている。オシロは200MHzだけど、プローブは100MHzなので、125Msy/sを見るのは厳しそう。でも頑張ってクロック同期すればデコードできないことは無さそうかな?

 100BASE-Tのバストリガに対応していないオシロで100BASE-T信号を見るとこれが常に流れるので、イーサネットフレームを狙ってキャプチャするのは難しい(W5500ならSEND_OK/RECVで割り込みをかけてこれをトリガすれば少なくともその付近にフレームがあるはずだが)。



 こういう遊びをしているとアナログ6+デジタル16くらいのオシロが欲しくなる。TekのMOS5みたいに、アナログ1ch or デジタル8chを8系統好きに組めるMSO5は便利そうだなぁ。なお値段。

 横河のやつだと12bit8ch+1bit32chみたいなモデルもある(MSO5換算12ch)。ベース価格で比べればTekの半分くらいの値段だし。まあ、それでも高級な軽自動車が新車で買えるくらいの値段になるらしいけど。横河の一部の機器にはIEEE 1588 PTPサーバー機能が乗っているらしい(クライアントは結構多い機種で対応)。カタログによると「誤差1us以下の高精度なクロック同期を実現」だそうだ。横河の計器は同一機器を接続してch数を倍増する機能があるけど、PTPで同期すれば異なる機種間でも時刻同期ができるらしい。トリガ信号を接続すればサンプリング時刻は同期できるけど、PTPなら非同期的な信号も含めて、柔軟に時刻同期できるだろうしな。

 Sigだとアナログ8ch+デジタル16chで100万円台から300万円弱まで(帯域幅による)。RIGOLもほぼ同じ価格帯かな。SigやRIGOLはいくら最近は良くなってきたとはいえ所詮は中国の安物計器メーカーから始まっているし、ブランド物には使いやすさとかの点ではまだまだ勝てなさそうな気がする。まあ、LeCroyあたりでSigのリバッジを売ってるのを見ると、ブランド品だって安物はクソみたいな品質なんだろうけど。

 LeCのカタログ、「アナログ8チャンネルとデジタル16チャンネルは常に利用可能です。他社の機器のように、デジタルチャンネルを利用する際に、アナログチャンネルを犠牲にすることはありません。テレダイン・レクロイなら、常に全チャンネルが利用できます」とか書いてあってすごい(横河のオシロでもアナログchをデジタルとして使うみたいな製品もあるし)。


*


 10BASE-Tの波形データをExcelに取り込んでみた

 縦軸は任意の単位(8bitADC直読み)、横軸はマイクロ秒。700kptsが2chなのでかなり重い。

 Excelで横幅が広い散布図を書くと補助目盛線の位置がずれる不具合、普通に迷惑なので早く直してほしいなぁ。。。



 .NET FWのChartでグラフ化

 .NET Framework久しぶりに触った。昔のC#って不自由だったんだなぁ。全然好きに書けない。それでもLangVersionで13.0とか指定すればかなり自由にはなるけど。


 2個目の送信を適当にマンチェスタ復号して手動デコード

 クリアビットと思われるエッジは青色の、セットビットと思われるエッジは赤色の点を打っている。また、それらを8個合わせて16進の値も合わせて表示した。復調にはクロックリカバリが必要かなと思っていたけど、クロックリカバリなしでもおおむね問題ない感じで復調できた。クリアビットが明らかに上に寄っているけど、プリアンブルの一番最初のエッジから50%後ろをサンプリングポイントとして採用しているだけなので、その分のズレだと思う(セット/クリア判定はサンプリングポイントから適当に±数サンプルずらした2箇所の高さを比較)。パケット長が60usで1シンボルが0.05usだからタイミングはそこまで厳しくないらしい。

 マンチェスタ符号のクロックリカバリってどうやればいいんだろう? エッジの位置を探すにしても、エッジが鈍っていたらどこを採用すればいいんだろうか。AC結合するにしても、ビットパターンによってはDCオフセットがあると思うんだけど。


 ビットの意味についてはWikipediaを見ながら復調してみたけど、とりあえず妥当な結果が得られていると考えられる。送信先ポートが0で送信元が9だけど、これは単にW5500の設定をミスっているだけ。16進の列もオンラインのCRC32計算機に突っ込んでみたら正しい結果が得られたから、少なくとも明確なビットエラーは無いはず。

 10BASE-Tは安いオシロでも十分に見えるシンボルレートだし、マンチェスタ符号だから見たとおりに復調できるし、楽でいいな。

 FCSの末尾は中途半端な電圧が出ているけど、これは単にマンチェスタ符号の振幅レベルが見えてるっぽい。実データの振幅が高いのはおそらくLANケーブルを伝搬したことで発生したオーバーシュートだろう。FCSの末尾ではマンチェスタ符号として不正なDCを出すことで明確に末端を示しているんだと思う。

 本来はARP(推定)や謎のエコーバックも復調したかったんだけど、思った以上に面倒なので省略。ただ解析するだけなら大した手間でもないんだけど、図示しようとするととても面倒。ChartなんでFW以外で使えないんだよ。。。


*


 ためしにW5500を操作するGUIを試作

 いろいろ設定できる場所とか見れるものが多いので、1画面に全部並べるとFHDでは収まりきらない。

 手動でパケットを投げたり読んだりもできるけど、とりあえずDNSだけ作ってみた。結構大変だった。主に普通のリソース管理で。SPIバスは1本しかないし、ソケットは同時に8本しか開けないから、それらをうまいこと管理する必要がある。

 結局、FT232H/W5500を使っていても、うまい感じに隠蔽すればC#のTcpClientやUdpClientと同じように使えるし、それこそSend/Receiveを作れば全く同じように使えるから、C#側でTcp/Udpを使うコードを書いてそのまま流用したりもできる。


 W5500のCommon Register 0x0017 Socket Interrupt Register、各ソケットから割り込み要求があるとそのビットがセットされるレジスタだけど、データシート上は書き込み可能(R/W)になっているのが謎い。0や0xFFを書いても何の効果もないし、もちろんセットビットに相当するソケットの割り込み要求がクリアされる、なんて機能も無い。


***


 そういえば、SpaceWireって情報がないときでもクロックが出続けているはずだけど、これでクロックを配布しようみたいな使い方ってないんだろうか? 全部の機器はルータで接続されているわけだし、ルータもクロックリカバリして他のポートにクロックを配布できるだろうし、すべての機器がコヒーレントに動いていれば、クロックを積分すれば時刻が得られるから、機器間の時刻同期も楽になるだろうし。

 ビットレートを切り替える際とかは困るだろうけど、宇宙用コンポーネントなんてルーティングも全部冗長化してるんだから、片方ずつ切り替えて常にコヒーレント(片系統が死んだら非コヒーレントで時刻決め)みたいな運用もできるだろうし。

 そこまでして精密にクロック(積分して時刻)を配布したい需要があるかどうかはともかく。SpaceWireだって時刻配布プロトコルはあるわけだから、大抵の需要はそれで十分だろうしな。


2026年1月7日水曜日

小ネタ


 米NISTの原子時計のラボツアー


 実験用のクロックだと思うけど、ナイトビジョンゴーグルが置いてあるのが面白いな(おそらくFLIR社のGen1)。機器では剥き出しの赤外線レーザーも使っているそうだから、センサーカードでトレースするよりNVGで見たほうが楽、ってことなんだろう。

 フィクション世界でよくある赤外線レーザーをナイトビジョンゴーグルで見るやつ、現実世界でも実際にやってるわけだ。


 コロラド州ボールダーってアメリカのかなり内陸の方にある。標準周波数・時刻を放送するにはそのほうが都合がいいんだろうけど、最近の一般相対論的効果が問題になるような(標準海面からの標高が必要になるような)時代になると大変そうだな。まあ、国土を網羅した水準点からちょっと伸ばしてラボに引き込めばそれで済むんだろうけど。

 将来的に標高計としての精度が10cmとか1cmとかのオーダーで日常的に得られるような時代になると、あまり内陸すぎると標準海面との結合が面倒になって海岸近くのラボのほうが使いやすいって話になったりするんだろうか? あるいは日本だと周りを海に囲まれていて潮汐が綺麗に流れないからモデル化が難しい、みたいな課題が出てきたりするんだろうか? 潮流を遮ることのない孤島に基準点を置いてコモンビューで結合するとかが必要になるのかな。

 単に海面と結合できればいい程度なら、東京大学は日本水準原点から近くて便利そうだ。NICTもそう遠い場所じゃないし。



 秋月電子、最近全然使ってなかったけど、久しぶりにいろいろ探して見るとディスコンマークだらけだな。

 秋月製のブレークアウトボードがだいぶ前からSparkfunみたいな設計思想でなんだかなーと思ってたけど、より一層電子工作初中級者向けに力を入れる一方で、かゆいところに手が届くような商品ラインナップを減らしているような雰囲気。

 ストリナもストリナで変なフォームファクタのブレークアウトボードを量産していた時期があったけど、最近はあまり見かけない気がする。そもそも最近は新製品をあまり作っていないというのもあるけど。ストリナは最近もちらほらセンサ類を出してるけど、基本的には電源周り専門メーカーみたいな感じになってきたな。

 最近は中国系の安いPCBメーカーが使いやすくなってきたから、変なSMDを使いたい人は自分で基板を起こしたり、部品もMouserとかで買ったりするようになって、小さい店だと中上級者向けの商品ラインナップは厳しいのかもしれないけど。個人向けにニッチな製品が買えるショップは大陸系のECストア(含不正規品流通ストア)がその役割を取って代わって、実店舗は入門・初中級が気軽に欲しい部品を買える方向に特化して、みたいな。時代の流れ的な。



 Type-C PDのデュアルロールなモバイルバッテリーとかで、ロールを強制的に切り替えるボタンが欲しい。例えばノートPCとモバイルバッテリーを接続した場合に、ノートPCの電力でモバイルバッテリーを充電したり、あるいは逆にモバイルバッテリーからノートPCを充電したり、というのを、気軽に切り替えられるようにしてほしいわけだ。

 CCのブリッジみたいなICで、特定のメッセージを捨てるとか、強制的にロールをスワップするみたいなICもありそうだけど、気軽に安心して信頼できる製品でそういう物があるかというと…… エレコムやサンワサプライあたりでそういう機能(ユーザーインターフェース)を内蔵したPD充電ケーブルとか売ってくれるとありがたいんだけど。あるいはスイッチ無しでも、ダイオードとして使えるPDケーブル(ケーブルの向きを変えたら給電方向を切り替えられる)とか。



 興味本位で海外通貨の購入方法を調べてみたら、近所のローソンが出てきて、いやいや、んなわけwwと思ってたんだけど、そういえばこのあたりってなまじ観光地なので、訪日客向けに外貨両替の需要もあるのか。

 ローソン外貨両替機|ローソン公式サイト

「外貨から邦貨への両替のみとなります」だそう。そりゃそうだろうな。

 Google Mapには近所にもこの機械が置いてあるらしいんだけど、公式サイトの一覧には書かれていない。謎い。


 旭川空港にも外貨両替機は置いてあるけど、100ドルとか100ユーロとかそのあたりの1金額しか対応していないらしい。海外旅行に行くために大きな額を両替したいわけじゃないからなー。単に小額紙幣を何種類か見比べるために手元に欲しいだけであって。



https://www.amazon.co.jp/dp/B076H4R6J6

 大量の毒ヘビが飛行機の中で暴れまわる、みたいな感じの作品。毒が出てくるので若干グロ表現ありのB級ホラーなので、他の人に勧めたいという気はさらさら起きない作品だけど。

 大昔に読んだB級映画の紹介で面白そうだと思って頭の片隅に入れていた作品。「フライトシミュレーター」(プレステ2)で2000時間の飛行経験を持つデブが最後に着陸を決めてサミュエル・L・ジャクソンが「神様プレステ様!」と叫ぶというシーンがあるらしくて面白そうだなって思って。

/* Bloggerのテキストエディタで黒文字黒背景にすると若干見えちゃうんだな。黒文字は明示的な色指示が無いので、スタイルシートとかブラウザの設定で真っ黒ではなく、濃い灰色で表示されるっぽい。ちゃんと見えないようにしようとすると、スタイルのcolorとbackground-colorに同じ色を指定しないとだめっぽい */


***


 間接的にニュートリノを見る生態系、という空想。

 惑星が恒星に近く、ニュートリノ断面積の大きい物質が比較的リッチな環境で、化学的に光を遮る物質がすくなく、地理的に恒星光が届かないような環境で進化した生態系を想定。このような環境では環境がニュートリノチェレンコフ光で発光しているはず。端的に言えば、このチェレンコフ光を見ることができるように進化した生物群。

 惑星の軌道が小さく常に暗黒の世界ということは、潮汐ロックした環境だろう。夜間側で生態系を維持できるということは、昼間側はもちろん、トワイライトゾーンも生息するには高温すぎる環境のはず。であるならば、恒星光を浴びたことがない生態系もあり得るはず。ただ、その場合は初期の低効率な光受容体を選択して残すことができないから、チェレンコフ光が見えるような高感度な目に進化する可能性がかなり低い。

 昼間側あるいはトワイライトゾーンで発生・進化した生態系が目を十分に進化させたあとで、何らかの要因で惑星軌道が縮小して生物は夜側へ移動し、その過程で高感度な目に進化させた、みたいな可能性はあり得るけど、ちょうどいい時間スケールで軌道を変えるのはかなり難しそう。あまり早すぎると生息地を移動する前に絶滅するだろうし、天体物理的な尺度での短期間でも、生物が進化するには十分に短い期間になるだろうし。

 あるいは、大きな軌道の時点では潮汐ロックはしておらず、惑星全体(少なくとも赤道全体)に生態系が分散していて、何らかのイベントで近日点が極端に下がって、かつ遠日点も下がって、一部の地域にいた生態系がたまたま夜側で生き残る、みたいなことは考えられるか。公転軌道を都合よく2段階に変えるようなイベントも思いつかないけど。1回だけならショルツ星みたいに恒星の接近で軌道がずれる可能性はなきにしもあらずだけど、もう1回となるとなぁ。内惑星とのスイングバイとかでなんとか…… それにしたってきれいな円軌道に持っていくのは難しいし。


 もしもニュートリノチェレンコフ光を見ることができる生態系があったとすると、進化の過程でニュートリノ断面積の大きい物質を排除するような選択もあるんだろうか? 「目に見える」食べ物を体内に取り込むと早く捕食されるということにはなるだろうけど、だからといって「目に見えない」食べ物をどうやって探すかという問題が出てくる。電気信号を探すみたいな器官が出てくるとかかな。そもそも「目に見えない」食べ物はどうやってニュートリノ断面積を下げてるんだという問題になるし。


 ニュートリノを「(間接的に)見る」というよりは、単純に光源として使っているだけではある。恒星に極めて近い惑星で、通常であれば温度が高すぎて生物が生存できない環境であっても、裏面なら適度に冷えるはずだし、裏面なら有害な放射線もほとんど完全に遮断できるが、惑星を貫通するニュートリノのチェレンコフ光を光源にして数百nm程度の電磁波を見ることができる生物が作れないか、みたいな考え方。


 地球の海洋でもニュートリノチェレンコフ光はそれなりの頻度で発生しているだろうけど、とはいえそれを見られる生物がいるかというと…… 人間がニュートリノチェレンコフ光を探そうとするとアホみたいな大きさのPMTが必要になるからなぁ。よほど強い理由がないと光受講器官をそこまで発達させるのは大変そう。


***


 EthernetってそのルーツはALOHAnetとかにもつながるわけだけど、これはUHF(つまりRF)でパケットをやり取りしていた。10BASEとかで明示的にベースバンド信号と書いてあるのは、それらと比較してという点もあったんだろうか?



 W5500のSocket n TX Write Pointer Registerの使い方が結構謎い気がする。送信する場合、データを入れたりSENDコマンドを叩いたりはコントローラー側で管理できるから、わざわざリングバッファを使う必要はないはず。RX Bufferみたいに、バッファの中にデータ長を持っているならともかく、そういうわけでもないし。書き込みするときにポインタをキューに持ってとかをやれば送信メッセージをキューイングできるけど、バッファの空き容量も自分で管理しなきゃいけなくなるし。



 W5500のSPIは基本的にCSをトグルして可変長(VDM; Variable Length Data Mode)で転送するけど、固定長(N=1,2,4、FDM; Fixed Length Data Mode)の場合はCSをトグルしなくても連続してデータを送ることができる。アドレスが離れた場所に8bit,16bit,32bitのデータを書いたり、同じアドレスに連続してデータを書いたりしたい場合は、FDMで転送するとCSトグル分の時間を省略できる。W5500のデータシートではCS Highの最小時間は30nsだから、無駄になるような時間でもないけど。

 W5500の場合、異なる番地に連続して値を書き込みたいという用途はさほど多くない。例えば宛先のIPアドレスとポートは連続した場所に配置されているから、まとめて6バイト転送(VDM)を行えばいい。強いて言えば、バンクを超えた場所(別のソケット)に対してまとめて読み書きしたい場合、とか? そんな使い方が必要になる状況も思いつかないけど。

 同じアドレスに書き込む用途は、例えばソケットにコマンドを送る場合が考えられる。例えばあらかじめ送るデータをTX Bufferに書いておいて、OPEN, SEND, CLOSEのコマンドを連続して送る、とか。

 今回の場合、ソフトSPIなのでクロックレートが極端に遅いので、1バイト転送(ヘッダ含めて4バイト/コマンド)に1ms程度かかる。このくらいの速度なら、OPEN, SEND, CLOSEを並べても問題なく送信できるようだ。UDPで送ったデータも正しく受信側で受け取れている(今回は5バイト転送)。10Mbpsなら1msあれば1万bitを送れるから、数バイト程度なら余裕で送れる。

 SPIクロックレートが20MHzとか50MHzとかで、コマンド間隔がマイクロ秒程度まで狭くなると厳しそうな気もするけど、とはいえSENDを打ってからすぐに転送が始まって、CLOSEを受けても先に送ってるパケットを出し切ってから閉じるだろうし。

 あとは、書き込みコマンドと読み込みコマンドを連続して出せる場合がある、みたいな利点もあるか。何に使うかわからないけど。SENDコマンドを打ったあとでInterruptを読んで、最速で送信が終わればSEND_OKが得られる、とか?



 試しにDHCP discoverを送信。offerが帰らないけど、Wiresharkで覗いたらちゃんと出てる。結論として、discoverを送ってからW5500をダンプするまでに0.1秒くらい待たせていたのを、もっと長く(2秒程度)待たせたらofferが見えるようになった。うちのルーター(DHCPサーバー)の特性なのか、DHCPとはこういうものなのか、応答が返るまでにちょっと時間がかかるっぽい。

 DHCPは貸し出そうとしているIPアドレスを使っている端末がないかどうかを確認するらしいから、それの待ち時間の分かも。WiFiとか多少レイテンシのある経路を考えると、応答がないと判断するまでには多少待つ必要があるし、それに応じてDHCP offerも時間がかかる、ということらしい(Wiresharkでdhcp or arpでフィルタすると、discoverとofferの間にarpが挟まる事がある。オファーを受けずに頻繁に探索するとarpを省略することがある?)。


 Wikipedia曰くDHCPクライアントもOfferを受けた段階でARPを出して、自分が見える範囲(DHCPサーバーが見えない可能性のある範囲)にも割当予定のIPアドレスを持った端末がいないかを確認する必要があるらしい。

 ただ、W5500からARPを出す方法がわからない。ぐぐってみると、TCPやUDPを出す前にARPを出すから、UDPタイムアウトをARPタイムアウトとして代用できるよ、みたいな話が出てくるんだけど、その場合って対象のIPアドレスが存在した場合は不要なUDP/TCPパケットを送信することになるはずなのだが、それってどうすればいいんだろう? ポート9にUDPで適当な長さのパケットを送ってみる、あたりが落とし所?


 Wiresharkは便利だけど、デスクトップPCはSDRのパケットが2系列流れているから、全部取るとあっという間にメモリ使用量が10GBを超える。/* デスクトップPC組んだときに後で増設しようと思って4スロットMBに2スロットしか積んでなくて、そのうち安くなるだろと思って放置してたらめちゃくちゃ高騰しやがって */

 ディスプレイフィルタでは[dhcp or arp]みたいに設定すればいいけど、キャプチャフィルタはもう少し複雑な設定が必要そう(少なくともDHCPは直接指定できない)。例えば[arp or (udp port 67 or 68)]みたいな感じにすれば良さそう? 


*


 SIGLENTのオシロ、起動するたびにIPアドレスが変わるのが謎いので、せっかくだし、Wiresharkでキャプチャ(2回分)

 DHCPはUnicastなのでDiscoverとRequestしか見えない。1回起動するたびにDiscoveryが3回出ているのが謎い。しかもトランザクションIDが2種類ある。


 W5500からDHCPのDiscover→Offer→Request→Packでやり取りすると、同じMACアドレスに対しては同じIPアドレスを割り当てようとしている気がする。

 SIGのオシロもMACアドレスは固定だから、同様に固定のIPアドレスが割り振られてもいいはずなんだけど、実際にはそうはならない。謎い。


 ユニキャストで通信されると何やってるかわからんな。リピーターハブを買えばいいんだろうし、amazonのレビューを見てもそういう用途で買ってる人が多いようだけど、しかしリピーターハブってわりといい値段するのな。高性能なはずのスイッチングハブのほうが安いなんて、量産効果すげーや。


 速度を固定してツイストペアを分岐してEthernetアダプタに突っ込んだりしたら、パケットをキャプチャできたりしないだろうか? 電力が半分になるけど、短距離の接続なら-6dB程度は問題ないだろうし。この方法だと片方向しか取れないけど、アダプタを2個使えばTXペアとRXペアを同時に監視できる。1000BASE-Tは双方向で使うからこの方法は使えないけど、10BASE-Tや100BASE-Tなら取れそう。この方法なら全二重のフルの帯域(20Mbps、200Mbps)も取れるはず。あるいは、半二重でいいなら、TX/RXペアを分岐したあとでアナログ的に加算してもいいはず。


***


 ArduinoでPORTD |= bit1;とかPORTD &= ~bit2;は許されるのに、PORTD = PORTD & ~bit2 | bit1;とかは許されないの謎い。エラーメッセージがno match for 'operator&'とかだから、PORTDとかってメモリマップドで直接触るわけじゃなくて、クラスでラップしてるらしい。

 PORTB&=1;とかやると読み出し、ビット操作、書き込みで遅そうだけど、パルス幅を測ってみるとちゃんと65nsあたりに見えるから、たぶんうまいことOUTSETとかOUTCLRに展開してるんだと思う。だからPORTB=PORTB&~1|2;みたいな操作ができない。

 あと、GPIOから読みたい場合、例えばPINDで8bitを読める、という説明があるんだけど、少なくともうちの環境だとコンパイルエラーになる。Google AI曰くVPORTB.INで読めるよ、とのことだけど、これはATmega側のレジスタなので、ビットマスクに互換性がない。

 ATmega側にはPORTA...Fがあるけど、PORTB...DはArduinoが上書きしているから、ATmega側のレジスタを直接触ることができない。


 Arduino、公式ボードだけでも大量にあるし、互換ボードも含めればさらに増えるし、それぞれで低レベルな部分は互換性が無いし、ググって出てきた情報がどのボードのものかも分かりづらいし、細かいところを触ろうとするとやっぱり大変。

 かといって、今更STM32もなぁ…… 比較的ガッツリSTM32に触っていた頃は手癖でプロジェクトを作ってmakefileを設定してビルドして、とかできてたけど、触らなくなってかなり経つからSTM32+STM32CubeMX+gccとかはちょっと面倒。

 今の時代に小さいマイコンでちょっとした制御を素早くやりたいなら、RasPiPico系にC++開発環境を載せて、速度が不要ならMicroPythonを使って、みたいな感じが良いのかな?


***


 一旦方針転換して、大昔に買ったストリナのFT232Hボードを叩いて遊ぶ。

 ちょっと前にこのボードのVer.2が発売されて、ディスコン部品の変更のほか、オンボードでLDOが乗って、外に3.3Vを出せるようになった。手元にあるやつはVer.1なので、5V出力のみ。W5500みたいに3.3V電源が必要なやつを相手にしようとすると、やはりLDOが乗ってる方がありがたい。


 FTDIのMPSSEを使うと、対応している変換チップならI2CやSPIのような同期シリアルバスやパラレルバスの変換チップとして使うことができる。昔は結構面倒そうな感じだった気がするけど、最近はSPIとかI2Cはラッパーが追加されて簡単に使えるようになったっぽい。

 試しにVer_libMPSSEを叩いて、DLLバージョンが読めることを確認。libmpsseはダウンロードした1.0.8と一致するけど、libftd2xxは3.2.21で、これはよくわからない。少なくとも、デバイスマネージャーで見えるFT232Hのドライババージョンとは一致しない。ググってもこの数値は出てこない。頭にlibとついているから、SPI/I2Cラッパーの下、ドライバの上の部分なのかも。

 続いてSpiGetNumberOfChannelsを叩いてみる。接続したFT232Hが認識されず、channelsが0固定で出てくる。……なんのことはない、FT232HをTeraTermで開いていたのが原因。閉じたら1が帰った。

 続けてSPI_GetChannelInfoでデバイスの情報を取得。DescriptionはASCII文字列(64bytes)だけど、SerialNumber(16byte)はバイナリっぽい。なんの数値かよくわからん。シリアルというくらいだから特に意味はないんだろうけど。

 SPI_OpenChannelとSPI_CloseChannelも、たぶん動作。

 この手の処理(DLL周り)、いい感じに実装する方法がいまいちよくわからん。ハンドルはnintで持つけど、nint剥き出しで取り扱うのも面倒だからクラスでラップしたいし、usingで閉じれるように関数の戻り値でインスタンスを返したいけど、開けなかったときは例外を投げるかnullを返すか、とか、いろいろ。if using(var dev = new Device()) { 正常系 } else { 異常系 }みたいな構文が欲しい。devが非nullのときはifブロックに入って、ブロックから出るときはusingを呼んで、devがnullな場合はelseブロックを処理して、みたいな。結局using var dev = new Device(); if (dev is not null) { } else { }で書くのと同じだから1行減るかどうか程度の違いでしかないけど。あとは変数のスコープの違いもあるけど。

 あとは、列挙型の持ち方も。readonly record structで定義しておくとToStringが自動的に実装されるからデバッグが楽だけど、当然書き換えができない。


 ここまでは順調だったんだけど、SPI_InitChannelでハングアップして進まなくなってしまった。色々試して、LatencyTimerに値を設定すると動作することが判明。ヘッダの定義には「value in milliseconds, maximum value shuld be <= 255」としか書いてなくて、8bit型だから「そりゃそうだろ」というような説明なんだけど、原因がわかってからフォルダ内でLatencyTimerに関する説明を探してみると、release-notes.txtの一番上のLimitationsの中に「LatencyTimer shuld be grater than 0 for FT232H」とそのものズバリの指示が書いてあった(FT232Hか否かはGetChannelInfoで見れるから、必要に応じて最小値の分岐もできる)。

 FT232HにはPORTDが8本あって、SPIはSCK, MOSI, MISOの3系統が必要なので、残り5本からCSが選べる。ここで選んだCSは明示的に出力に設定してやらないといけない(SCK, DO, DIはうまいことマスクしてくれる)。CSの論理も指定できるので、HでEnableになるシリアルデバイスを制御したりにも使える。

 SPI_InitChannelで渡すパラメータを、SPI_ChangeCS関数で渡すこともできる。CSは少なくとも5本使えるから、5個程度のSPIデバイス(CS論理が反転しているものも含む)を接続することができる。

 あとは、パラメータが問題ない場合でも、まれにInitでハングアップすることがある。そういう場合はデバイスの挿抜でハードウェアをリセットすれば解決する場合がある。


 データの転送はSPI_Read, SPI_Write, SPI_ReadWriteがあって、おおむね期待通りの動作をする。これらの関数に渡すオプションでCSを操作できて、例えばbit1を立てれば開始時にCSをアサートするし、bit2を立てれば終了時にCSをネゲートする。それぞれ0なら何もしないから、10バイト書いたあとに10バイト読むがその間はCSをアサートし続ける必要があって、転送が終わったらネゲートしたあとにさらに2バイト送らなきゃいけない、みたいなシーケンスも、問題なく要求できる。

 あとは、バイト数でなくビット数で転送数を指示するモードもあるらしい。オクテット単位でなく、中途半端なクロック数でも送れそう?(未確認)

 ただ、SPI_ReadWriteがなんか変な気がする。送信バッファが、最初にゼロ埋めされた8bitが出て、続けて指定したバッファが(つまり1バイトずれて)出る。受信側はおそらく問題ない(ループバックさせれば正しく1バイトずれた結果が得られる)。同じような操作(GCHandle/Dllimport)でSPI_Writeを呼べば問題ないから、たぶんReadWriteのバグだと思う。SPIで全二重が必要な状況はさほど多くはないけど、皆無と言い切れるわけではないので、ちゃんと使おうとすると困りそう。あと、読み書きをWrite/Readで分割して半二重で頑張るにしても、コマンドを分割するとその分多少のレイテンシが増えるし。


 面白い機能としては、SPI_IsBusyという関数があって、クロックの操作無しにMISOを読むことができる。例えばコマンドを送ると処理中はMISOがLowで、処理が終わったらMISOをHighに上げる、みたいなデバイスを監視することを想定している(もちろん逆も可)。ただ、SPI_IsBusyを呼んだ場合、CSのトグル操作(アサート&ネゲート)が挟まる。なので、一旦デアサートされるとMISOにビジー状態を出力しないようなデバイスを使うことは基本的にできない。

 もしCSのトグル無しにビジーチェックを行いたい場合は、CSのネゲートは省略したWriteで処理を指示し、Write後に一旦CSをChangeCSで別のピンに変更したうえで、IsBusyでポーリングして、ビジーが終わったら再びCSを戻して、SPI_ToggleCSでデアサートする(あるいは0バイトの書き込みでデアサートだけさせる、あるいはIsBusyで解放する)、みたいな処理は可能。

 ただし変更先のCSがジタバタするのと、それに接続されているデバイスがMISOへ出力して競合するので、この用途で使うCSはNCとしておく必要がある。MPSSEにはCSが5本あるから、こういう使い方をする場合はデバイスは4個までしか接続できない。


 SPI用の端子とは別に、GPIOが8本あって、任意に入出力として使うことができる。デバイスの割り込みピンを読んだりに使える(あくまでもアプリケーション側からポーリングして8bitバスを読む必要があるが)。書き込み時はDirも渡さなきゃいけないので、このあたりは適当なラッパーを作ると良さそう。どうせハンドルを持つクラスで隠すだろうしな。

 GPIOをCSとして使うことも可能ではあるけど、操作が煩雑になる欠点はある。あるいは、3to8デコーダとかを外付けして、デコーダのEnable端子にCSを接続して、みたいなことをすればバンクを切り替える感じでデバイスを大量にぶら下げることもできる。あまり多く接続するとSPIバスの負荷が大きくなるけど。

 結局、SPIデバイスを4,5個つないで10MHzくらいで使うのが安心かな。



 SPIとGPIOを操作するサンプル

 CS5本に対して、1本目はWrite, Read, ReadWriteを8バイトずつ、2-5本はWriteを8バイトずつ、その後、GPIO8本に対して32回のトグル操作。

 Writeの前とReadの後にちょっと時間がかかってるっぽい。その割にReadWriteの前はほとんど待ち時間がないのが謎い。それにReadWriteの後が長すぎるのも。


 GPIOは32回のトグルで1.54ms程度なので、1.54ms/31=49.7us程度と、ほぼ50us毎に操作ができる(矩形波を出して10kHz)。ジッタが大きいのはWindowsだししょうがないと思う。むしろ非RTOSでマイクロ秒程度の操作ができることのほうが驚き。コンテキストスイッチがなければそれなりに早いだろうけど、とはいえドライバ周りとかもレイテンシあるだろうに。USB HSのポーリング間隔って8kHzのはずだけど、最短27us(逆数で37k)でトグルってどうやってんだ。



 VCPで開いている場合はGetNumChannelsから見えなくなるけど、OpenChannelでMPSSEとして開いている場合はGetNumChannelsから見えたままになる。例えばGetNumChで1が得られて、OpenChannel(0)で開いた場合、再度(or別のアプリから?)GetNumChで取ると1が帰るが、index:0で開こうとすると、エラーが返る。

 どうせOpenChannelで開いて正常orエラーで判断するしかないなら、GetNumChannelsを呼ぶ必要性はよくわからん。

 しいて言えば、GetChannelInfoでデバイスのハンドルが得られるから、MPSSEとして開いているかは確認できるので、GetNumChannelsでデバイス数を得て、それぞれにGetChannelInfoで使用中かどうかを確認して、未使用なMPSSEを使う、みたいなことは考えられるか。あるいは、GetChannelInfoでシリアル番号を読んで特定のデバイスを選択するとか。

 他のアプリが開いているデバイスでもハンドルが取れるのかは未確認。それが取れたら結構変な使い方ができるけど、リソースの競合とかも怖いしなぁ。



 I2Cモードも試しに叩いてみたけど、結構クセが強そう。SPIモードのSCKがSCLになるのは期待通りだけど、SDAはMOSIで書いてMISOで読む感じになる。MOSIとMISOを短絡しなきゃいけないので、SPIとI2Cを切り替えながら使うような用途には不向き。そんな使い方したいかどうかは別として。あるいは、GPIOで制御信号を出してフォトカプラとかでつないでもいいのかもしれないけど。

 クロックレートは任意の数値を設定できるが、ヘッダにはよく使う速度として100kbps、400kbps、1Mbps、3.4Mbpsが定義してある。

 あと、Read/Writeのオプションが結構複雑で、うまいこと設定しないと正しく動作しないっぽい。なんとなく正しく動いていそうなパラメータはあるけど、本当にこれでいいのかはわからない。スタート/ストップコンディションの有無とかアドレスのスキップとか、色々オプションも設定できる。不要な場合を除いてStart/Stopは明示しておけばとりあえず大丈夫かな? あとはFAST_TRANSFER_BYTEもあるとよし。

 細かいところだと、Readで得られる転送済みバイト数が、バイト数ではなくビット数で帰ってる気がする。


 I2Cで1バイト書き込みの拡大

 3.3V系で4.7kΩ、100kbps。初期化オプションに2を指定している(HiZ/Lowモード)。


 I2CはSPIに比べてコマンドを出せる周期が低い感じ。レジスタを読む場合、書き込みと読み込みを個別にやらなきゃいけないので、その間少し時間がかかる。


 試しにTSYS01(大昔に何かで使った予備)を試してたんだけど、なぜかリードでアドレスを指定したときにNACKが頻発することがあって、うまく通信できなかった。結局、Resetコマンドのあとに10ms程度の待ち時間を入れて解決(Windowsが管理しているから25ms程度待ってるけど)。データシートにはそれらしいことは書いていないけど、Reset後に立ち上がるまで少し待たないとだめらしい。うまく動いたときは、もしかしたらOSやFT232の遅延でいい感じに時間が経っていたのかも。

 うまく使えれば妥当そうな値が読めるので、多少の事に使うなら可能ではありそう。



 試しにI2C High-Speed mode対応のデバイスを接続


 同じく3.3V系、4.7kΩ、100kbps/3Mbps。

 先に100kbps/ODでデバイス04h Wを呼び出して対応デバイスをHsへ移行させて、その後にクロックを3Mbps/PPへ変更してからSrに続けてデバイスのアドレスを指示し、レジスタを指示、さらにSrとアドレス、2バイト読み出し、というシーケンス。/* Hs移行指示は04h Wを使っているけど、これは予約されているので、本来は04h Rや05h W等を使う必要がある */

 明らかにドライブ能力が足りていないので、オシロでは閾値を任意に設定できるから正しい値が読めているけど、ロジアナやFT232Hでは正しい値が読めない。

 ちなみに、Sm/FmからHsへの移行指示を省略していきなり3Mbpsでデバイスアドレスを送ると、アドレスNACKが帰るが、Hs移行指示を出してからデバイスアドレスを送れば正しくACKが出るから、デバイス側のHsへの移行は正しく行われているはず。

 NXP UM10204を眺めてみた感じ、Hsでプルアップを強化するのはコントローラーの責任であって、通常時(Sm/Fm)は通常のプルアップ抵抗オンリーだが、Hsに切り替えるコマンドを出した時点でコントローラーは電流源をONにする必要があるらしい。ただ、この図ではあくまでもSCLに対して電流源を追加するというような書き方にしか見えず、SDA側は通常通りのような気がする。データラインはどうするのがいいんだろう?

 おそらくFT232Hには電流源を追加するような機能はないので、適切なHsコントローラーとして使うことはできないと思う。どうしても必要なら、FT232HのGPIOに定電流ダイオードをつけておいて、Hsに切り替えた時点でGPIOもトグルして、SCLとSDAをそれで引くという手はあるけど。

 あと、Sm/FsからHsへ切り替えるためにはいちいちI2C_Initを呼んでクロックを切り替える必要があるが、それに0.2秒弱かかる。よほど大量のデータをやり取りするのでもなければ、Fsで使ったほうが早いと思う。



 SPIでもTSYS01に接続

 ちゃんと読める。SPIの場合はビジーを取れるので、リセット後の2ms程度やADCの8ms程度も適切に待てる(A7:灰色のジタバタしているのがCS退避先)。

 クロックは10MHzで使用(TSYSは20MHzまで)。ちゃんと速度は出るけど、その分スカスカに見える。



 libmpsse、まだまだ開発中という感じが拭えない気はする。仕事で使えるかというと、ちょっと怪しそう。どうしてもPCとSPI/I2Cのブリッジが必要なら、FT232HをUARTで使ってその下に適当なマイコンを挟んだりして、テキストベースでコマンドを打って必要に応じてバイナリデータを交換して、みたいな感じのプロトコルを作ったほうが安心できそう。マイコンをHIDでPCに直結する手もあるけど、その場合はたいていFSまでだろうから、帯域幅が厳しい。手軽にやるならやはり232H経由のコマンドが楽そう。


***


 乱数発生器を内蔵した小さなチップって無いものかな、と思って軽くググってみたけど、あんまりなさそう? 電源ONで常時1Mbps程度で乱数を作って、十分に長いサイクルで予測が難しく、起動時に確実に乱数が出るようなしくみを持っているもの。

 LFSRの幅が100bitとかはちょっと計算が重そうではあるけど、数十Mspsとかであれば最近の半導体なら流してくれないかな。例えば100bitのLFSRを適当な頻度(数秒に1回程度?)でFeRAMとかに保存して、次回起動時はそこから再開して、工場出荷時に適当な初期値を書いておいて、みたいな感じで、乱数はSPIとかI2Cで好きに読むことができるような感じで。

 ある程度強度のある乱数が欲しい用途って、暗号化とかセキュリティの分野だから、大抵はそういうモジュールにTRNGも入っている印象。外付けでそういうのが必要な用途ってあんまりなさそう。

 マイコンにFeRAM的な長寿命のNVRが乗ってるなら、それで32bit程度のLFSRを作って必要なときだけ生成すれば、予測不能性が不要ならそれで十分だろうしな。FeRAMでなくても、32bit程度ならバッテリバックアップドメインの小さいRAMにも入るだろうし、ある程度綺麗な乱数が必要な用途ならRTC用の電池とかも積んでるだろうし。


***


 いよいよRasPi Picoに手を出すかー、と思ってamazonでポチってみたら、明らかにRSコンポーネンツのパッケージに入った基板が届いた。RSで620円で売ってるやつがamazonで1400円かぁ…… 送料含めてもRSで買ったほうがだいぶ安いんだな。でもRSはクレカがないと注文できないので。社会的な信用がない人間はこういうところで損が目に見えるな。

 このRSの袋が正規品なのであれば、中身も正規品と考えて妥当なはずだが……


 SPIのブリッジにArduino Nanoを使うよりRasPi Picoを使うべきじゃねと思ってポチったけど、FT232HでPCにSPIが直結できちゃったので、SPIブリッジを自分で作る必要がなくなってしまった。。。



 買ったまま開封すらせずに積むのもあれなので、とりあえずVS Codeの拡張で開発環境を入れて、blinkをビルド。USBで接続してストレージにblink.uf2をコピー。コピーすると勝手にリセットされて走るが、ユーザープログラムが走っている間はストレージとして認識できなくなるから、プログラムを書き込みたい場合はBOOTSELを押しながらRUNを地絡してストレージとして再認識させなきゃいけない。

 書き込みの手順としては、リセットボタンを押してプログラムを止めてからBOOTSELを押してリセットボタンを離して、USBとして認識されたらコマンドプロンプト等でcopyコマンドで書き込む、みたいな感じで、STM32F4のUSB DFUと同じような手間で使える。ただしRaspberry Pi Picoはオンボードのリセットスイッチが無いので、どうにか頑張るしかない。

 Picoを2枚買いして1枚をターゲットボード、1枚をデバッグアダプタとして使って、開発環境からデバッガで書き込んで走らせるほうが楽そう。この場合はデバッグ端子を接続する方法を考える必要があるけど。

 STBee Miniってオンボードでリセットスイッチやブートスイッチがついてて、買ったらそのままLチカできるしボタン入力も試せるから便利なのよな。スイッチが小さくて押しづらいというのはあるけど。


 BOOTSELはブート用のFlash ROM(QSPI)のSSにアクティブLowで接続されている。通常はプルアップされていて、RP2040が起動したときにSSがHighならFlash ROMから起動するが、SSがLowならRP内蔵ROMからUSB MSCを起動する、という感じになるらしい。

 ユーザープログラムからBOOTSELを読むことも可能だが、このピンはQSPIのSSだから、BOOTSELを押している間はFlash ROMからのプログラムを実行することができないので、普段使いしていいものでもなさそう。

 そのためか、BOOTSELはRasPiPicoの外部には引き出すことができない(クロックほどではないにしても、ある程度狭いパルスを通すから、変に引き出してトラブル起こされても困るからってのもあるだろうけど)。なので、外部にリセットスイッチとBOOTSELスイッチを追加して、ボタンを2個押してUSB MSCを起動する、みたいなことができない。手動でUSBを起動するなら外付けのリセットスイッチとオンボードのBOOTSELを組み合わせるしかなさそうだ。

 BOOTSELを押せばFlashからのプログラムの読み出しが止まるから、基本的にユーザープログラムは停止するはず。というわけで、WDTを設定しておけば、BOOTSELを押せば勝手にリセットされて、USBが起動する。RAMから走らせるプログラムでWDTをリセットしながら無限ループさせたりしていると機能しないけど、そういう状況を除けば、おそらくRasPiPicoを単体で使うときに、一番楽にプログラムを書き込む方法はこれだと思う。(2026/01/15)

 自分でcopy hoge.uf2 f:\とか叩く手間はあるけど、RasPiPicoのMSCは2E8A:0003として見えるから、これを検出したらファイルをコピーするスクリプトを書くとか、あるいは指定したパスで単に1秒毎にコピーを試みて、ドライブが認識されていなければ単にコピーに失敗するとか、色々工夫は考えられる。BOOTSELボタンを押したら勝手にプログラムが転送されてそれが走る、みたいなことはできるはず。

 RPには命令キャッシュ的なXIPという機能があるらしくて、こいつには16kの領域があるらしいので、それを有効にした場合はBOOTSELでQSPIを止めても小さなプログラムなら走り続けそうだけども。ぐぐってみるとXIPはデフォルトでONらしい。じゃあなんでBOOTSELで止まるんだ……



 とりあえず、Lチカは確認できたし、sleep_msの引数を変えれば周期も変わるから、開発環境も含めてそれなりに正しく動いているはず。

 VS Codeに拡張1個(+自動で入る3個)を入れるだけで使える開発環境。めちゃくちゃ簡単だなー。



追記:2026/01/15

 上述のWDTとBOOTSELでリセットするのはおそらく正常に動いていなかったので、とりあえず取り消しておく。


***


 C#でbyte hoge=(int)1;みたいな定数のダウンキャストで、キャスト先の範囲に収まる場合はエラーにならないんだな。列挙型も定数なので溢れなければ暗黙的に変換できる。一旦int型に明示的にキャストする必要はあるけど、例えばenum Hoge{foo=0x0001,bar=0x0100}があってbyte value=(int)Hoge.foo;は許可されるけど、byte value=(int)Hoge.bar;はエラーになる。byte value=(byte)Hoge.bar;もエラーになる(無理やり通すならuncheckedで囲む必要がある)。