2017/08/18

[linux][c/c++]現在時刻の取得

Linuxで時間の取得を行いたい場合がある。
今の時間だ。
time(NULL)でepoch timeを取得していたのだが、それでよいのか自信がなくなってきた。


マイコンの場合、RTCに設定した時刻が取ってこれるだけで、それ以上でもそれ以下でもない。
それに、RTCから自分で値を引っ張り出さないといけないので、epochも何も気にしようがない。

しかし、time()はきっとライブラリ側でOSが管理しているしくみに置き換えられているはず。
Linuxで時間といえばgettimeofday()だよなあ、と検索したのだが、どうもgettimeofday()は廃止予定らしい。
gethostbyname()もそんな感じだったな。。

推奨されているのは、clock_gettime()
まずは動かしてみよう。

https://gist.github.com/hirokuma/17bdf87bf3c8c6f29008e74635f9984e

2017/08/18 10:10くらいにBash on Ubuntu on Windowsで実行させると、こうなった。

$ ./tst
tv_sec=1503018649, tv_nsec=105938100

ネットでepochを現在時刻に変換するサイトを見つけてやってみると、JSTとして変換すると現在時刻になった。
dateコマンドでは、こうなる(あれこれしているうちに5分くらい経ってしまったが)。

$ date
Fri Aug 18 10:15:53 DST 2017


これは、内部ではUTCで管理していて、出力時にJSTの下駄を履かせているという考え方でよいのだろうか?
(DSTになっているのも気になるが。。。)
VirtualBoxで動かしているXubuntu16.04でも同じになったので、Bash on Ubuntuがそうしているわけではなさそうだ。


そして、epoch timeは各地の時刻ではなく、UTCで出すというのが共通の認識ということでよいのだろうか。
数字しかないので、UTCがデフォルト、のようなルールがないと困るのだけど、明示的に書いてある資料が見つからない。


オライリーの「C言語クイックリファレンス」には、

  • time()は現在のカレンダー時刻を返す
  • これは、紀元と呼ばれる
  • Unixの紀元はUTCの1970年1月1日 00:00:00

とある。
そして、「紀元」は"epoch"だから、epoch timeはUTCということでいいんじゃないかな。
うんうん、そうしておこう。

tig

ファイル履歴管理にgitを使っているのだが、未だにコマンド慣れしていない。
慣れない操作で失敗するのも嫌なのでGUIのツールを使っていたのだけど、最近はクラウド上につくったVMを扱わんといかんことも多くなり、なるべくgitをコマンドラインで使うようにしている。


でも、ある程度はGUIっぽく表示してくれた方が見やすいじゃないか。
そう思って探していると、tigというコマンドが見つかった。

gitを逆に並べたtigだが、コマンドラインで動かすツールながらも、GUIっぽく出してくれる。
なんというか、FDみたいなコマンドになるのかもしれん。
・・・FDってWindowsのみだったかも。


tigの操作は、ちょっとviっぽい。
カーソルの移動がそうだからか。


使うのは、ステージに挙げたりcommitしたりするところが主だ。
git addするとき、ファイルのパスをいちいちコマンドで書くのが面倒なのだよ。

tigを立ち上げて、sを押して更新したファイルの一覧を出し、uを押してcommitしたいものをステージに上げる。
上げ終わったら、大文字のCを押してcommitするエディタを起動する。
うちではnanoが立ち上がった。

historyなんかも重たくなく見られるので、使いこなせると便利そうだ。


ただ、最近はtigする気力も無いので、VirtualBoxでGUIが動く状況であればVisual Studio Codeを使っている。
差分なんか見やすいしね。

2017/08/17

[勉]MIPI

Xilinxからメールが来た。

MIPI D-PHY 搭載のザイリンクス UltraScale+ デバイス

MIPI?
初めて聞く単語なので、これは調べねばなるまい。


Mobile Industry Processor Interfaceの略らしい。

デバイス古今東西(17) ―― 撮像デバイスの変遷と次世代標準インターフェースMIPI規格|Tech Village (テックビレッジ) / CQ出版株式会社

「モバイル機器向け」なのだそうだ。
記事が2010年なので、7年前にはすでにあった規格ということになるな(2003年らしい)。

シリアル通信というと、UART, I2C, SPI, USBなどなど、たくさんある。
そこに連なるようなものなのか、


こちらが、mipi allianceのページ。
https://www.mipi.org/

仕様書をちょっとくらい見てみようかと思ったけど・・・数が多くて止めた。
Specifications Overview

カテゴリーだけで、これだけある。

  • Audio
  • Camera and Imaging
  • Chip-to-Chip/IPC
  • Control and Data
  • Debug and Trace
  • Display and Touch
  • Physical Layers
  • Software Integration

