WindowsでGUI版gitクライアントのSmartGitを使えるようにする


今までSVN + RapidSVNを使用していたのですが、GitのリポジトリにアクセスしたかったのでGitのクライアントのインストールをしてみました。

SVNと同様gitも基本はコマンドラインでの操作ですが、コマンド操作だけだと面倒なので、GUIも欲しいところです。調べてみたところWindowsでのgitフロントエンドはSmartGitがよさげらしいです。


SmartGitは商用利用は有償(1ライセンスで7000円ぐらい)ですが、非商用で使う場合ならFreeです。
非商用でも機能制限は無いので、快適に使用できます。

仮に将来商用で使う事になったとしても、それ程高くないので今回はSmartGitを使ってみる事にしました。


git+SmartGitのセットアップの手順は以下の通りです。

コマンドライン版git(msysgit)のインストール


SmartGitを使用するには、コマンドライン版のgitが必要となるので事前にインストールしておきます。
WindowsでGitを使うならmsysgitを使用すると、UTF-9をサポートしてたりして何かと良いらしいです。


msysgitは、下記のサイトからダウンロードします。
Downloads – msysgit – Git for Windows – Google Project Hosting



ダウンロードしたexeを実行します。
現時点での最新は、Git-1.8.0-preview20121022.exeでした。


Nextをクリックします


ライセンス(GPL)の確認です。



インストール先です。
このパスは、後でSmartGitをインストールする時に使うので控えておきます。



インストールするコンポーネントです。
デフォルトでも良いのですが、今回は以下のチェックをはずしました(個人的に不要だったので)。

チェックを外したもの(2つ)
Additional icons -> In the Quick Launch
Associate .sh files to be run with Bash




スタートメニューの登録について。デフォルトにしときます。



PATHの設定です。

上から順に、以下の設定になります。

GitをBashだけで使用するう
    これは最も保守的な選択で、システムに変更を加えた句内場合に使用します。
    環境PATHを変更は行われません。
 
GitをWindowsのコマンドプロンプトから使用する
    これは、他のアプリと競合しないと思われる、安全なオプションです。
    セットアッププログラムはGitだけを環境変数PATHに追加します。
    GitをCygwinと同時に使用する場合に使用する際は、このオプションを使用します。
 
Gitと幾つかのUnixコマンドををWindowsのコマンドプロンプトから使用する
    Gitと同梱されたUnitコマンドを環境変数PATHに追加します。
    注意:このオプションを選ぶとPATHが書き換わるので,
         Windows標準のfind.exe/sort.exeが使用できなくなります。
         この意味が分かる人だけ、このオプションを使用してください!!



Gitは内部でUnixのコマンドを使用するため、インストール先フォルダにUnixコマンド互換のexeをコピーします。3つ目のオプションは、これらのコマンドをPATHに入れるかという選択肢です。

セットアップを行っているPCは、Unixコマンド郡を別途入れてある環境のものを使ってます。
競合すると面倒なので、今回は2番目のオプションを選択しました…



改行文字を自動変換するかの指定です。こちらも3つの選択肢が有ります。


下記の説明で、Windowsスタイルの改行コードはCR+LFで、UnixスタイルはLFの事です。
(ってgitをinstallしようとしてる人にとっては常識でしょうけど…)
3つのオプションの意味は、以下の様な感じです。

チェックアウト時Windowsスタイル・コミット時Unixスタイルの改行コード
    チェックアウト時にLFの文字コードをCR+LFに変換します。
    コミット時にCR+LFのコードをLFに変換します。
    クロスプラットフォーム向けのプロジェクトをWindowsで使用するときのお勧めです。
    (conre.autocrlfがtrueにセットされます)
 
 
チェックアウト時無変換・コミット時Unixスタイルの改行コード
    チェックアウト時は文字コードを変更しません。
    コミット時にCR+LFのコードをLFに変換します。
    これはUnix環境での設定にお勧めです。
    (conre.autocrlfがinputにセットされます)
 
 
チェックアウト時無変換・コミット時無変換の改行コード
    チェックアウト/コミット時に文字コードを変更しません。
    このオプションはクロスプラットフォーム向けのプロジェクトにはお勧めしません。
    (conre.autocrlfがfalseにセットされます)



“not recommended”と書かれていますが、自分で管理したいので無変換(as is)にしておきます。

これで、gitのセットアップは完了です。



試しにコマンドラインからgitと打ってみて実行できることを確認しておきます。


インストールフォルダのbinをチェックしてみると、確かに色々Unix-likeなコマンドが入ってるみたいです。





SmartGitのインストール

コマンドライン版のgitが用意できたら、次はSmartGitです。

下記のサイトからダウンロードします。
http://www.syntevo.com/smartgit/download.html



zipを展開して、セットアップを実行します。





インストールのウィザードはシンプルなんで、適当に選んでいけばOKです。
(今回は全てデフォルトにしました)











ウィザードが終わったら、デスクトップのアイコンをダブルクリックします。




ライセンスの確認です。



使用形態の確認です。
上から順に、”商用版の評価目的、商用版のライセンス登録、非商用利用”です。
今回は一番下の非商用利用を選択しました。



git.exeの有る場所の指定です。
これは先ほどインストールしたmsysgitの場所を指定します。


SSHクライアントの指定です。
今回はSmartGitのSSLクライアントを使用するので、下側を選択します。


ユーザー情報です。
設定内容は.gitconfigに保存されるらしいです。


ホスティングサーバの指定です。
GitHub等を使用していて、アカウントを持っている場合は、下側を選択します。
今回は上側の”I don’t use…”を指定しました。


Finishをクリックして完了です。



この後、”何をしたい?”的なダイアログが出ますが、一旦Closeを押します。


SmartGitのメイン画面が表示されました。


これでインストールは完了です。

次回は、SmartGitを使用して公開されているgitリポジトリからファイルを取得(clone)してみます。
SmartGitを使ってAndroidのソースを取得する

[Android]EditTextの入力文字で改行を入力不可にさせる

Androidのテキスト入力UIであるEditTextは、デフォルトだと入力文字列に改行を入れることが可能となっています。
これを改行不可にするには、setInputType()メソッドで入力可能文字を指定します。

// 設定項目の入力欄
EditText edtMessage;
edtMessage = new EditText( this );
edtMessage.setInputType( InputType.TYPE_CLASS_TEXT );	// 改行を認めない
edtMessage.setText( "hello world" );




レイアウトをxmlで指定している場合は、タグに以下の属性を追加します。

android:inputType="text"



上記の設定を行い、文字入力中に改行を指定しようとすると、入力の確定と見なされます。

[Android]IntentでEditTextの値を画面間で渡せない時にチェックすること

例えば、子画面で入力された値を親画面に戻す場合の処理を考えてみます。

子画面側の処理

public class ChildActivity extends Activity {
 
    EditText edtMessage;
 
    ...中略...
 
    /* OKボタンがクリックされた時のリスナ */
    private class BtnOkClickListener implements OnClickListener {
        @Override
        public void onClick(View v) {
 
            Intent it = getIntent();
            it.putExtra( "Key_Message", edtMessage.getText() );
            setResult( RESULT_OK, it );
 
            finish();
        }
    }    
}



これを以下のように、Intent#getStringExtra()で取ろうとしても上手くいきません
nullが返ってきてしまいます。

public class ParentActivity extends Activity {
 
    /** ボタンクリック時のハンドラ(子画面に遷移)
     */
    private class BtnAddAlermClickListener implements OnClickListener {
        public void onClick(View v) {
            Intent it = new Intent( getApplicationContext(), ChildActivity.class );
            startActivityForResult( it, REQ_INPUT_MSG );
        }
    }
 
    /** 子画面から戻ってきた時のハンドラ
     */
    @Override
    public void onActivityResult( int reqCode, int result, Intent it ) {
        if ( reqCode == REQ_INPUT_MSG && result == RESULT_OK ) {
            String msg = it.getStringExtra( "Key_Message" );
            txtMessage.setText( msg );
        }
    }
}



この理由は以下の通りです。
edtMessage.getText()は戻り値としてStringではなくEditableオブジェクトを返します。
ですので、it.putExtra()で管理されるvalueはEditableクラスのインスタンスです。


一方、it.getStringExtra()では、キーに対応するvalueがStringクラスで無い場合はnullを返す仕様となっています。この為、変数msgにはnullがセットされてしまいます。


この問題を回避するには、セット時にtoString()で明示的にStringオブジェクトを格納します。

