Raspbian、というのが私が使っているOSの名称のようだ。
SSHが使えるのが便利だから、これを使っていくことにしよう。
「画面に何か出してみよう」と書いたものの、Raspbianが入ったSDカードを入れると、HDMIから文字が出力されるので、既に何かは出ていると思う。
終了~。
・・・では面白味がないので、自分の意思で何か出してみることにする。
きっと、画面出力用に何かライブラリがあると思うが、ここは基本に返ってフレームバッファを使うことにする。
私の認識では、フレームバッファってのはVRAMみたいなもので、ここにデータを書くとOSというかドライバが上手に画面へ転送してくれるというものだ。
では、試しに。
$ ls /dev/fb*
/dev/fb0
フレームバッファは/dev/fb0みたいだ。
ここに何か転送してみる。
/etc/bash.bashrcというファイルがあるので、これを使おう。
$ cat /etc/bash.bashrc
これをたたくと、コンソールに文字がずらずら出たと思う。
では、これをフレームバッファに出力してみよう。
$ cat /etc/bash.bashrc > /dev/fb0
画面の左上に、ゴミが表示されたんじゃないかと思う。
bash.bashrcの中身がフレームバッファに書き込まれたので、それをドライバが出力してくれたのだ。
bash.bashrcはテキストファイルだけれども、それはテキストかどうかを人間が決めただけであって、コンピュータからすると「データが入ったファイル」に過ぎない。
だから、ゴミっぽいものが表示されるのだ。
じゃあ、画像ファイルならよいかというと、そうでもない。
「/usr/share/lxde/wallpapers/lxde_green.jpg」というファイルがあると思うので、それで試してみよう。
$ cat /usr/share/lxde/wallpapers/lxde_green.jpg > /dev/fb0
ゴミの量が増えたと思う。
画像ファイルも、所詮は取り決めた形式で収められたデータに過ぎず、コンピュータからすると「データが入ったファイル」なのだ。
じゃあどうしたら思い通りに表示できるかというと、コンピュータが期待する形式でデータを出力すればよい。
画面にゴミが出ていると思うので、一度クリアしておこう。
$ clear
では、もう一度bash.bashrcをコンソールに出力してみよう。
$ cat /etc/bash.bashrc
画面に文字がずらずら出たことだろう。
では、今度はフレームバッファの内容をファイルに保存してみよう。
$ cat /dev/fb0 > screenshot.raw
$ ls -l screenshot.raw
-rw-r--r-- 1 pi pi 3548160 Oct 13 01:16 screenshot.raw
うちだとこんな感じになったが、ファイルサイズは人によって違うと思う。
では、もう一度画面をクリア。
$ clear
そして、さっきのファイルをフレームバッファに出力。
$ cat screenshot.raw > /dev/fb0
bash.bashrcの出力などが画面に表示されたんじゃないかと思う。
フレームバッファの出力していた内容をファイルに保存し、それをもう一度出力し直したから当然と言えば当然なのだが、そういうことなのだ。
もうちょっとだけ実践をしておこう。
$ fbset
mode "1680x1050"
geometry 1680 1050 1680 1050 16
timings 0 0 0 0 0 0 0
rgba 5/11,6/5,5/0,0/16
endmode
これがうちの画面サイズだ。
では、さっきのscreenshot.rawファイルサイズ(3548160byte)を考えていこう。
きっと、画面サイズの定数倍になってるはずだ。
3548160 / 1680 = 2112
・・・ならんやん。
私の予想では、さっきのfbsetの結果に「16」って出てるから、1ピクセルが16bit=2byteなんだろうと思ったのだ。
だから、1680 x 1050 x 2、になるはずだったのだ。
うーん。
調べてみよう。
Raspberry Piのいいところは、セルフコンパイルができるところだな。
調査にはもってこいだ。
fbtest.c
#include <stdio.h>#include <string.h>
#include <sys/types.h>#include <sys/stat.h>#include <fcntl.h>#define FB "/dev/fb0"
#define WIDTH (1680)#define PP (2)int main(int argc, const char *argv[]){int fb;
int loop;
const data[] = { 0xff };
fb = open(FB, O_RDWR);if(fb == -1) {
perror("cannot open fb.");
return -1;
}for(loop = 0; loop < WIDTH * PP; loop++) {
write(fb, data, 1);}return 0;
}
$ gcc -o fbtest fbtest.c
$ ./fbtest
うん、画面の一番上に、白い線がぴーっと1ラインだけ引かれた。
何をするプログラムだったかというと、0xFFというデータを 1680x2バイト分フレームバッファに書き込むものだったのだ。
もし1ピクセルが2バイト以上であれば、線は右端まで届かずに終わっただろうし、横幅が1680ピクセルじゃなかったら、はみ出して次の行に表示されるなり短いなりしただろう。
じゃあ、次。
#include <stdio.h>#include <string.h>
#include <sys/types.h>#include <sys/stat.h>#include <fcntl.h>#include <unistd.h>#define FB "/dev/fb0"
#define WIDTH (1680)#define HEIGHT (1050)#define PP (2)int main(int argc, const char *argv[]){int fb;
int loop;
const data[] = { 0xff };
const empty[] = { 0x00 };
fb = open(FB, O_RDWR);if(fb == -1) {
perror("cannot open fb.");
return -1;
}/*
for(loop = 0; loop < WIDTH * PP; loop++) {write(fb, data, 1);}*/for(loop = 0; loop < HEIGHT; loop++) {
int loop2;
for(loop2 = 0; loop2 < PP; loop2++) {
write(fb, data, 1);}lseek(fb, (WIDTH - 1) * PP, SEEK_CUR);}return 0;
}
左端に白い線が出たと思う。
2byteだけ0xFFを書き、(横幅-1) x 2byteだけスキップ、という動作を高さ分だけ繰り返すプログラムだ。
これはこれで、間違っていなさそうだ。
つまり、/dev/fb0で保存したサイズが実画面よりも大きい、ということでいいのかな。
横幅は変わらなさそうだから、
3548160 / 1680 / 2 = 1056
つまり、実画面は1050ピクセルだが、保存は1056ピクセル分行っている、ということか。
あるいは何か別の用途で使ってるメモリなのか。
まあ、あまり気にしないでおこう。
0 件のコメント:
コメントを投稿
コメントありがとうございます。
スパムかもしれない、と私が思ったら、
申し訳ないですが勝手に削除することもあります。
注: コメントを投稿できるのは、このブログのメンバーだけです。