まあ、NFC Forumの規格もたくさんあったし、そういうものかもしれん。


これで終わってしまうのはさすがに悔しいので、Xilinxのメールで紹介された規格くらい調べておこう。

「MIPI D-PHYを搭載」

mipi allianceの説明ページは、こちら
PHYなので、物理層なのだろう。
スマートフォンのカメラやディスプレイ向きのようだ。

技術的な内容は出てこなかった。


MIPI ‐ 通信用語の基礎知識

同期式とのこと。
ソース同期と書いてあるので、クロック線は持たず、データ自体がクロックと同じ意味を持つということか。
マンチェスターみたいな感じかな?
マンチェスターだと1bitを2データで表すが、差動だと1データ分の時間で2データを表現できるので、倍の速度になるのかも。
上限が1Gbpsとなっているので、なにか技術的に上限が発生するのだろうが・・・そこまではわからんな。


これで終わろうと思ったが、最後に見たページではもう少し情報が載っていた。
前田真一の最新実装技術あれこれ塾:第47回 内部ディスプレイ接続規格 (4/4) - MONOist(モノイスト)

高速モードは1.5Gbpsみたいだ。
そして、予想と違ってクロック線があり、ビデオ信号だとレーンを複数用意するようだ。
下手に予想するもんじゃないな。

2017/08/11

hexdumpで16進数を出力したい

バイナリファイルをソースコードに埋め込みたいことがある。
画像データを配列として使いたい場合などだ。

ファイルから読み込んで%02xなどで出力させるだけなのだが、いちいちコマンドを作るのも面倒だ。
hexdumpというコマンドがあるのでやってみたが、オプションを使えばなんとかいけそうなものの、よくわからん。
だいたい、なんで2バイトごとに出すのがデフォルトなんだ?


と、コマンドに文句を言ってもしょうがないので、オプションを調べよう。

hiro99ma blog: hexdumpのフォーマット

0xを付けた出力をしたい場合は、これでよい。
これは8バイトごとに改行しているので、8/1になっている。

$ hexdump -e '8/1 "0x%02x, " "\n"'  abcdef.bin


pythonで、ひたすらずらずら並べた文字列を作りたいこともある。

$ echo "$(hexdump -e '1/1 "%02x"' abcdef.bin)"

echoはなくてもよいのだけど、改行を付加しないので、コマンドラインで実行すると見づらかったのだ。


で、hexdumpを16進数の1桁ダンプ以外で使うことが無さそうなので、aliasに登録しようとした。

alias hexdump='hexdump -e '\''1/1 "%02x"'\'

いやあ、こんなに難しいとは。。
シングルクオーテーションで全体を囲む中にシングルクオーテーションを入れたい場合は、

  • 一度シングルクオーテーションを閉じる
  • \'を付ける
  • シングルクオーテーションを始める

ということをせんといかんそうだ。

青文字がシングルクオーテーションで囲んだ範囲、赤文字がエスケープしたシングルクオーテーションとなる。

alias hexdump='hexdump -e '\''1/1 "%02x"'\'


aliasをシングルクオーテーションで囲むのは、スペースも含めて入れてほしいという場合だけのはず。
まあ、これで登録しても、aliasコマンドで見ると

alias hexdump='hexdump -e '\''1/1 "%02x"'\'''

なんだけどね。

2017/08/07

[c/c++]lmdbでの検索

たまにはFPGAを離れて、DBのことをやってみるのもよいだろう。
そうだな、lmdbなんてどうだろうか?


最後にlmdbのことをやったときは、付属サンプルのmstest.cを見ていくだけだった。
今回は、KEYから検索したり、VALUEから検索するときのことを考えよう。



今のところ、私のlmdbに対するイメージはこうだ。

image


mdb_env_create()で1つのENVを作り、mdb_env_open()する。
ENVからmdb_txn_begin()でTXNを開始し、同じトランザクション内で処理したいものをmdb_dbi_open()でDBIを開く。
あとは、TXNとDBIのセットでmdb_put()したりmdb_get()したり。
終わってトランザクションを確定させたいなら、mdb_txn_commit()してmdb_dbi_close()。
変更したものを破棄するなり、読込むだけで保存するものが無ければ、mdb_txn_abort()だけ。
mdb_put/get()だけでなく、cursor系のAPIもある。


さて、検索するには、どのAPIを使うのがよいのか。。。

いまのところ、私の認識はこうだ。

  • KEYが指定できる場合は、mdb_get()
  • それ以外は、cursor系APIでDBIの中を全部探す

SQLではないので、自分でやるしかないだろう。
mdb_cmp()で比較するようなことができるのかと思ったが、関係なさそうだ。


自分でやるしかないので、全部KEY-VALUEに突っ込むだけではなく、DBIをうまいこと分散させるのもよいだろう。