public void onClick(View v) {
 
    Intent it = getIntent();
    it.putExtra( "Key_Message", edtMessage.getText().tostring() );
    setResult( RESULT_OK, it );
 
    finish();
}

[Android]ListViewで,一覧にアイコン付きのメッセージを表示

前回はListViewの各要素に対して、文字を表示させました。
ボタンがクリックされるたびにListViewに項目を追加させる

今回はこれを少し発展させて、アイコン付きの文字表示にします。

今回作るプログラムの実行結果はこんな感じです。


一覧の明細に対する見た目を変更する方法は複数有りますが、今回はアダプタクラスを作成する方法で実装してみます。



画面のActivityクラス側ですが、変更箇所は1つだけです。

変更前

protected void onCreate(Bundle savedInstanceState) {
    ...
    lstAlert = new ListView( this );        
    adapter = new ListArrayAdapter( this, alertList );
    lstAlert.setAdapter(adapter);
 
    ....
}


上記のListArrayAdapterを今回新規に作成するクラスに差し替えます。


変更後

    adapter = new AlertListArrayAdapter( this, alertList );





で、実際のAlertListArrayAdapterクラスは、以下の様な感じになります。

package com.example.test1;
 
import java.util.List;
 
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Color;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
 
public class AlertListArrayAdapter extends ArrayAdapter<String> {
    private List<String> itemList;
 
    /**
     * コンストラクタ
     * @param context   コンテキスト情報
     * @param itemList  表示させる項目の一覧
     */
    public AlertListArrayAdapter( Context context, List<String> itemList ) {
        super( context, -1, itemList );
        this.itemList = itemList;
    }
 
 
    /** 指定されたpositionを表示させるviewを取得する
     */
    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        Context ctx = getContext();
 
        //------------------------------------------------------
        // 初めて表示する項目の場合はViewオブジェクトを作成する
        //------------------------------------------------------
        if ( convertView == null ) {
            Bitmap clockIconBmp;
 
            LinearLayout layout = new LinearLayout( ctx );
            layout.setPadding( 10, 10, 10, 10 );
            layout.setBackgroundColor( Color.WHITE );
 
            convertView = layout;
 
            // 時計のアイコンを左に表示
            ImageView imgIcon = new ImageView( ctx );
            clockIconBmp = BitmapFactory.decodeResource(ctx.getResources(), android.R.drawable.ic_lock_idle_alarm ); 
            imgIcon.setImageBitmap( clockIconBmp );
 
 
            // 左に説明のテキストを表示
            TextView txtMsg = new TextView( ctx );
            txtMsg.setTag( "txtMsg" );
            txtMsg.setPadding( 30, 10, 30, 10 );
 
            // レイアウトにアイコン、テキストUIを追加
            layout.addView( imgIcon );
            layout.addView( txtMsg );
        }
 
 
        // 一覧の説明表示欄に、メッセージを流し込む
        TextView txtViewMsg = (TextView)convertView.findViewWithTag( "txtMsg" );
        txtViewMsg.setText( itemList.get( position ) );
 
 
        // 表示すべきviewを返す
        return convertView;
    }
}



ListViewに項目を表示させるべき状況が発生すると、Androidのイベントループ側がgetView()を呼んでくれます。Adapterクラスは、この要求に対して表示させる見た目のViewオブジェクトを返してあげます。



getView()の引数は3つ有ります。

第1引数のpositionで、指定された場所が分かるので、メソッド内では可変部の情報をpositionを元にデータ取得します。

第2引数のconvertViewは、既に一度表示された明細項目を再表示する場合には、前回表示されてたViewが返るので、可変部だけを設定します。初めて表示される項目の場合(初期表示/スクロールさせた時など)は、convertViewがNullなのでViewオブジェクト自体を、getView()内で生成するします。




今回のサンプルではアイコンと文字の2つだけでしたが、アダプタクラスgetView()が返すViewを変更すればどんなデザインでも組み立てることが可能です。また、Viewに流し込む可変部のデータも、ArrayListではなくArrayList>や、カスタムのクラスにしてしまえば、Adapter側へ複数/複雑な構造を持ったデータを渡す事が可能です。

[Android]ボタンがクリックされるたびにListViewに項目を追加させる

画面に表示されたボタンをクリックするたびに、ListViewへ項目を追加します。
ListViewに表示される各項目は、アイコンを設置するなど自由なデザインを組むことが出来るのですが、今回はシンプルに文字列を表示させるだけです。

※複雑なデザインにする場合は、こちらの記事を参考にして下さい。


実行結果




ソースコード

package com.example.test1;
 
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
 
import android.os.Bundle;
import android.app.Activity;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.TextView;
 
public class MainActivity extends Activity {
    Button   btnAddAlerm;
    ListView lstAlert;
    TextView txtMessage;
 
    ArrayList<String> alertList = new ArrayList<String>();
    ArrayAdapter<String> adapter;
 
    /**
     * 画面生成時のハンドラ
     */
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
 
        //--------------------
        // 画面レイアウトを作成
        //--------------------
        LinearLayout layout = new LinearLayout( this );
        layout.setOrientation( LinearLayout.VERTICAL );
        setContentView( layout );
 
        //----------------------------
        // 画面のレイアウトを組み立てる
        //----------------------------
        txtMessage = new TextView( this );
        txtMessage.setText( "こんにちは" );
 
        btnAddAlerm = new Button( this );
        btnAddAlerm.setText( "click me" );
 
        lstAlert = new ListView( this );        
        adapter = new ArrayAdapter<String>( this, android.R.layout.simple_list_item_1, alertList );
        lstAlert.setAdapter(adapter);
 
        layout.addView( txtMessage );
        layout.addView( btnAddAlerm );
        layout.addView( lstAlert );
 
        // ボタンクリック時のイベントを定義
        btnAddAlerm.setOnClickListener( new BtnAddAlermClickListener() );
    }
 
 
    /** ボタンクリック時のハンドラ
     */
    private class BtnAddAlermClickListener implements OnClickListener {
 
        public void onClick(View v) {
            txtMessage.setText( "ボタンがクリックされました" );
 
            // 一覧に追加するメッセージを組み立て
            String msg = "item" + alertList.size() + ": " + new SimpleDateFormat( "yyyy/MM/dd HH:mm:ss" ).format( new Date() );
 
            // ListViewに項目を追加
            alertList.add( msg );
            lstAlert.setAdapter(adapter);
        }
    }
 
}



ListViewを使用するのに必要な3つのオブジェクト


ListViewを使用するには、以下の3つのオブジェクトが必要です。

ListView自体
Adapterクラス
表示すべき項目の一覧





ListView

ListView自体は単なるViewでこれまで,使用したButton/TextView等と同様のUIオブジェクトです。



Adapterクラス

Adapterクラスは、ListViewに対してデータを渡すためのData-UI間の橋渡し役です。
今回はBaseAdapterを継承したArrayAdapterクラスを使用します。

lstAlert = new ListView( this );        
adapter = new ArrayAdapter<String>( this, android.R.layout.simple_list_item_1, alertList );
lstAlert.setAdapter(adapter);


コンストラクタでは、context,resource,dataの3つを渡します。


resourceは、Androidで事前定義されている”android.R.layout.simple_list_item_1″を指定します。
これは、SDKのインストール先の以下の場所辺りで定義されています。

%INSTALL_DIR%\platforms\android-10\data\res\layout\simple_list_item_1.xml




内容はこんな感じで、単一のTextViewとして定義されています。

<TextView xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@android:id/text1"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:textAppearance="?android:attr/textAppearanceLarge"
    android:gravity="center_vertical"
    android:paddingLeft="6dip"
    android:minHeight="?android:attr/listPreferredItemHeight"
/>



もっと凝ったUIを表示させたい場合は、このリソースを別のものに変えるか、ArrayAdapterを継承した独自のクラスを作成します。
※継承させる場合のコードはこちらで説明しています。

3つ目の引数は、表示させたい項目の一覧です。



表示すべき項目の一覧


表示すべき項目の一覧は、まさに出したいデータです。
今回は文字列を管理するだけなのでjava.utilのArrayListを使用しました。

[Android]ハードウェアキーが押された時のイベントを取る

ケータイについているハードウェアキーを押した時のイベントを検出します。
沢山キーが付いている端末を使っている時は、onKeyDownの第一引数を画面にダンプすることで各キーのキーコードを確認できます。

package com.example.test1;
 
import android.os.Bundle;
import android.app.Activity;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.View;
import android.widget.LinearLayout;
import android.widget.TextView;
 
