バイナリのレジストリ

regコマンドを使って
以前、HDDが死んで、HDDの入れ替えを行ったPCのソフトが不調になった。古いHDDの中身は取り出していたのだが、ソフトの部分を置き換えても、レジストリが違うので動かない。レジストリはバックアップしていなかったのだが、システムファイルがあるので、そこからレジストリの情報を取り出せないかと思って調べたら、できるようだ。 レジストリは、windows/system32/config内に保存されているが、バイナリなので、そのままでは読めない。レジストリをいじるためには、regeditを良く使っていたが、組み込まれていないレジストリはこれでは扱えない。XP以降ではregというツールを使えるようになっており、これを使うとバイナリファイルに保存されているレジストリを取り出すことができる。コマンドプロンプトでバックアップされたバイナリのレジストリファイルがあるところに行って、reg load HKLM\Temp_software softwareとすると、System\Temp_softwareというレジストリの下に、softwareというファイルに保存されていたレジストリが展開される。これをregeditを用いて取り出せば良い。注意しないといけないのは、regeditを立ち上げていると、エラーが出てしまうことである。このせいで、しばらく悪戦苦闘してしまった。 レジストリを入れ替えて、ソフトのファイルを古いHDDのものに入れ替えたら、無事に動くようになった。

Read more...

xvkbdを使ってみた

