目次

オブジェクト指向風ワード定義

 Forthのワードは、ビルトイン、ユーザーの定義を
 問わず、使いたいときに指定することが可能。

 オブジェクト指向のプログラミング言語では
 オブジェクトに続けて、メソッド名を並べる
 記法を使います。

 AmForhでも、オブジェクト指向風のワード定義ができます。

 「.」(dot)を利用して、SFR(Special Function Register)の
 1ビットを操作するワードを定義してみましょう。

 ポートの指定ビットをセット、リセットするワードは
 次のように記述すればOK。

: pbo.set 1 swap lshift PORTB c@ or PORTB c! ;
: pbo.clr 1 swap lshift $ff xor PORTB c@ and PORTB c! ;
: pco.set 1 swap lshift PORTC c@ or PORTC c! ;
: pco.clr 1 swap lshift $ff xor PORTC c@ and PORTC c! ;
: pdo.set 1 swap lshift PORTD c@ or PORTD c! ;
: pdo.clr 1 swap lshift $ff xor PORTD c@ and PORTD c! ;

: pb5.set 5 pbo.set ;
: pb5.clr 5 pbo.clr ;
: pb4.set 4 pbo.set ;
: pb4.clr 4 pbo.clr ;
: pb3.set 3 pbo.set ;
: pb3.clr 3 pbo.clr ;
: pb2.set 2 pbo.set ;
: pb2.clr 2 pbo.clr ;
: pb1.set 1 pbo.set ;
: pb1.clr 1 pbo.clr ;
: pb0.set 0 pbo.set ;
: pb0.clr 0 pbo.clr ;

: pc5.set 5 pco.set ;
: pc5.clr 5 pco.clr ;
: pc4.set 4 pco.set ;
: pc4.clr 4 pco.clr ;
: pc3.set 3 pco.set ;
: pc3.clr 3 pco.clr ;
: pc2.set 2 pco.set ;
: pc2.clr 2 pco.clr ;
: pc1.set 1 pco.set ;
: pc1.clr 1 pco.clr ;
: pc0.set 0 pco.set ;
: pc0.clr 0 pco.clr ;

: pd7.set 7 pdo.set ;
: pd7.clr 7 pdo.clr ;
: pd6.set 6 pdo.set ;
: pd6.clr 6 pdo.clr ;
: pd5.set 5 pdo.set ;
: pd5.clr 5 pdo.clr ;
: pd4.set 4 pdo.set ;
: pd4.clr 4 pdo.clr ;
: pd3.set 3 pdo.set ;
: pd3.clr 3 pdo.clr ;
: pd2.set 2 pdo.set ;
: pd2.clr 2 pdo.clr ;
: pd1.set 1 pdo.set ;
: pd1.clr 1 pdo.clr ;
: pd0.set 0 pdo.set ;
: pd0.clr 0 pdo.clr ;

 ポート出力のためにSFRの中にあるレジスタを
 オブジェクトと見なし、「.」の左に配置。
 メソッドは「.」の右に配置しておけばワード
 の機能を説明していることを理解できるはず。

 一部のワードをテストすると、以下。



 ポートCの出力の動作を調べると、次のようになります。



 ポートDの出力の動作を調べると、以下。



 ポートの出力をセット、クリアできるようにしたなら
 DDRの各ビットを入力、出力にするためのワードを定義。

: pb.out 1 swap lshift DDRB c@ or DDRB c! ;
: pb.in 1 swap lshift $ff xor DDRB c@ and DDRB c! ;
: pc.out 1 swap lshift DDRC c@ or DDRC c! ;
: pc.in 1 swap lshift $ff xor DDRC c@ and DDRC c! ;
: pd.out 1 swap lshift DDRD c@ or DDRD c! ;
: pd.in 1 swap lshift $ff xor DDRD c@ and DDRD c! ;

: pb5.out 5 pb.out ;
: pb5.in 5 pb.in ;
: pb4.out 4 pb.out ;
: pb4.in 4 pb.in ;
: pb3.out 3 pb.out ;
: pb3.in 3 pb.in ;
: pb2.out 2 pb.out ;
: pb2.in 2 pb.in ;
: pb1.out 1 pb.out ;
: pb1.in 1 pb.in ;
: pb0.out 0 pb.out ;
: pb0.in 0 pb.in ;

: pc5.out 5 pc.out ;
: pc5.in 5 pc.in ;
: pc4.out 4 pc.out ;
: pc4.in 4 pc.in ;
: pc3.out 3 pc.out ;
: pc3.in 3 pc.in ;
: pc2.out 2 pc.out ;
: pc2.in 2 pc.in ;
: pc1.out 1 pc.out ;
: pc1.in 1 pc.in ;
: pc0.out 0 pc.out ;
: pc0.in 0 pc.in ;

: pd7.out 7 pd.out ;
: pd7.in 7 pd.in ;
: pd6.out 6 pd.out ;
: pd6.in 6 pd.in ;
: pd5.out 5 pd.out ;
: pd5.in 5 pd.in ;
: pd4.out 4 pd.out ;
: pd4.in 4 pd.in ;
: pd3.out 3 pd.out ;
: pd3.in 3 pd.in ;
: pd2.out 2 pd.out ;
: pd2.in 2 pd.in ;
: pd1.out 1 pd.out ;
: pd1.in 1 pd.in ;
: pd0.out 0 pd.out ;
: pd0.in 0 pd.in ;


 DDRBのワードをテストすると、以下。



 DDRCの内容を調べると、次のようになります。



 DDRDの内容を調べると、以下。



 DDR、OUTPUTをワードで定義したので、INPUTも
 作っておきます。
 スタックに入力論理値があるように定義。

: pbi dup 1 swap lshift PINB c@ and swap rshift 1 and ;
: pci dup 1 swap lshift PINC c@ and swap rshift 1 and ;
: pdi dup 1 swap lshift PIND c@ and swap rshift 1 and ;

: pib5 5 pbi ;
: pib4 4 pbi ;
: pib3 3 pbi ;
: pib2 2 pbi ;
: pib1 1 pbi ;
: pib0 0 pbi ;

: pic5 5 pci ;
: pic4 4 pci ;
: pic3 3 pci ;
: pic2 2 pci ;
: pic1 1 pci ;
: pic0 0 pci ;

: pid7 7 pdi ;
: pid6 6 pdi ;
: pid5 5 pdi ;
: pid4 4 pdi ;
: pid3 3 pdi ;
: pid2 2 pdi ;
: pid1 1 pdi ;
: pid0 0 pdi ;

 動作をテストすると、以下。



 オブジェクト指向風のワード定義では、スタックに
 パラメータを置かないで済ませることも可能。

 入力論理値は、スタックに存在すると
 作業台にスタックを利用と、意識して
 メソッドを使えるとプログラム作成が
 楽になります。

 ここまでのワード定義では、基礎となるワードを
 定義し、そのワードを利用する派生ワードを定義
 する作業を繰り返しています。

 Unixのalignのように、ワードに別名を与えて
 より使いやすくことも可能。

 Forthインタプリタは、自己増殖型のプログラミングが
 可能なので、自分にとってわかりやすいワード名を使う
 ことで、開発効率を上げられます。

 システム開発の効率が上がるのなら、新しいワードを
 定義し、そのワードを使うワードを作成というループ
 を構成するのが、よいと考えています。


目次

inserted by FC2 system