public class MainActivity extends Activity {
    Button   btnAddAlerm;
    TextView txtMessage;
 
 
    /**
     * 画面生成時のハンドラ
     */
    @Override
    protected void onCreate(Bundle savedInstanceState) {
 
        super.onCreate(savedInstanceState);
 
        //--------------------
        // 画面レイアウトを作成
        //--------------------
        LinearLayout layout = new LinearLayout( this );
        layout.setOrientation( LinearLayout.VERTICAL );
        setContentView( layout );
 
        //----------------------------
        // テキスト表示欄と、ボタンを画面に追加
        //----------------------------
        txtMessage = new TextView( this );
        txtMessage.setText( "こんにちは" );
        layout.addView( txtMessage );
 
    }
 
    /** キークリック時のハンドラ
     */
    @Override
    public boolean onKeyDown( int keyCode, KeyEvent e ) {
        switch ( keyCode ) {
            case KeyEvent.KEYCODE_VOLUME_DOWN:
                txtMessage.setText( "ボリュームDown" );
                break;
            case KeyEvent.KEYCODE_VOLUME_UP:
                txtMessage.setText( "ボリュームUp" );
                break;
            case KeyEvent.KEYCODE_DPAD_UP:
                txtMessage.setText( "上キー" );
                break;
            case KeyEvent.KEYCODE_DPAD_DOWN:
                txtMessage.setText( "下キー" );
                break;
            case KeyEvent.KEYCODE_DPAD_LEFT:
                txtMessage.setText( "左キー" );
                break;
            case KeyEvent.KEYCODE_DPAD_RIGHT:
                txtMessage.setText( "右キー" );
                break;
            case KeyEvent.KEYCODE_DPAD_CENTER:
                txtMessage.setText( "中央キー" );
                break;
            default:
                txtMessage.setText( "不明なキー  keyCode:" + String.valueOf( keyCode ) );
                break;              
        }
        return false;
 
    }
 
}





また、各キーコードはandroid.view.InputEvent.KeyEventクラスで定数の定義がされています。

コードと値の対応は以下の通りです。
プログラム中では、if ( keyCode == KeyEvent.KEYCODE_0 ) といった感じで使用します。

コード 定数名
----- ------------------------
0     KEYCODE_UNKNOWN                 
1     KEYCODE_SOFT_LEFT               
2     KEYCODE_SOFT_RIGHT              
3     KEYCODE_HOME                    
4     KEYCODE_BACK                    
5     KEYCODE_CALL                    
6     KEYCODE_ENDCALL                 
7     KEYCODE_0                       
8     KEYCODE_1                       
9     KEYCODE_2                       
10    KEYCODE_3                       
11    KEYCODE_4                       
12    KEYCODE_5                       
13    KEYCODE_6                       
14    KEYCODE_7                       
15    KEYCODE_8                       
16    KEYCODE_9                       
17    KEYCODE_STAR                    
18    KEYCODE_POUND                   
19    KEYCODE_DPAD_UP                 
20    KEYCODE_DPAD_DOWN               
21    KEYCODE_DPAD_LEFT               
22    KEYCODE_DPAD_RIGHT              
23    KEYCODE_DPAD_CENTER             
24    KEYCODE_VOLUME_UP               
25    KEYCODE_VOLUME_DOWN             
26    KEYCODE_POWER                   
27    KEYCODE_CAMERA                  
28    KEYCODE_CLEAR                   
29    KEYCODE_A                       
30    KEYCODE_B                       
31    KEYCODE_C                       
32    KEYCODE_D                       
33    KEYCODE_E                       
34    KEYCODE_F                       
35    KEYCODE_G                       
36    KEYCODE_H                       
37    KEYCODE_I                       
38    KEYCODE_J                       
39    KEYCODE_K                       
40    KEYCODE_L                       
41    KEYCODE_M                       
42    KEYCODE_N                       
43    KEYCODE_O                       
44    KEYCODE_P                       
45    KEYCODE_Q                       
46    KEYCODE_R                       
47    KEYCODE_S                       
48    KEYCODE_T                       
49    KEYCODE_U                       
50    KEYCODE_V                       
51    KEYCODE_W                       
52    KEYCODE_X                       
53    KEYCODE_Y                       
54    KEYCODE_Z                       
55    KEYCODE_COMMA                   
56    KEYCODE_PERIOD                  
57    KEYCODE_ALT_LEFT                
58    KEYCODE_ALT_RIGHT               
59    KEYCODE_SHIFT_LEFT              
60    KEYCODE_SHIFT_RIGHT             
61    KEYCODE_TAB                     
62    KEYCODE_SPACE                   
63    KEYCODE_SYM                     
64    KEYCODE_EXPLORER                
65    KEYCODE_ENVELOPE                
66    KEYCODE_ENTER                   
67    KEYCODE_DEL                     
68    KEYCODE_GRAVE                   
69    KEYCODE_MINUS                   
70    KEYCODE_EQUALS                  
71    KEYCODE_LEFT_BRACKET            
72    KEYCODE_RIGHT_BRACKET           
73    KEYCODE_BACKSLASH               
74    KEYCODE_SEMICOLON               
75    KEYCODE_APOSTROPHE              
76    KEYCODE_SLASH                   
77    KEYCODE_AT                      
78    KEYCODE_NUM                     
79    KEYCODE_HEADSETHOOK             
80    KEYCODE_FOCUS                   
81    KEYCODE_PLUS                    
82    KEYCODE_MENU                    
83    KEYCODE_NOTIFICATION            
84    KEYCODE_SEARCH                  
85    KEYCODE_MEDIA_PLAY_PAUSE        
86    KEYCODE_MEDIA_STOP              
87    KEYCODE_MEDIA_NEXT              
88    KEYCODE_MEDIA_PREVIOUS          
89    KEYCODE_MEDIA_REWIND            
90    KEYCODE_MEDIA_FAST_FORWARD      
91    KEYCODE_MUTE                    
92    KEYCODE_PAGE_UP                 
93    KEYCODE_PAGE_DOWN               
94    KEYCODE_PICTSYMBOLS             
95    KEYCODE_SWITCH_CHARSET          
96    KEYCODE_BUTTON_A                
97    KEYCODE_BUTTON_B                
98    KEYCODE_BUTTON_C                
99    KEYCODE_BUTTON_X                
100   KEYCODE_BUTTON_Y                
101   KEYCODE_BUTTON_Z                
102   KEYCODE_BUTTON_L1               
103   KEYCODE_BUTTON_R1               
104   KEYCODE_BUTTON_L2               
105   KEYCODE_BUTTON_R2               
106   KEYCODE_BUTTON_THUMBL           
107   KEYCODE_BUTTON_THUMBR           
108   KEYCODE_BUTTON_START            
109   KEYCODE_BUTTON_SELECT           
110   KEYCODE_BUTTON_MODE             
111   KEYCODE_ESCAPE                  
112   KEYCODE_FORWARD_DEL             
113   KEYCODE_CTRL_LEFT               
114   KEYCODE_CTRL_RIGHT              
115   KEYCODE_CAPS_LOCK               
116   KEYCODE_SCROLL_LOCK             
117   KEYCODE_META_LEFT               
118   KEYCODE_META_RIGHT              
119   KEYCODE_FUNCTION                
120   KEYCODE_SYSRQ                   
121   KEYCODE_BREAK                   
122   KEYCODE_MOVE_HOME               
123   KEYCODE_MOVE_END                
124   KEYCODE_INSERT                  
125   KEYCODE_FORWARD                 
126   KEYCODE_MEDIA_PLAY              
127   KEYCODE_MEDIA_PAUSE             
128   KEYCODE_MEDIA_CLOSE             
129   KEYCODE_MEDIA_EJECT             
130   KEYCODE_MEDIA_RECORD            
131   KEYCODE_F1                      
132   KEYCODE_F2                      
133   KEYCODE_F3                      
134   KEYCODE_F4                      
135   KEYCODE_F5                      
136   KEYCODE_F6                      
137   KEYCODE_F7                      
138   KEYCODE_F8                      
139   KEYCODE_F9                      
140   KEYCODE_F10                     
141   KEYCODE_F11                     
142   KEYCODE_F12                     
143   KEYCODE_NUM_LOCK                
144   KEYCODE_NUMPAD_0                
145   KEYCODE_NUMPAD_1                
146   KEYCODE_NUMPAD_2                
147   KEYCODE_NUMPAD_3                
148   KEYCODE_NUMPAD_4                
149   KEYCODE_NUMPAD_5                
150   KEYCODE_NUMPAD_6                
151   KEYCODE_NUMPAD_7                
152   KEYCODE_NUMPAD_8                
153   KEYCODE_NUMPAD_9                
154   KEYCODE_NUMPAD_DIVIDE           
155   KEYCODE_NUMPAD_MULTIPLY         
156   KEYCODE_NUMPAD_SUBTRACT         
157   KEYCODE_NUMPAD_ADD              
158   KEYCODE_NUMPAD_DOT              
159   KEYCODE_NUMPAD_COMMA            
160   KEYCODE_NUMPAD_ENTER            
161   KEYCODE_NUMPAD_EQUALS           
162   KEYCODE_NUMPAD_LEFT_PAREN       
163   KEYCODE_NUMPAD_RIGHT_PAREN      
164   KEYCODE_VOLUME_MUTE             
165   KEYCODE_INFO                    
166   KEYCODE_CHANNEL_UP              
167   KEYCODE_CHANNEL_DOWN            
168   KEYCODE_ZOOM_IN                 
169   KEYCODE_ZOOM_OUT                
170   KEYCODE_TV                      
171   KEYCODE_WINDOW                  
172   KEYCODE_GUIDE                   
173   KEYCODE_DVR                     
174   KEYCODE_BOOKMARK                
175   KEYCODE_CAPTIONS                
176   KEYCODE_SETTINGS                
177   KEYCODE_TV_POWER                
178   KEYCODE_TV_INPUT                
179   KEYCODE_STB_POWER               
180   KEYCODE_STB_INPUT               
181   KEYCODE_AVR_POWER               
182   KEYCODE_AVR_INPUT               
183   KEYCODE_PROG_RED                
184   KEYCODE_PROG_GREEN              
185   KEYCODE_PROG_YELLOW             
186   KEYCODE_PROG_BLUE               
187   KEYCODE_APP_SWITCH              
188   KEYCODE_BUTTON_1                
189   KEYCODE_BUTTON_2                
190   KEYCODE_BUTTON_3                
191   KEYCODE_BUTTON_4                
192   KEYCODE_BUTTON_5                
193   KEYCODE_BUTTON_6                
194   KEYCODE_BUTTON_7                
195   KEYCODE_BUTTON_8                
196   KEYCODE_BUTTON_9                
197   KEYCODE_BUTTON_10               
198   KEYCODE_BUTTON_11               
199   KEYCODE_BUTTON_12               
200   KEYCODE_BUTTON_13               
201   KEYCODE_BUTTON_14               
202   KEYCODE_BUTTON_15               
203   KEYCODE_BUTTON_16               
204   KEYCODE_LANGUAGE_SWITCH         
205   KEYCODE_MANNER_MODE             
206   KEYCODE_3D_MODE                 
207   KEYCODE_CONTACTS                
208   KEYCODE_CALENDAR                
209   KEYCODE_MUSIC                   
210   KEYCODE_CALCULATOR              
211   KEYCODE_ZENKAKU_HANKAKU         
212   KEYCODE_EISU                    
213   KEYCODE_MUHENKAN                
214   KEYCODE_HENKAN                  
215   KEYCODE_KATAKANA_HIRAGANA       
216   KEYCODE_YEN                     
217   KEYCODE_RO                      
218   KEYCODE_KANA                    
219   KEYCODE_ASSIST