raspberry pi用の仮想キーボードのカスタマイズ raspberry piにLCDを取り付けたが、まだまだ使える状態に無かったので、少しいじってみた。タッチパネル用の仮想キーボードとしては、matchbox-keyboardを入れていたが、カスタマイズが難しそうだったので、xvkbdを使うことにした。デフォルトでコンパクトなタイプが立ち上がるように、.local/share/applications/xvkbd.desktopを編集して、以下のようにした。 [Desktop Entry] Name=xvkbd Exec=xvkbd -compact -modal Icon=xvkbd Type=Application Comment=Virtual Terminal=false Categories=Utility; ここで、問題になるのが、バックスペースである。コンパクトモードにすると、デリートキーしか無くなって、直前の文字を消すためには、矢印で戻ってからデリートを押さなければならず、面倒である。そこで、/etc/X11/app-defaults/XVkbd-commonを編集して、設定を変える。まず、二つのキーのサイズを入れ替える。 !XVkbd*BackSpace.width: 75 XVkbd*BackSpace.width: 45 !XVkbd*Delete.width: 45 XVkbd*Delete.width: 75 そして、実際のキーの配置を入れ替えるために、このファイルの最後に以下を加えた。 xvkbd.NormalKeys: \ F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 Delete \n\ Escape 1 2 3 4 5 6 7 8 9 0 - = \\ ` \n\ Tab q w e r t y u i o p [ ] BackSpace \n\ Control_L a s d f g h j k l ; ' Return \n\ Shift_L z x c v b n m , .
Read more...

古いwineのインストール

wineとdebianの相性
昨日debian stretchにwine0.9.25を入れるのに失敗したので、仕方なく古いdebianを使うことにした。選んだのはdebian lennyの5.0.10 i386である。CDイメージからインストールして、まずは/etc/apt/sources.listに

deb http://archive.debian.org/debian/ lenny main
deb-src http://archive.debian.org/debian/ lenny main

を追加して、

aptitude update
aptitude install build-essential flex bison libx11-dev libxext-dev

とする。 ここで、wine 0.9.25をコンパイルするのだが、何も工夫せずに./tools/wineinstallを実行するだけで、インストールできた。問題のソフトも無事に動く。ただ、シリアルのエラーは出ている。このソフトが動くか動かないかが何で決まっているのか、さっぱり分からない。タイミングかな?

Read more...

i386をインストール

wineとdebian stretch

古い測定システムのPCが死亡したので、別のPCを測定用に立ち上げようとして苦労している。そのシステムは2012年の2月に立ち上げて、一度PCが死んだけど、近い世代のPCにHDDを載せ替えて使っていたが、そのPCも死んで、同じ世代のPCが見当たら無かったので、仕方無く別のPCにシステムをインストールしようとしている。

このソフトは、windows95かNT4.0でしか動かないらしく、シリアルポートも使っている。これをwineで動かしていたのだが、wineのversionによって動かないことが分かっている。最新のwineで動いてくれないかなと思って試してみたが、

fixme:comm:set_queue_size insize 4096 outsize 4096 unimplemented stub

と出て、装置が認識されなかった。また、昔の記録によると、0.9.25で動かしていたので、これをインストールしようとしたが、64ではコンパイルできなかった。そこで、OSをi386のdebianにしようと思って調べたら、つい最近新しくstretchが出ていたので、このi386をインストールすることにした。

とりあえず、isoイメージを落として、CDRに焼いて、LXDEをインストールした。aptitudeとwineのコンパイルに必要なbuild-essential flex bison libx11-dev libxext-devをインストール。そして、https://dl.winehq.org/wine/source/0.9/からwine-0.9.25.tar.bz2を取ってきて展開する。2012-02-09のところに書いてあるように、ファイルを変更して、./tools/wineinstallを実行する。しかし、libs/port/interlocked.cのところでエラーが出る。tools/wineinstallを

CONFARGS="CFLAGS=-fgnu89-inline"

と変更して、config.cacheを削除して、コンパイルすると、少し進んでtools/wrc/parser.yでエラーになる。このファイルに

#define YYLEX		yylex()

を付け加えたら、また少し進んだ。今度は、いくつかの関数が重複して定義されていますと言われる。これは、おそらくinterlocked.cのところのエラーを回避したために起こっているようだ。 ううん、難しいな。

Read more...

raspberry piのlcd

3.5inchのlcd
aliexpressでraspberry pi用のlcdが安く売っていたので、買ってみた。3.5inchでタッチパネルもついている。届いたものを見てみたら、メーカーも何も分からないので、いろいろと試行錯誤しながら設定してみた。結果としては、WaveShareのdriverで動いたので、WaveShare製なのかも知れない。

ここの情報を見ながら設定を行った。必要なドライバーをdownloadして、展開する。

wget http://www.waveshare.com/w/upload/7/74/LCD-show-170309.tar.gz
tar xvf LCD-show-*.tar.gz
説明を読むと、新しいraspbianでは、LCD-show/boot/config35.txtの中のdtoverlay=ads7846の行をコメントアウトする必要があるようだ。そして、LCD35-showを実行すると、LCDが表示されるようになり、LCD-hdmiを実行すると、hdmiに表示するようになる。/boot/cmdline.txtと/boot/config.txtは書き換えられるので、backupしておいた方が無難だろう。 タッチスクリーンもすぐに使えるようになった

GUIに関しては、liteから手でインストールした。

sudo apt-get install --no-install-recommends xserver-xorg
sudo apt-get install --no-install-recommends xinit
sudo apt-get install raspberrypi-ui-mods
キーボード入力もできるようにmatchbox-keyboardも入れた。

しかし、3.5inchは小さいので、その画面だけで何かをするのは、なかなか難しいそうだ。

Read more...

DAコンバーター

MCP4922とarduino UNO

DACとしては、以前はMCP4922を使っていたが、最近は MCP4726を使うようになった。前者のinterfaceはSPIで、後者はI2Cである。arduinoでMCP4922を使ったことが無かったので、プログラムを書いてみた。

arduino UNOのSPIは、SS(10), MOSI(11), MISO(12), SCK(13)の4pinを使って行なわれる。今回は、ICにコマンドを送るだけなので、MISOは使わない。また、MCP4922のLDACは9pinに、SHDNはVccに接続した。SPIの使い方は、SPI.hを組み込んで、モードをセットして、書き込む。

serialからDAのデータを受け取るときに、どのような処理をしようか迷ったが、parseIntを使うと、数字をintに変換してくれるので、正の数だとchAを、負の数だとchBにデータを送るようにしてみた。

#include <SPI.h>
#define LDAC   9
void setup(){
  Serial.begin(9600);
  pinMode(LDAC,OUTPUT);
  SPI.begin();
  SPI.setBitOrder(MSBFIRST);
  SPI.setClockDivider(SPI_CLOCK_DIV8);
  SPI.setDataMode(SPI_MODE0);
}
void loop() {
  if(Serial.available()>0){
    int i=Serial.parseInt();
    digitalWrite(LDAC,HIGH);
    digitalWrite(SS,LOW);
    if(i<0){i=-i-1;i|=0x8000;}
    i|=0x3000;
    SPI.transfer(i >> 8);
    SPI.transfer(i & 0xff);
    digitalWrite(SS,HIGH);
    digitalWrite(LDAC,LOW);
    delay(500);
  }
}
Read more...

ADコンバーター

MCP3425とarduino UNO

最近はADCとしては、MCP3425をよく使っている。内部標準電圧を使用するので参照電圧は不要だし、差動入力で負の電圧も読めるし、i2cなので通信に必要な信号の数が少ないというという利点がある。2.048Vまでの電圧を符号を含めて16bitでADCでき、小さな電圧に対しては8倍まで増幅して読むことも可能である。これをarduino UNOで使うときに、符号の部分でつまづくことがあるので、メモをしておこうと思う。

配線は非常に単純で、電源と測定する電圧とSDA,SCLをつなげば良い。pull upはAVRがしてくれるので、気にしなくても良い。ただし、SDAとSCLはそれぞれA4とA5につながっているので、それらのピンは使えなくなる。

下のプログラムでは、i2cで通信するときには、アドレス0x68を指定して、レジスタに0x88を書き込んでいる。これは、one shot modeで 16bit増幅なしで測定を開始するということを意味する。このモードでは1/15秒で測定が終了する。測定が終了したかを調べることもできるが、その通信によるノイズが入らないように、十分に時間が経ってから、データを読み出す。Wire.read()で1byteのdataを読み出すが、この関数の型はintである。arduino UNOでのintは16bitなので、符号を気にせずに計算する式で、符号もうまく処理できるようだ。何の工夫も無いコードであるが、一応符号も考慮しているのである。しかし、16bit以外のモードではこうは行かないので、注意しなければならない。

#include <Wire.h>
void setup(){
  Wire.begin();
  Serial.begin(9600);
  delay(100);
}
void loop(){
  Wire.beginTransmission(0x68);
  Wire.write(0x88);
  Wire.endTransmission();
  delay(100);
  Wire.requestFrom(0x68,2);
  Serial.println(Wire.read()*256+Wire.read());
  delay(500);
}
Read more...

backportを使って

jessieのkicad
kicadを使って回路を考えていたが、開こうとすると、“some files could not be found"というエラーが出て、うまく行かない。いろいろと調べたら、debian jessieだと、backportのkicadを使うと良いらしい。/etc/apt/source.listに

deb http://httpredir.debian.org/debian jessie-backports main contrib non-free

を加えて、

aptitude update
aptitude -t jessie-backports install kicad

として、インストールした。でも、前のバージョンで作ったやつは、動かないようなので、作り直しだ。

Read more...

beamerのエラー

図の取り込みとbb
beamerを使ってtexでコンパイルしようとしたら、図の取り込みのところでエラーが出る。bbが無いから作ろうとしているが、すでにきちんと作ってある。こういうときは、dvipdfmxオプションなどが抜けていることが、今回はきちんと指定してある。エラーメッセージをよく見て、

platex --shell-escape tempj

としたらうまくいった。

Read more...

同じアドレスを持つデバイス

アドレスの重複するデバイスとI2Cで通信 I2Cでは,複数のデバイスと二本の信号線だけで通信することができます.しかしそれには,アドレスが重複していないという条件が必要です.同じアドレスのデバイスが二個あり,これらと通信するためには,二系統のI2Cを使うか,切り替え機能のあるICを使って,通信を実現することができ,そうしている人が多いようである. ICを使って切り替えるとしても,デバイスを選択するために信号線が必要なので,その信号線を使って通信を行なってしまえば,新たなICを使わないでも二個のデバイスと通信ができる.この際,SCLは共通に使って,SDAをそれぞれのデバイスに一本ずつ使えば,三本の信号線で二個のデバイスと通信できる.逆に,クロックが送られなければ通信は行なわれないと考えて,SDAを共通にして,SCLをそれぞれのデバイスに割り当てることもできるだろう.前者の場合には,クロックが共通なので,同時に二個のデバイスと,同じバイト数の通信を行なうことになる.後者の場合には,別々のタイミングで,それぞれのデバイスと通信することになる. 上記の考えを拡張すると,アドレスが重複しているn個のデバイスとの通信は,(n+1)本の信号線を使うと実現できることが分かる.ほぼ同じデータをやりとりする場合には,SCL共通の方が一度に通信できるという点で優れており,送受信するデータ数やタイミングがデバイス毎に違う場合には,SDA共通が良いだろう. arduinoを使って,SCL共通でこれを実現するためのプログラムを試しに書いてみた.mulWireBegin()で初期化を行い,mulWireBeginTransmittion()とmulWireWrite()とmulWireEndTransmittion()を使って,デバイスに送信する.受信は,mulWireRequestFrom()とmulWireRead()とmulWireEndRequest()を使って行なう.バッファなどは無く,これらのコマンドの実行と同時に通信が行なわれるので,受信のときにもその終了操作を行なうコマンドが必要になる点が,通常のarduinoのI2Cのコマンドと異なる.参考にソースを載せておくが,まだ動作確認を行なっていないので,動作は保証できません. #define MulWireDelay 6 // 6 micro second 100kHz #define mwNUM 2 #define mwSCL A5 uint8_t mwSDA[mwNUM]={A4,A3}; uint8_t mwadrs[mwNUM]={0x68,0x68}; void mulWireBegin(){ char i; pinMode(mwSCL,OUTPUT); for(i=0;i<mwNUM;i++){pinMode(mwSDA[i],OUTPUT);} digitalWrite(mwSCL,HIGH); for(i=0;i<mwNUM;i++){digitalWrite(mwSDA[i],HIGH);} delay(10); } void mulWireBeginTransmission(uint8_t *adrs){ char i; for(i=0;i<mwNUM;i++){digitalWrite(mwSDA[i],LOW);} delayMicroseconds(MulWireDelay); digitalWrite(mwSCL,LOW); mulWireData(2,adrs); //*2 } void mulWireRequestFrom(uint8_t *adrs){ char i; for(i=0;i<mwNUM;i++){digitalWrite(mwSDA[i],LOW);} delayMicroseconds(MulWireDelay); digitalWrite(mwSCL,LOW); mulWireData(3,adrs); //*2+1 } void mulWireEndTransmission(){ char i; for(i=0;i<mwNUM;i++){digitalWrite(mwSDA[i],LOW);} delayMicroseconds(MulWireDelay); digitalWrite(mwSCL,HIGH); delayMicroseconds(MulWireDelay); for(i=0;i<mwNUM;i++){digitalWrite(mwSDA[i],HIGH);} } void mulWireEndRequest(){ mulWireEndTransmission(); } uint8_t mulWireWrite(uint8_t *data){ mulWireData(0,data); } uint8_t mulWireData(char mode,uint8_t *data){ // mode: 0:raw, 2:*2, 3:*2+1 char i,m,a; uint8_t temp; m=(mode1)?
Read more...