[Android]画面/ボタンのタッチを検出する

画面上のボタンがタッチされると”ボタンがタッチされました”、ボタン以外のエリアがタッチされると”画面がタッチされました”というメッセージを表示します。

ここで”タッチ”というのは、ボタンに指が触っているけど離されていない、押されたままの状態です。
.Net Framework的な言い方だとOnPress()な感じです。


ボタンタッチ時


画面タッチ時(ボタン以外のエリア)




コード

package com.example.test1;
 
import android.os.Bundle;
import android.app.Activity;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.View.OnTouchListener;
import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.TextView;
 
 
public class MainActivity extends Activity {
    Button   btnAddAlerm;
    TextView txtMessage;
 
 
    /**
     * 画面生成時のハンドラ
     */
    @Override
    protected void onCreate(Bundle savedInstanceState) {
 
        super.onCreate(savedInstanceState);
 
        //--------------------
        // 画面レイアウトを作成
        //--------------------
        LinearLayout layout = new LinearLayout( this );
        layout.setOrientation( LinearLayout.VERTICAL );
        setContentView( layout );
 
        //----------------------------
        // テキスト表示欄と、ボタンを画面に追加
        //----------------------------
        txtMessage = new TextView( this );
        txtMessage.setText( "こんにちは" );
        btnAddAlerm = new Button( this );
        btnAddAlerm.setText( "click me" );
        layout.addView( txtMessage );
        layout.addView( btnAddAlerm );
 
        // ボタンタッチ時のイベントを定義
        btnAddAlerm.setOnTouchListener( new BtnAddAlermTouchListener() );
 
    }
 
    /** 画面がタッチされた時のハンドラ
     */
    @Override    
    public boolean onTouchEvent( MotionEvent e ) {
        if ( e.getAction() == MotionEvent.ACTION_DOWN ) {
            txtMessage.setText( "画面がタッチされました" );
        }
        if ( e.getAction() == MotionEvent.ACTION_UP ) {
            txtMessage.setText( "画面から離れました" );
        }
        return true;    
    }
 
 
    /** ボタンがタッチされた時のハンドラ
     */
    private class BtnAddAlermTouchListener implements OnTouchListener {
        @Override
        public boolean onTouch(View v, MotionEvent e) {
            if ( e.getAction() == MotionEvent.ACTION_DOWN ) {
                txtMessage.setText( "ボタンがタッチされました" );
            }
            if ( e.getAction() == MotionEvent.ACTION_UP ) {
                txtMessage.setText( "ボタンから離れました" );
            }
            return true;
        }
    }
}

[Android]デバッグ時にコードを編集すると”Hot Code Replace Failed”エラーが出る

Androidのアプリ開発で、実機でのデバッグ実行中にコードを編集すると
以下の警告ダイアログが表示されることがあります。


  Hot Code Replace Failed
 
  Some code changes cannot be hot swapped into a running virtual machine, 
  such as changing method names or introducing errors into running code.
 
  The current target virtual machine [main.Main at localhost:9999] from launch 
  [XXXXX] was unable to replace the running code with the code in the workspace.
 
  It is safe to continue running the application, but you may notice 
  discrepancies when debugging this application.
 
  Reason:
  The target VM dows not support hot code replace




これは、AndroidのJavaVMであるDalvik VMが、プログラム実行中のコード編集(hot code replace)に対応していないからです。

この警告ダイアログで、Continueをクリックすると編集前のコードでプログラムの実行が継続されます。
Terminateだとプログラムが停止します。
Disconnectは実機上でプログラムは実行され続けますが、eclipse側のデバッグセッションは終了します。


コード編集後のプログラムでデバッグする場合は、Terminateを選択し再度デバッグ実行を行います。

[Android]ボタンが押されたらメッセージを表示する

ボタンクリック前



クリック後


package com.example.test1;
 
import android.os.Bundle;
import android.app.Activity;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.TextView;
 
public class MainActivity extends Activity {
    Button btnAddAlerm;
    ListView lstAlert;
    TextView txtMessage;
    /**
     * 画面生成時のハンドラ
     */
    @Override
    protected void onCreate(Bundle savedInstanceState) {
 
        super.onCreate(savedInstanceState);
 
        //--------------------
        // 画面レイアウトを作成
        //--------------------
        LinearLayout layout = new LinearLayout( this );
        layout.setOrientation( LinearLayout.VERTICAL );
        setContentView( layout );
 
        //--------------------------------------
        // テキスト表示欄と、ボタンを画面に追加
        //--------------------------------------
        txtMessage = new TextView( this );
        txtMessage.setText( "こんにちは" );
        btnAddAlerm = new Button( this );
        btnAddAlerm.setText( "click me" );
        layout.addView( txtMessage );
        layout.addView( btnAddAlerm );
 
        // ボタンクリック時のイベントを定義
        btnAddAlerm.setOnClickListener( new BtnAddAlermClickListener() );        
 
    }
 
 
    /** ボタンクリック時のハンドラ
     */
    private class BtnAddAlermClickListener implements OnClickListener {
 
        public void onClick(View v) {
            txtMessage.setText( "ボタンがクリックされました" );
 
        }
    }
 
}


[C#]switch文のcase句の中だけで有効な変数を宣言する[C,C++,javaも同様]

プログラム中に例えば、以下の様なswitch文があったとします。

void func( int inData ) {
 
    switch ( inData ) {
        case 1:
            ...;
            break;
        case 2:
            ...;
            break;
    }
}




このcase句の中で、ワークの一時変数を使いたい場合、以下のようにcase内で宣言する事が可能です。

int func( int inData ) {
 
    switch ( inData ) {
        case 1:
            int retVal = 10 + inData;
            return retVal;
        case 2:
            ...;
            break;
    }
}




ですが、下記のコードはエラーになってしまいます。

int func( int inData ) {
 
    switch ( inData ) {
        case 1:
            int retVal = 10 + inData;
            return retVal;
        case 2:
            int retVal = 10 * inData;   // NG:これはエラーになる
            return retVal;
    }
}


これは変数retValがメソッドfunc()全体で有効となり、同一変数名の重複定義となってしまうからです。



このような場合、以下のように各case句にブロック”{…}”を作ります。

int func( int inData ) {
 
    switch ( inData ) {
        case 1: {
            int retVal = 10 + inData;
            return retVal;
        }
        case 2: {
            int retVal = 10 * inData;   // OK
            return retVal;
        }
    }
}


上記のコードだと、ワーク変数のスコープがメソッド全体ではなくブロック内ローカルとなる為、名前が重複してもエラーとなりません。

一方で、switch分の後でこの変数を参照する事は出来ないので、注意が必要です。
…ですが、この記事の目的は”case句の中だけで有効な変数を宣言したい”なので、この制限は問題ではなく、逆にメリットになるはずです。


ちなみに、この手のテクニックは、C#固有なものではなく、C,C++,java言語等でも同様に使用可能です。



また、上記以外にswitchの外で変数定義を行う方法もあります。
(一般には、こっちのほうがスタンダードな書き方です)

int func( int inData ) {
    int retVal;
 
    switch ( inData ) {
        case 1:
            retVal = 10 + inData;
            break;
        case 2:
            retVal = 10 * inData;   // OK
            break;
    }
    return retVal;
}


これだと、switch文の後で変数値を参照する事が可能です。
一方でデメリットは変数の生存期間が必要以上に長くなるというデメリットが有ります。

名古屋市図書館のWebサイトは、NEC製のWebOTXを使用

エラーが出たページ:
www.library.city.nagoya.jp/licsxp-opac/WOpacYoyCartBackAction.do

エラー内容:


HTTPステータス 500 -
 
type 例外レポート
メッセージ
説明 The server encountered an internal error () that prevented it from fulfilling this request.
 
例外
java.lang.NullPointerException
 
注意 原因のすべてのスタックトレースは、WebOTX Web Container/6.31.10.00のログに記録されています
WebOTX Web Container/6.31.10.00




レスポンスヘッダ

Connection	close
Content-Length	1247
Content-Type	text/html;charset=utf-8
Date	Tue, 04 Dec 2012 xx:xx:xx GMT
Server	WebOTX_Web_Server/2.0.59 (Unix) mod_jk/1.2.15





WebOTX Web_ServerはNEC製のWebアプリケーションサーバ

WebOTXはJakarta Tomcat 6.0をベースに次の機能を独自に強化したWebコンテナを提供しています。


Webコンテナ機能 : WebOTX Application Server : WebOTX : ソフトウェア | NEC


mod_jk 1.2.15のリリースタイミング
JK-1.2.25 released: 7 August 2007
The Apache Tomcat Connector – Documentation Index





某図書館のWebにアクセスしたら、こんなの出た。
例外処理の漏れだろうか。

— 2年前

by V.S.A. IV (HTTPステータス 500 – type 例外レポート メッセージ 説明 The server…)
-> たぶん、さいたま市中央図書館の事。
検索ページのUIが一緒なので同じシステムっぽい。

Firefoxプラグインで,Yahooメールの広告を非表示にする

Yahooメールを使用していると、画面のいたるところに広告が表示されとても目障りです。



こんな時は、firefoxプラグインのStylishを使用すると、余計な情報を隠す事が出来ます。
Stylish :: Add-ons for Firefox


今回作成したスタイルは以下の通り

@-moz-document domain( "mail.yahoo.co.jp" ) {
    table#jpwelcomeadlsq,
    div.ad_NW,
    div#jp_ads_ult,
    div#jp_ads_IM,
    div#slot_LCL,
    div#yjmail_top_smp_bnr {
        height:0px !important;
        display:none !important;
    }
 
    iframe#jp_ads_im_empty,
    iframe#tgtMON,
    div#theAd {
        display:none !important;
    }
}




こんな感じでコピペすればOKです。





スタイル適用前、適用後の比較

たった20行弱のスタイル定義ですが効果は絶大です。
幾つかのページで、見た目がどの様に変わるか比較してみます。

ログイン直後の画面


適用前


適用後



メール閲覧画面


適用前


適用後



エラー画面(該当メールなし)


適用前


適用後




ちょっとした事ですが、余計なものに煩わされずに済むというのは、気が散る事が減るので良いです。

PIC16F84Aのファイルレジスタ

PIC16Fシリーズの入門用として有名な16F84Aには、83byteのファイルレジスタが用意されています。
ファイルレジスタというのは、パソコンで言うところのRAMと、メモリマップされたI/Oレジスタに相当するものです。

名前は、ファイル”レジスタ”ですが、IntelのCPUで使用されている演算用レジスタ(EAX,EBX等の名前で呼ばれています)とは意味が違うので注意してください。(これに相当する,汎用レジスタはWレジスタというもので別途用意されています)


ファイルレジスタのメモリマップ

利用可能な144byteにはそれぞれ固有の(ユニークな)番地が割り振られています。
具体的な番地はデータシートで明記されており、以下の通りとなっています。


上記表のうち、グレーになっている番地のレジスタは使用できません。
この為、実際に以下の番地にアクセスできるという事が分かります。

0x00~0x06
0x08~0x4f
0x80~0x86
0x88~0xCF



レジスタの各番地は8bit幅で、0x00~0xFFの256通りの値をセットできます。

SFR(Special Function Register)

その内、一部の番地のレジスタには特殊な意味があり、SFRと呼ばれています。
SFRというのはSpecial Function Registerの略です。

SFRをアクセスする事で、CPUの動作設定を変更させたり、マイコンから出ているI/Oピンの状態を読み書きする事が可能です。

以下にSFRの一覧を示します。

Addr 名称           内容
---- ----------     --------------------------------------
0x00 INDF           間接参照レジスタ
0x01 TMR0           タイマ
0x02 PCL            プログラムカウンタ(下位8bit)
0x03 STATUS         ステータスレジスタ
0x04 FSR            バンク切り替え用レジスタ
0x05 PORTA          ポートAの値
0x06 PORTB          ポートBの値
0x08 EEDATA         EEPROMの値
0x09 EEADR          EEPROMのRead/Writeアドレス
0x0A PCLATH         プログラムカウンタ(上位5bit)
0x0B INTCON         割り込みフラグ
0x81 OPTION_REG     オプションレジスタ(プリスケーラetc)
0x85 TRISA          ポートA入出力モード
0x86 TRISB          ポートB入出力モード
0x88 EECON1         EEPROM操作用
0x89 EECON2         EEPROM操作用





SFR以外の0x0C~0x4F(計67byte)はプログラマが自由に使用可能な汎用領域で、内部的にはSRAMとして実装されています。

0x8C~0xCF番地も同様にアクセス出来ますが、この領域はBank0にマップされています。これは、例えば0x8C番地の値を書き換えると0x0Cも書き換わるという意味ですが、バンクの概念については次節の”バンク切り替え処理”を参照してください。

ファイルレジスタのバンク切り替え処理


先ほどの表を見ると、ファイルレジスタは大きく0x00~0x7Fと0x80~0xFFの2つに分けられており、表の上を見るとそれぞれBank0,Bank1という名前が付いていることが分かります。PICでは、プログラムの実行中、プログラムからはBank0かBank1のどちらかしか読み書きする事が出来ないような制限が有ります(この制限はプログラムの機械語上、レジスタ指定のビットが7bitしかない事から来ています)。

どっちのバンクにアクセスしたいかは、後述するSTATUSレジスタのRP0,RP1ビットを操作することで切り替え可能です。

上記のレジスタの内、PCL,STATUS,FSR,PCLATH,INTCONレジスタはよく使用されるので,以下のアドレスからもアクセス可能です。

0x82 PCL
0x83 STATUS
0x84 FSR
0x8A PCLATH
0x8B INTCO


要は、バンク切り替えをしなくても常に参照できるという事です。


ビット毎に意味があるレジスタの内容一覧

SFRの内、STATUS/OPTION/INTCONレジスタは、ビット毎に意味を持たせています。
各レジスタが、ビット毎にどんな意味を持たせているかは以下の通りです。

STATUSレジスタ (0x03, 0x83)


STATUSレジスタは、CPUによる命令の実行結果や、CPUの動作状態を通知します。

ビット      名称    意味
7                   未実装(読むと常に"0")
 
5,6         #RP0        バンク指定(負論理)
            #RP1        01 = Bank 1 (80h - FFh)
                        00 = Bank 0 (00h - 7Fh)
                        ※読み込み専用です。
 
4           #TO     タイムアウトビット(負論理)
                        1 = 起動時か、CLRWDT/SLEEP命令実行時
                        0 = ウォッチドッグタイマによるタイムアウトが発生
                        ※読み込み専用です。
 
3           PD      パワーダウンビット
                        1 = 起動後か、CLRWDT命令実行時
                        0 = SLEEP命令実行時
 
2           Z       ゼロフラグ
                        1 = 直前の数値演算・論理演算の結果が0だった
                        0 = 直前の数値演算・論理演算の結果が0以外だった
 
1           DC      キャリー発生フラグ
                    (ADDWF, ADDLW,SUBLW,SUBWF命令)
                        1 = bit3からのキャリーが発生した
                        0 = bit3からのキャリーが発生しなかった
 
0           C       キャリー発生フラグ
                            1 = 最上位ビットでキャリーが発生した
                            0 = 最上位ビットでキャリーが発生しなかった




OPTIONレジスタ (0x81)


OPTIONレジスタはCPUの動作を指定します

ビット      名称    意味
7           #RBPU   PORTBの内部プルアップ指定(負論理)
                        1 = PORTBの内部プルアップを無効にする
                        0 = PORTBの内部プルアップを有効にする
 
6           INTEDG  割り込みのエッジ指定
                        1 = RB0/INTピンの立上りエッジで割り込み発生
                        0 = RB0/INTピンの立下りエッジで割り込み発生
 
5           T0CS    TMR0タイマのクロック指定
                        1 = RA4/T0CKIピンからタイマクロック供給
                        0 = CPUシステムクロック(CLKOUT)からタイマクロック供給
 
4           T0SE    TMR0 Source Edge Select bit
                        1 = RA4/T0CKIピンの立下りでタイマ加算
                        0 = RA4/T0CKIピンの立上りでタイマ加算
 
3           PSA     タイマ/ウォッチドッグのプリスケーラ割当て指定
                        1 = Prescalerをウォッチドッグ(WDT)に割当てる
                        0 = Prescalerをタイマモジュール(TMR0)に割当てる
 
2-0         PS2     プリスケーラ値の指定
            PS1         値  TMR0使用時  WDT使用時
            PS0         000 1:2         1:1
                        001 1:4         1:2
                        010 1:8         1:4
                        011 1:16        1:8
                        100 1:32        1:16
                        101 1:64        1:32
                        110 1:128       1:64
                        111 1:256       1:128




INTCONレジスタ (0x0B, 0x8B)


INTCONレジスタは割り込みに関する処理を制御します

ビット      名称    意味
7           GIE:    Global Interrupt Enableフラグ
                        1 = 割込み制御を有効にします
                        0 = 全ての割込みを無効にします
 
6           EEIE    EEPROM書き込み完了の割込み通知
                        1 = EEPROM書き込み完了時に割込みを発生させます
                        0 = EEPROM書き込み完了時に割込みを発生させません
 
5           T0IE    TMR0オーバーフロー割込み通知
                        1 = TMR0オーバーフロー時に割込みを発生させます
                        0 = TMR0オーバーフロー時に割込みを発生させません
 
4           INTE    RB0/INTピンによる外部割込み通知
                        1 = RB0/INTピンによる外部割込みを発生させます
                        0 = RB0/INTピンによる外部割込みを発生させません
 
3           RBIE    PORTBの状態変化による割込み通知(RB7~RB4)
                        1 = PORTBの状態変化による割込みを発生させます
                        0 = PORTBの状態変化による割込みを発生させません
 
2           T0IF    TMR0オーバーフロー割込みフラグ
                        1 = TMR0割込みが発生した
                        0 = TMR0割込みが発生しない
 
1           INTF    RB0/INTピンによる外部割込みフラグ
                        1 = RB0/INTピンによる外部割込みが発生した
                        0 = RB0/INTピンによる外部割込みが発生しない
 
0           RBIF    PORTBの状態変化による割込みフラグ
                        1 = PORTBの状態変化による割込みが発生した
                        0 = PORTBの状態変化による割込みが発生しない


T0IF, INTF, RBIFフラグは、プログラマが割り込み処理内で0にクリアする必要があります。

RBIFはRB7~RB4の内、どのピンの状態が変わったかまでは通知してくれません。
割り込みハンドラ内で自分で判断する必要が有ります。

[C#]DataGridViewで選択行を画面に表示させる

以下のコードで、DataGridViewで選択されている行が画面の一番上の行に表示されます。

if ( DataGridView1.SelectedCells.Count > 0 ) { 
    DataGridView1.FirstDisplayedScrollingRowIndex = DataGridView1.SelectedCells[0].RowIndex;
}



複数のセルが選択されている場合は、最初のセルがある行を表示します。


まず、DataGridView1.SelectedCells.Countで、選択された行があるかをチェックしています。
選択行がある場合は、最初の選択セルがある行を、DataGridView1.SelectedCells[0].RowIndexで取得し,
その結果をFirstDisplayedScrollingRowIndexにセットすることで、表示上の一番上の行にさせます。

結果としてグリッドがスクロールし、選択行が表示されるようになります。


常に選択行を表示したい場合は、グリッドのセル選択が変わったときのイベントか、タイマーで一定時間毎に上記の処理を行えばOKです。


上記の処理だと、選択された行が既に画面に表示されている場合でも、対象行が一番上に移動してしまいます。
画面外にスクロールアウトされている時だけ一番上の行として表示させる場合は、以下のチェックを追加します。

// 選択された行を先頭行にする
if ( DataGridView1.SelectedCells.Count > 0 ) { 
    // 対象行が非表示の場合は何もしない
    if ( !DataGridView1.SelectedCells[0].Visible ) {
        return;
    }
    // 対象行が既に画面内に表示されている時は何もしない
    if ( DataGridView1.SelectedCells[0].Displayed ) {
        return;
    }
 
    DataGridView1.FirstDisplayedScrollingRowIndex = DataGridView1.SelectedCells[0].RowIndex;
}

[PIC]HI-TECH Cのサンプルプログラムを逆アセンブルしてみる

前に作りかけたPic16f84のCPUシミュレータですが、暇が出来たので開発を再開させます。

ずいぶん久しぶりなので、何をやってたかを思い出すのを兼ねて、動作確認用サンプルのhexファイルを作る事にします。


今回の対象はHI-TECH Cのコンパイラをインストールしたときに一緒に入っているサンプルPGです。
ファイルは、標準インストールだと以下の辺りに入ってます。

C:\Program Files\HI-TECH Software\PICC\9.83\samples\misc\led.c



このプログラムはLEDの点滅プログラムで、コードは以下の通りのシンプルなものです。
“Freely distributable.”らしいので、ソースを全文転記します。

#include    <htc.h>
 
/*
 *  Demo program
 *
 *  Flashes LEDs on Port B, responds to switch press
 *  on RA1. Usable on PICDEM board.
 *
 *  Copyright (C)1997 HI-TECH Software.
 *  Freely distributable.
 */
#define BUTTON  RC1 //bit 1 of PORTC
 
main(void)
{
    unsigned char   i, j;
 
    TRISB = 0;      /* all bits output */
    j = 0;
    for(;;) {
        PORTB = 0x00;       /* turn all on */
        for(i = 100 ; --i ;)
            continue;
        PORTB = ~j;     /* output value of j */
        for(i = 100 ; --i ;)
            continue;
        if(BUTTON == 0)     /* if switch pressed, increment */
            j++;
    }
}



コメントにも有りますが、このプログラムでは以下の処理をしています。

 1. ポートBのLEDを点滅させます。
 2. RA1のスイッチを押すと点滅する値が変わります。



…なはずですが、このコード、コメントはRA1にボタンが繋がっている書かれてるのに、#defineがRC1になってます。16F84AにPORTCは無いので、これはRA1に書き換えておきます。

#define BUTTON  RC1 //bit 1 of PORTC




#define BUTTON  RA1 //bit 1 of PORTA





で、MPLABでプロジェクトを作ってコンパイルした結果は以下の通りです。

---  C:\home\project\pic\16F84A_Example_LED\16F84A_Example_LED.as  -------------------------------
1:                 opt subtitle "HI-TECH Software Omniscient Code Generator (Lite mode) build 10920"
2:                 
3:                 opt pagewidth 120
4:                 
5:                  opt lm
6:                 
7:                  processor   16F84A
8:                 clrc macro
9:                  bcf 3,0
10:                 endm
11:                clrz macro
12:                 bcf 3,2
13:                 endm
14:                setc macro
15:                 bsf 3,0
16:                 endm
17:                setz macro
18:                 bsf 3,2
19:                 endm
20:                skipc    macro
21:                 btfss   3,0
22:                 endm
23:                skipz    macro
24:                 btfss   3,2
25:                 endm
26:                skipnc   macro
27:                 btfsc   3,0
28:                 endm
29:                skipnz   macro
30:                 btfsc   3,2
31:                 endm
32:                indf equ 0
33:                indf0    equ 0
34:                pc   equ 2
35:                pcl  equ 2
36:                status   equ 3
37:                fsr  equ 4
38:                fsr0 equ 4
39:                c    equ 1
40:                z    equ 0
41:                pclath   equ 10
42:                 FNROOT  _main
43:                 global  _EEADR
44:                psect    maintext,global,class=CODE,delta=2
45:                global __pmaintext
46:                __pmaintext:
47:                _EEADR   set 9
48:                 global  _EEDATA
49:                _EEDATA  set 8
50:                 global  _PORTB
51:                _PORTB   set 6
52:                 global  _CARRY
53:                _CARRY   set 24
54:                 global  _GIE
55:                _GIE set 95
56:                 global  _RA1
57:                _RA1 set 41
58:                 global  _EECON1
59:                _EECON1  set 136
60:                 global  _EECON2
61:                _EECON2  set 137
62:                 global  _TRISB
63:                _TRISB   set 134
64:                 global  _RD
65:                _RD  set 1088
66:                 global  _WR
67:                _WR  set 1089
68:                 global  _WREN
69:                _WREN    set 1090
70:                 file    "16F84A_Example_LED.as"
71:                 line    #
72:                psect cinit,class=CODE,delta=2
73:                global start_initialization
74:                start_initialization:
75:                
76:                psect cinit,class=CODE,delta=2
77:                global end_of_initialization
78:                
79:                ;End of C runtime variable initialization code
80:                
81:                end_of_initialization:
82:                clrf status
   3D1    0183     CLRF 0x3
83:                ljmp _main   ;jump to C main() function
   3D2    2BD3     GOTO 0x3d3
---  C:\home\project\pic\16F84A_Example_LED\led.c  -----------------------------------------------
1:                 #include <htc.h>
2:                 
3:                 /*
4:                  *   Demo program
5:                  *
6:                  *   Flashes LEDs on Port B, responds to switch press
7:                  *   on RA1. Usable on PICDEM board.
8:                  *
9:                  *   Copyright (C)1997 HI-TECH Software.
10:                 *   Freely distributable.
11:                 */
12:                
13:                //#define BUTTON RC1 //bit 1 of PORTC
14:                #define BUTTON   RA1 //bit 1 of PORTA
15:                
16:                main(void)
17:                {
18:                 unsigned char   i, j;
19:                
20:                 TRISB = 0;      /* all bits output */
   3D3    1683     BSF 0x3, 0x5
   3D4    0186     CLRF 0x6
21:                 j = 0;
   3D5    1283     BCF 0x3, 0x5
   3D6    018D     CLRF 0xd
22:                 for(;;) {
23:                     PORTB = 0x00;       /* turn all on */
   3D7    0186     CLRF 0x6
24:                     for(i = 100 ; --i ;)
   3D8    3064     MOVLW 0x64
   3D9    008C     MOVWF 0xc
   3DA    080C     MOVF 0xc, W
   3DB    008E     MOVWF 0xe
   3DC    2BDF     GOTO 0x3df
   3DF    3001     MOVLW 0x1
   3E0    028E     SUBWF 0xe, F
   3E1    1D03     BTFSS 0x3, 0x2
   3E2    2BE4     GOTO 0x3e4
   3E3    2BE5     GOTO 0x3e5
   3E4    2BDF     GOTO 0x3df
   3E5    2BE6     GOTO 0x3e6
25:                         continue;
   3DD    2BDF     GOTO 0x3df
   3DE    2BDF     GOTO 0x3df
26:                     PORTB = ~j;     /* output value of j */
   3E6    090D     COMF 0xd, W
   3E7    0086     MOVWF 0x6
27:                     for(i = 100 ; --i ;)
   3E8    3064     MOVLW 0x64
   3E9    008C     MOVWF 0xc
   3EA    080C     MOVF 0xc, W
   3EB    008E     MOVWF 0xe
   3EC    2BEF     GOTO 0x3ef
   3EF    3001     MOVLW 0x1
   3F0    028E     SUBWF 0xe, F
   3F1    1D03     BTFSS 0x3, 0x2
   3F2    2BF4     GOTO 0x3f4
   3F3    2BF5     GOTO 0x3f5
   3F4    2BEF     GOTO 0x3ef
28:                         continue;
   3ED    2BEF     GOTO 0x3ef
   3EE    2BEF     GOTO 0x3ef
29:                     if(BUTTON == 0)     /* if switch pressed, increment */
   3F5    1885     BTFSC 0x5, 0x1
   3F6    2BF8     GOTO 0x3f8
   3F7    2BF9     GOTO 0x3f9
   3F8    2BD7     GOTO 0x3d7
30:                         j++;
   3F9    3001     MOVLW 0x1
   3FA    008C     MOVWF 0xc
   3FB    080C     MOVF 0xc, W
   3FC    078D     ADDWF 0xd, F
   3FD    2BD7     GOTO 0x3d7
31:                 }
   3FE    2BD7     GOTO 0x3d7
32:                }
   3FF    2800     GOTO 0




実際のプログラムはmainだけですが、スタートアップルーチンが有るのでかなり長くなってます。
最初のスタートアップの*.asファイルは83行も有りますが、ほとんどはアセンブラ(MPASM.exe)に対する指示で、実際のコードは以下の2つだけです。

82:                clrf status
   3D1    0183     CLRF 0x3
83:                ljmp _main   ;jump to C main() function
   3D2    2BD3     GOTO 0x3d3



MPLABでプログラムメモリを見ると、最初の命令は”GOTO 0x03d1″なのでこのコードに飛んでいます。


で、スタートアップルーチンはステータスレジスタをクリア(CLRF 0x3)した後、main()にジャンプするだけ(GOTO 0x3d3)なので、理解するのは楽勝です。



プログラム本体は、Program Memoryウィンドウ上でもぎりぎり1画面に表示できるレベルでした。
HI-TECH Cはコードを0x03FFの上位番地側に詰めて配置するようです。



hexファイルは、たったこれだけです。

:02000000D12B02
:1007A2008301D32B8316860183128D018601643067
:1007B2008C000C088E00DF2BDF2BDF2B01308E022A
:1007C200031DE42BE52BDF2BE62B0D09860064309D
:1007D2008C000C088E00EF2BEF2BEF2B01308E02DA
:1007E200031DF42BF52BEF2B8518F82BF92BD72BA8
:0E07F20001308C000C088D07D72BD72B002868
:00000001FF




このhexファイルを、以前作った逆アセンブラで処理させてみます。


…驚くべき事に、ちゃんと処理されったっぽいです。


前回作ったシミュレータは、GOTOとADD命令だけしか解釈できなかったので、次回はこのコードを動かせるところまでがんばってみます。

英文に出てくる”i.e.”と”e.g.”の違いは?

英語の文章を読んでいると、”i.e.”とか、”e.g.”といった略語が出てくることがあります。
今回は、それぞれの略語の語源と、意味を説明します。

i.e.


i.e.というのは、ラテン語の”id est”が語源です。
これは、英語で言うと”that is”や、”in other words”に置き換えることが出来ます。
前の文に出てきた内容の例を説明している場合に使用します。

例:

I watch baseball from childhood, i.e. i love it longtime.
 
子供のころから野球を観戦していた。つまりずっと好きだったという事だ



e.g.


e.g.というのは、ラテン語の”exemplia gratia”が語源です。
これは、英語で言うとfor exampleに相当します。
ですので、前の文に出てきた内容の例を説明している場合に使用します。

音読する場合は、そのまま、”いー、じー”と読んだり、”for example”と読んでしまう事が多いです。
正式に[eksempli: gra:tia:]と発音する場合は非常に稀です。

例:

There are many baseball teams, e.g. Giants, Dragons and Tigers. 
 
日本には多くの野球チームがあります。
例えばジャイアンツ、ドラゴンズ、タイガースなどです。



その他、注意点


i.e.やe.g.は略語なので、ピリオドをつける必要があります。

ですが、イギリス圏ではie、egのようにピリオドを略して表記する場合も有ります。

ネイティブに「いいね! 」と思わせる イマドキ言葉の英語表現
9割の日本人が使い方を間違える英単語101

電圧計(テスタ)の内部抵抗を調べる方法


テスタ(デジタルマルチメータ)の電圧計を使うと、回路中の電位差を計測することが出来ます。
B0017S38LM


電圧値を測る場合は、対象物と並列に電圧計を入れる必要があります。
計測を行う上で電圧計の内部抵抗値が低いと、元の回路の電流に影響を与えてしまいます。
このため、電圧計は、高い内部抵抗値となっています。


電圧計の内部抵抗値は、一般に数メガオーム ~ 十数メガオームといわれています。




というのが電圧計の教科書的な説明なのですが、”高い内部抵抗値”というのは実際のところどの程度のものなのでしょうか?自分が持っている電圧計の具体的な抵抗値を計測するにはどうすればよいでしょうか?


気になる場合は、以下の手順で自分が持っている電圧計の内部抵抗を調べることが出来ます。
これは、抵抗値に対する分圧の法則を利用しています。

1. 適当な電池を用意し、電圧を測ります。
 
2. 1メガオーム程度の抵抗を用意し、テスタで実際の抵抗値を測ります。
 
3. 内部抵抗を調べたいテスタ本体と、2.で用意した抵抗を、直列で電池に繋ぎます。
   (電池の電圧を分圧させます。)
 
4. 別のテスタを用意し、3.で繋いだ計測対象の電圧計の両端の電位差を読み取ります。


上記の計測を行う事で、テスタの内部抵抗を求める事が出来ます。


例えば、計測結果が以下の値だった場合…

電池の電圧
	1.60v
 
1メガオームの抵抗値
	0.98MegΩ
 
分圧の測定値(電圧計の両端の電位差)
	1.20V



分圧の法則から、電圧計の抵抗値をRとすると以下の式で求める事が出来ます。

1.20 / (1.20-1.60) = R /0.98Meg
 
R = 3 * 0.98Meg
  = 2.94Meg


という訳で、この場合電圧計の内部抵抗は2.94メガオームという事が分かります。



4774139017
テスターの使い方がよくわかる本

4798030090
図解入門 はじめての人のためのテスターがよくわかる本

[殻割り]フォトカプラを分解する


電子回路を構成する素子のひとつにフォトカプラというものが有ります。

フォトカプラは通常、発光ダイオードとフォトトランジスタで構成されています。

入力された電気信号は発光ダイオードに入り光信号に置き換えられます。
一方フォトトランジスタは光を受けると通電するので、光を経由して電気信号を伝える事が可能です。


これにより電気的に絶縁された状況で情報を伝える事ができ、ノイズの影響を防ぐことが可能です。



…というのが、教科書的なフォトカプラの説明ですが、実際の所、中身はどんな感じになんでしょうか?



気になったので、実際にフォトカプラを購入して殻割りしてみました。

まずは、今回の実験台になってもらうフォトカプラです。
型番はTLP521で、秋月やマルツだと150円ぐらいで購入できます。

これを、ニッパーで削っていきます。



上から薄く剥いでいっても中身に到達しないので、中央あたりから思いっきり力を加えたら2つに割れました。



割れた面です。

素子が左右に向かい合わせになっているかと思いきや、上下に合わさっています。
写真だと分かり辛いですが、黒っぽく見える面は実は赤色で、角型LEDのような質感です。


せっかくなので、LED側の破片をブレッドボードに繋いでみます。



肉眼だと通電させても変化がないのですが、カメラを通してみると発光している事が確認できます。
データシートを見ると、”GaAlAs赤外発光ダイオードを使用”と記載されており、赤外線が使われている事が分かります。

カメラと通さないと光が確認できないというのは、前に確認したRPR-220との反射型フォトセンサと振る舞いが似ています。


という訳で、上下に重なっているというのは、最初のイメージとちょっと違ってましたが、確かに光を通じて情報の送信が行われる構造となっていました。
※実験で使ったフォトカプラは、この後スタッフが美味しく頂きました。

PIC18Fシリーズの型番コード体系

Micorship社から発売されているPICには、幾つかのシリーズが有ります。
シリーズを大きく分けると以下の6つに分類されます。

PIC10F,12Fシリーズ
PIC16Fシリーズ
PIC18Fシリーズ
PIC24F,24Hシリーズ
dsPICシリーズ
PIC32MXシリーズ



この中でも、PIC18Fシリーズは8ビットマイコンであるPIC16Fシリーズの後継で、16Fシリーズで使い辛かったI/O機能を改良しつつ、アセンブラレベルの命令セットは上位互換があるという特徴を持っています。


PIC18Fシリーズ中にも製品は沢山有るのですが、18Fシリーズは有る程度型番に規則性を持っており、型番だけから大まかなスペックを把握することが出来ます。

“18F”の後は、基本的に数字4桁です。製品によっては2桁目の後にアルファベットが入る場合があります。
アルファベットを無視すると、4桁を構成する各桁の意味は以下の通りです。

18FabVcd-x/yy zzz
 
a:ピン数
    1:  18ピン
    2:  28ピン
    4:  40/44ピン
    6:  64ピン
    8:  80ピン
    9: 100ピン
 
b:プログラムメモリの容量
    2:   4kByte(2kワード)
    3:   8kByte
    4:  16kByte
    5:  32kByte
    6:  64kByte
    7: 128kByte
 
V:駆動電圧
    ブランク: 2.0~5.5V駆動
    J       : 2.0~3.6V駆動(EEPROM無し)
    K       : 1.8~3.6V駆動(EEPROM有り) ※但しK20は1.8~5.5V
 
c,d:主な機能
    1x  汎用品
    2x  フラッシュセルフ書き込み可能
    3x  モータ制御向け
    5x  USB機能付き
    6x  LAN機能付き
    7x  アナログ機能強化
    8x  CAN(Controller Area Network、自動車内ネットワークの規格)
    9x  LCDドライバ内蔵
    x3  12bit A/Dコンバータ
    x5  中間メモリ容量24/48/96kbyte
 
x:温度範囲
    I: -40~85℃
 
yy:形状
    SP: SDIP
    SS: SSOP
    SO: SOIC
    ML: QFN
    PT: TQFP
    (ブレッドボード、ユニバーサル基板仕様の場合は"SP"を選択)
 
zzz:パターン


[C#]DataGridViewでプログラムから列の追加/削除を行う


列の追加


DataGridViewColumn col;
 
// Titleと表示名を指定して追加
dataGridView1.Columns.Add( "ColItemCode", "商品コード" );
 
// 列定義のオブジェクトを使って追加
col = new DataGridViewColumn();
col.Name = "ColItemName";
col.HeaderText = "商品名称";
dataGridView1.Columns.Add( col );




列の削除


// 全ての列を全削除
dataGridView1.Columns.Clear();
 
// 列名を指定して削除
dataGridView1.Columns.Remove( "ColItemName" );
 
// 列番号を指定して削除
dataGridView1.Columns.RemoveAt( 0 );




追加した列幅の調整


// ピクセル数指定で調整
dataGridView1.Columns[0].Width = 200;	
 
// 右端に余白が出ないように埋める(最右端の列で使用する)
dataGridView1.Columns[0].AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill; 
 
// ヘッダ以外のセル内容が表示される
dataGridView1.Columns[0].AutoSizeMode = DataGridViewAutoSizeColumnMode.AllCellsExceptHeader; 
 
// セル内容(ヘッダ含む)が完全に表示される幅
dataGridView1.Columns[0].AutoSizeMode = DataGridViewAutoSizeColumnMode.AllCells;