HDTとは何でなぜ必要か
=======================

HDTはハードウェアー記述テーブル（Hardware Description Table）
の略で、ハードウェアー・ドライバー簡単に検出し、サーボ、DC
モーター、センサーのような装置をEyebotプラットフォームに取り
付けて使うことを可能にするための一つの構想です。

HDTは２つの部分から構成されています。
1.) HDTアクセス関数
2.) HDTデータ構造

　HDTアクセス関数
---------------------
これら関数はRoBiOSの一部であり、ドライバーがハードウェアー
の場所や接続の有無を判断するのに使われます。最新版には４つ
の基本関数があり、/mc/robios/hdt.cで確認することができます。

int HDT_Validate(void);
　RobiOSがHDTデータ構造をチェックしたり初期化するのに使われ
　ます。

void *HDT_FindEntry(TypeID typeid,DeviceSemantics semantics);
　デバイスドライバーが、内容を一致させ、データ構造に対応する
　ポインターを返すための登録情報を探すのに使われます。

DeviceSemantics HDT_FindSemantics(TypeID typeid, int x);
　x番目の登録情報を探し、その内容を返すのに使われます。

int HDT_TypeCount(TypeID typeid);
　与えられた型の登録情報数をカウントします。

char *HDT_GetString(TypeID typeid,DeviceSemantics semantics)
　内容説明を表示します。

これらの関数はユーザープログラムから使うことはできません！

　HDTデータ構造
------------------
HDTデータ構造は独立したデータファイルです。(/mc/hdtdata)
各Eyebotやその他の装置の設定には独自のHDTデータが必要です。
これらのデータファイルには、装置がどこに取り付けられていて
どのように制御するのかというすべての情報が記入されています。

HDTデータ構造は２つの部分から構成されています。
1.) 種々のHDT装置のデータ構造
2.) HDTリスト

1.) モーターなどの装置のデータ構造はドライバーに必要なすべて
　　の情報を含んでいます。

例えば：
motor_type motor0 = {0,  0, TIMER1, 8196, (void*)(OutBase+2), 6, 7, (BYTE*)&motconv0};
0               : the maximum driver version for which this entry is sufficient
0               : the tpu channel the motor is attached to
TIMER2          : the tpu timer that has to be used
8196            : pwm period in Hz
OutBase+2       : the I/O Port address the driver has to use
6               : the portbit for forward drive
7               : the portbit for backward drive
motconv0        : the pointer to a conversion table to adjust different motors

このような「xxxx_type」構造が/mc/robios/include/hdt.hの中で定義されています。

2.) HDTリストは取り付けられた装置とその内容について記述されています。

例えば：
HDT_entry_type HDT[] =
{
    MOTOR,MOTOR_RIGHT,"RIGHT",(void *)&motor0,
    MOTOR,MOTOR_LEFT,"LEFT",(void *)&motor1,

    PSD,PSD_FRONT,"FRONT",(void *)&psd1,

    INFO,INFO,"INFO",(void *)&roboinfo,

    END_OF_HDT,UNKNOWN_SEMANTICS,"END",(void *)0
};

例えば最初の行は
MOTOR           : it is a motor
MOTOR_LEFT      : its semantics
"LEFT"          : a readable string for testroutines
&motor0         : a pointer to the motor0 data structure


INFOとEND_OF_HDT登録は必須です！
その情報や他のすべての定数については/mc/robios/include/hdt.hの中
で定義されています。


どのように使うのか
------------------------
これはモーター・デモ(/mc/demos/motor)の実例です。
まず、モーターのハンドルが必要です。：

MotorHandle     leftmotor;

次に、使用するモーターの情報を使ってMOTORInitを呼び出し、ハンドル
を初期化しかければなりません。

MOTORInit関数は与えられた情報を使ってモーターを探し、初期化のため
にモーター用ドライバーを呼び出します。

leftmotor = MOTORInit(LEFTMOTOR);

これで、回転速度を設定することによってモーターを使うことができます。
この関数は、モーター用ドライバーを呼び出し、上記で初期化されたモー
ターに与えられた回転速度を設定します。

MOTORDrive (leftmotor,50);

モーターを使用した後で、再び解除する必要があります。
この関数は解除するモーターを呼び出します。

MOTORRelease (leftmotor);

他のすべての装置についても同様に使用します。
関数の詳細については/mc/EXECLIBを参照してください。

メモリー書き込み/ダウンロード
------------------------------

メモリー書き込みによる方法:

HDT構想を使った書き込み手順は少し異なります。
HDTはRoBiOSとは別に書き込む必要があります。

手順はFlash-ROMのメモリー容量に依存します。

1 Mビット：
1 MビットのFlashメモリーは物理的に各16KBの８ブロックに分割されて
います。最初の７ブロックはRoBiOSで使用されます。最後のブロックは
HDTデータ構造に予約されています。よって、この領域は最大で16KBで
かなり十分な容量です。 

RoBiOSを下記のように書き込みます。：
flash 11111110 robios.hex 0

HDTは下記のようにします。：
flash 00000001 hdtdata.hex $1c000 


4 Mビット：
4 MビットのFlashメモリーは物理的に各64KBの８ブロックに分割されて
いて、各ブロックに対して別々に消去したり書き込んだりできます。
最初の２ブロックがRoBiOSとHDTで使われます。残りの６ブロックには
RoBiOSのUSRメニューを使って３つまでのユーザープログラムを書き込
むことができます。明らかに1Mビットの場合のように分割して同じ位置
にHDTデータ構造を書き込むことができません。HDTを入れるときに容量
64KBのブロック（第３ブロック）を無駄にしないためには、回り道をす
る必要があります。最大16KBの容量をもつHDTを第３ブロックの最初の
領域に書き込みます。この操作によって、先に保存してあるユーザー
プログラム（スロット１）が消去されることに注意してください。
Eyebotを再起動するとRoBiOSが新しいHDTを認識し、次のようにして第２
ブロックにデータを書き込まれます。：
まず、第２ブロックにあるRoBiOSの領域の48KBのデータがRAMにコピーさ
れます。そして、新しいHDTの領域である第３ブロックの初めの16KBのデ
ータが続けてRAMにコピーされます。この新しい64KBのデータはFlash-ROM
の第２ブロックに書き込まれます。第３ブロックは消去され、新たにユー
ザープログラムを書き込むことができるようになります。この操作によっ
て、1MビットFlach-ROMの場合と同じデータが同じアドレスに格納される
ことになります。

RoBiOSを下記のように書き込みます。：
flash 11000000 robios.hex 0

HDTは下記のようにします。：
flash 00100000 hdtdata.hex $20000 


ダウンロードによる方法：

RoBiOSのV.1.4以降のバージョンではHDTやRoBioSをシリアルインターフェ
ース(1-3)経由でダウンロードすることができます。どちらのFlashメモリー
の場合にも違いはありません。ユーザープログラムをダウンロードするよう
に'USR'メニューから'LD'を選択し、パソコン上の「hdtxxx.hex」または
「robios.hex」ファイルの転送を開始します。RoBiOSは自動的に新しいHDT
またはRoBiOSを検出し、適切にデータを書き込みます。これは上述のメモリー
書き込みによる方法よりも速くて簡単です。


HDTへの登録情報の記入方法
---------------------------

バッテリー情報
-----------------
typedef struct
{
    int     version;
   	short   low_limit;
	short   high_limit;
}battery_type;

例：
battery_type battery = {0,550,850};

int version: 
　互換性のあるドライバーの最大バージョン数を指定します。
　新しいドライバーほど多くの情報を必要としており、このタグ
　によってドライバーが必要以上の情報を読み取ることを防止
　します。

short low_limit: 
　バッテリーがなくなる直前におけるADコンバーターの１チャン
　ネルの測定値を指定します。これにより搭載しているバッテリー
　の最小限界電圧値を定義します。

short   high_limit:
　完全に充電したバッテリーを取り付けたときのADコンバーター
　の１チャンネルの測定値を指定します。これにより搭載している
　バッテリーの最大限界電圧値を定義します。


バンパー
---------
typedef struct
{
    int     driver_version;
    int     tpu_channel;
    int     tpu_timer;
    short   transition;
}bump_type;

例：
bump_type bumper0 = {0, 6, TIMER2, EITHER};

int driver_version: 
　互換性のあるドライバーの最大バージョン数を指定します。
　新しいドライバーほど多くの情報を必要としており、このタグ
　によってドライバーが必要以上の情報を読み取るこ　とを防止
　します。

int tpu_channel:
　バンパーが取り付けられているTPUのチャンネル番号を指定し
　ます。0〜15の値が有効です。各バンパーは「衝突」信号を検
　出するためにそれぞれ一つのTPUチャンネルが必要です。

int tpu_timer:
　TPUタイマーを指定する必要があります。設定値は、TIMER1と
　TIMER2が有効です。もし「衝突」を検出したら、後の計算用
　にタイマー値が格納されます。

　TIMER1は4MHz-8MHzの範囲で使用します。(CPUクロックに依存)
　TIMER2は512Khz-1MHzの範囲で使用します。(CPUクロックに依存)

short transition:
　信号検出方法を指定します。設定値は、RISING、FALLING、
　EITHERが有効です。バンパーの作用方法を切り替えるために、
　TPUの処理方法を選択することができます。


コンパス
----------
typedef struct
{
  short   version;
  short   channel;
  void*   pc_port;
  short   pc_pin;
  void*   cal_port;
  short   cal_pin;
  void*   sdo_port;
  short   sdo_pin;
}compass_type;

例：
compass_type compass = {0,13,(void*)IOBase, 2,(void*)IOBase, 4, (BYTE*)IOBase, 0};

short version:
　互換性のあるドライバーの最大バージョン数を指定します。
　新しいドライバーほど多くの情報を必要としており、このタグ
　によってドライバーが必要以上の情報を読み取ることを防止
　します。

short channel: 
　データ転送の同期をとるためにコンパスに接続するTPUのチャン
　ネル番号を指定します。設定値は、0〜15が有効です。

void* pc_port:
　8ビットのレジスター／ラッチ（出力）を表すポインターを指定
　します。このPC信号がコンパスの測定開始信号になります。

short pc_pin:
　pc_portで指定したレジスター／ラッチにおけるPC信号用のビット
　番号を指定します。設定値は、0〜7が有効です。

void* cal_port:
　8ビットのレジスター／ラッチ（出力）を表すポインターを指定
　します。このCAL信号がコンパスの校正開始信号になります。もし
　も校正の必要がない場合にはNULLを指定することができます（こ
　の場合には校正用関数を呼び出すことはできません）。

short cal_pin:
　cal_portで指定したレジスター／ラッチにおけるCAL信号用のビッ
　ト番号を指定します。設定値は、0〜7が有効です。

void* sdo_port:
　8ビットのレジスター／ラッチ（入力）を表すポインターを指定
　します。このSDO信号はコンパスのシリアルデータ出力端子に接
　続されます。ドライバーはTPCチャンネル信号と同期をとってシ
　リアルデータを読み取ります。

short sdo_pin:
　sdo_portで指定したレジスター／ラッチにおけるSDO信号用のビッ
　ト番号を指定します。設定値は、0〜7が有効です。


システム情報
-------------
typedef struct
{
	int     version;
	int     id;
	int     serspeed;
	int     handshake;
	int     interface;
	int     auto_download;
	int     res1;
	int     cammode;
    int     battery_display;
    int     CPUclock;
    float   user_version;
    String10 name;
    unsigned char res2;    
}info_type;

例：
info_type roboinfo0  = {0,VEHICLE,SER115200,RTSCTS,SERIAL2,AUTOLOAD,0,AUTOBRIGHTNESS,BATTERY_ON,16,VERSION,NAME,0};

int version: 
　互換性のあるドライバーの最大バージョン数を指定します。
　新しいドライバーほど多くの情報を必要としており、このタグ
　によってドライバーが必要以上の情報を読み取ることを防止
　します。

int id:
　RoBiOSが動いている現在の環境を指定します。設定値は、PLATFORM, 
　VEHICLE, WALKERが有効です。OSMachineType()関数を使って読み出す
　ことができます。

int serspeed:
　デフォルトのシリアルポートにおけるデフォルトの通信速度
　を指定します。設定値は、SER9600、SER19200、SER38400、SER57600、
　SER115200が有効です。

int handshake:
　デフォルトのシリアルポートにおけるデフォルトの同期方法
　を指定します。設定値は、NONE、RTSCTSが有効です。

int interface:
　ユーザープログラムを転送するためのデフォルトシリアルポー
　トの番号を指定します。設定値は、SERIAL1、SERIAL2、SERIAL3
　が有効です。

int auto_download;
　RoBiOSのメインメニューに関するダウンロードモードを指定しま
　す。AUTOLOADモードに設定されているときには、RoBiOSが起動す
　ると、デフォルトのシリアルポートをスキャンし、ダウンロード
　用ファイルを探します。ファイルを検出すると自動的にダウンロ
　ードして実行します。NO_AUTOLOADモードに設定されているときに
　はスキャンは行われません。

int res1:
　これは予備の設定です。（かつては無線遠隔操作の状態変数として
　使用されていました。現在は独自のHDT登録を行います。したがって
　常に0を設定します。）

int cammode:
　デフォルトのカメラモードを指定します。設定値は、AUTOBRIGHTNESS
　とNOAUTOBRIGHTNESSが有効です。

int battery_display:
　バッテリー状態表示の有無を指定します。設定値は、BATTERY_ONと
　BATTERY_OFFが有効です。

int CPUclock:
　MC68332マイクロプロセッサーのクロック周波数(MHz)を指定します。
　OSMachineSpeed()関数を使って呼び出すことができます。

float user_version:
　ユーザーが決めた現在のHDTバージョン数を指定します。この値は単に
　情報として使用され、RoBiOSのHRDメニューで表示されます。

String10 name;
　ユーザーが決めたこのEyeBotの名前を指定します。この名前は単に情報
　として使用され、RoBiOSのメインメニューで表示されます。
　OSMachineName()関数を使って呼び出すことができます。

unsigned char robi_id;
　ユーザーが決めたこのEyeBotのID番号を指定します。このID番号は
　単に情報として使用され、RoBiOSのメインメニューで表示されます。
　OSMachineID()関数を使って呼び出すことができます。メニューから
　Hrd/Set/Rmtを順に操作することによって一時的に変更することも
　できます。

unsigned char res2:
　これは予備の設定です。（かつては無線遠隔操作のロボットIDとして
　使用されていました。現在は独自のHDT登録を行います。したがって
　常に0を設定します。）


赤外線センサー
---------------
typedef struct
{
    int     driver_version;
    int     tpu_channel;
}ir_type;

例：
ir_type   ir0 = {0, 8};

int driver_version: 
　互換性のあるドライバーの最大バージョン数を指定します。
　新しいドライバーほど多くの情報を必要としており、このタグ
　によってドライバーが必要以上の情報を読み取ることを防止
　します。

int tpu_channel:
　赤外線センサーの取り付けられたTPUのチャンネル番号を指定
　します。設定値は、0〜15が有効です。各赤外線センサーは障
　害物認識信号を検出するためにそれぞれ一つのTPUチャンネル
　が必要です。


テレビ用赤外線リモコン
-------------------------
typedef struct
{
  short   version;
  short   channel;
  short   priority;
  /* new in version 1: */
  short   use_in_robios;
  int     type;
  int     length;
  int     tog_mask;
  int     inv_mask;
  int     mode;
  int     bufsize;
  int     delay;
  int     code_key1;
  int     code_key2;
  int     code_key3;
  int     code_key4;
} irtv_type;

これは新規に拡張されたIRTV構造です。RoBiOSではバージョン0の古
い設定様式を使ってもノキアVCN 620標準設定を取り扱うことができ
ます。しかし、新しいバージョンを使う場合だけ、赤外線リモコンに
よってRoBIOSの４つのキーを操作することができます。

古い設定(バージョン 0の様式):
SoccerBotの例：
irtv_type irtv = {0, 11, TPU_HIGH_PRIO};  /* TPU 11 (=S10)にセンサーを接続 */

EyeWalkerの例：
irtv_type irtv = {0, 0, TPU_HIGH_PRIO};   /* TPU 0にセンサーを接続 */

新しい設定 (バージョン 1の様式、ノキアVCN620):
irtv_type irtv = {1, 11, TPU_HIGH_PRIO, REMOTE_ON, SPACE_CODE, 15, 0x0000, 0x03FF, DEFAULT_MODE, 1, -1, RC_RED, RC_GREEN, RC_YELLOW, RC_BLUE}; 


short version: 
　互換性のあるドライバーの最大バージョン数を指定します。
　新しいドライバーほど多くの情報を必要としており、このタグ
　によってドライバーが必要以上の情報を読み取ることを防止
　します。

short channel:
　IRTVセンサーが取り付けられているTPUのチャンネル番号を指定
　します。設定値は、0〜15が有効です。通常、センサーは空いて
　いるサーボ用コネクターに接続します。しかし、EyeWalkerにつ
　いては空いているサーボ用コネクターが無いので、DCモーター用
　コネクターに接続しています。（このためには簡単な改造が必要
　です。詳細はマニュアルを見てください。）

short priotity:
　割当てられているTPUチャンネルのIRQ優先度を指定します。
　TPU_HIGH_PRIOを設定するようにしてください。それにより、
　リモコンの指示が取りこぼされなくなります。

short use_in_robios:
　REMOTE_ONを設定するとEyeBotの４つのキーをRobiosで使うこと
　ができます。REMOTE_OFFを設定するとこの機能が無効になります。

int type:
int length:
int tog_mask:
int inv_mask:
int mode:
int bufsize:
int delay:
　これらは特定のリモコンのための設定値を指定します。IRTVInit()
　関数を呼び出すときと完全に同じパラメータを使う必要があります。
　上記ではデフォルトのノキアVCN620のための例を示してあります。
　これらの設定は「irca」というサンプルプログラムの中で使用され
　ています。

int code_key1:
int code_key2:
int code_key3:
int code_key4:
　これらはEyeBotの４つのキーとリモコンの４つのボタンを対応させる
　ために指定します。ノキア製リモコン用のコードが「IRnokia.h」とい
　うヘッダーファイルの中で使用されています。


ラッチ
-------
　取り付けられている入出力用のラッチの場所と個数を指定します。

typedef struct
{
  short   version;
  BYTE*   out_latch_address;
  short   nr_out;
  BYTE*   in_latch_address;
  short   nr_in;
} latch_type;

例：
latch_type latch = {0, (BYTE*)IOBase, 1 , (BYTE*)IOBase, 1};

int version: 
　互換性のあるドライバーの最大バージョン数を指定します。
　新しいドライバーほど多くの情報を必要としており、このタグ
　によってドライバーが必要以上の情報を読み取ることを防止
　します。

BYTE*   out_latch_address:
　出力用ラッチの開始アドレスを指定します。

short   nr_out:
　８ビット出力用ラッチの個数を指定します。

BYTE*   in_latch_address;
　入力用ラッチの開始アドレスを指定します。

short   nr_in;
　８ビット入力用ラッチの個数を指定します。


DCモーター
-------------

typedef struct
{
	int     driver_version;
	int     tpu_channel;
	int     tpu_timer;
	int     pwm_period;
	BYTE*   out_pin_address;
	short   out_pin_fbit;
	short   out_pin_bbit;
    BYTE*   conv_table;     /* NULL if no conversion needed */
}motor_type;

例：
motor_type motor0 = {1,  0, TIMER1, 8196, (void*)(OutBase+2), 6, 7, (BYTE*)&motconv0)};

int driver_version: 
　互換性のあるドライバーの最大バージョン数を指定します。
　新しいドライバーほど多くの情報を必要としており、このタグ
　によってドライバーが必要以上の情報を読み取ることを防止
　します。

int tpu_channel:
　DCモーターが取り付けられているTPUのチャンネル番号を指定し
　ます。設定値は、0〜15が有効です。各DCモーターは様々な回転数
　で駆動するために、それぞれPWM（パルス幅変調）信号が必要です。
　MC68332に内蔵されているTPUは16チャンネルまでのPWM信号を生成
　することができます。ここで入力する値は、実際の回路に基づいて
　決めます。

int tpu_timer:
　TPUタイマーを指定する必要があります。指定値は、TIMER1と
　TIMER2が有効です。PWM信号は内部タイマーに基づいて生成され
　ます。２種類のタイマーがあり、PWM信号の周期を決めるのに
　使うことができます。TIMER1はCPUクロック周波数に依存して
　4MHzから8MHzまでの速度で機能し、信号周期はCPUが4MHzの場合
　には128Hz〜4MHz、8MHzの場合には256Hz〜8MHzになります。
　TIMER2はCPUクロック周波数に依存して512KHzから1MHzまでの
　速度で機能し、信号周期はCPUが512KHzの場合には16Hz〜512KHz、
　1MHzの場合には32Hz〜1MHzになります。

　実際にTIMERxの速度を決定するには下記の式を使います。：
　　TIMER1[MHz] = 4MHZ * (16MHz + (CPUクロック周波数[MHz] % 16))/16
　　TIMER2[MHz] = 512KHZ * (16MHz + (CPUクロック周波数[MHz] % 16))/16

int pwm_period:
　１つのPWM信号の周期をHzで指定します。この値はCPU周波数
　とは独立しています。最大周波数はモーターを100段階の速度
　で制御するためにTPU周波数の100分の1になります。よって、
　最大周波数はTIMER1では40-80KHz、TIMER2では5-10KHzになり
　ます（CPUクロック周波数に依存します）。最小周波数はタイ
　マーのクロック周波数を32768で割った値、すなわち最大周期
　に対応して、128-256Hz (Timer1)と16-32Hz (Timer2)になりま
　す。モーターの「戻り」を防止するためには、周期をあまり遅
　くしすぎないように設定する必要があります。一方、速くしす
　ぎるとTPUの計算時間が足らなくなります。

BYTE* out_pin_address:
　入出力ポートのアドレスを指定します。設定値は、32ビットの
　アドレス値です。モーターの回転方向を制御するためにH型ブリ
　ッジを使います。このタイプの回路では、通常、１つのラッチ
　にある２つの出力端子を接続します。例えば、EyeBot基板の出力
　用ラッチはOUTBASEとそれにつづくアドレスにあります。２つの
　端子のうち１つは正転用に他方は反転用に設定します。

short out_pin_fbit:
　正転用ポートのビット番号を指定します。設定値は、0〜７が有
　効です。これはout_pin_addresで指定したラッチのビット番号に
　なります。

short out_pin_bbit:
　反転用ポートのビット番号を指定します。設定値は、0〜７が有
　効です。これはout_pin_addresで指定したラッチのビット番号に
　なります。

BYTE* conv_table: 
　モーター特性の違いを補正するための変換表へのポインターを指定し
　ます。設定値は、NULLあるいは101バイトの変換表へのポインター
　値が有効です。通常、同じように電力を供給しても、２つのモーター
　はわずかに異なった回転速度になります。例えば、移動ロボットを
　前進させたくても曲がって進む場合に役立ちます。1つのモーターを
　もう1つのモーターに対して調整するときに、１つの変換表が必要に
　なります。設定可能な各速度(0〜100%)において、両側のモーターが
　同じ回転数になるように変換表を作成しなければなりません。回転速
　度の速いモーターを調整するのは上手なやり方です。高速回転の時に
　遅い方のモーター速度を速くすることは設定値を100％以上にしなけれ
　ばならず不可能だからです！

　ヒント：接続されているエンコーダーを使って変換表を作成すること
　　　　　ができます。


距離検出センサー (PSD)
-------------------------------
typedef struct
{
	short   driver_version;
	short   tpu_channel;
	BYTE*   in_pin_address;
	short   in_pin_bit;
	short   in_logic;
	BYTE*   out_pin_address;
	short   out_pin_bit;
	short   out_logic;
	short*  dist_table;
}psd_type;

例：
psd_type psd0 = {0, 14, (BYTE*)(Ser1Base+6), 5, AL, (BYTE*)(Ser1Base+4), 0, AL, (short*)&dist0};
psd_type psd1 = {0, 14, (BYTE*)InBase, 2, AH, (BYTE*)OutBase, 0, AH, (short*)&dist1};

int driver_version: 
　互換性のあるドライバーの最大バージョン数を指定します。
　新しいドライバーほど多くの情報を必要としており、このタグ
　によってドライバーが必要以上の情報を読み取ることを防止
　します。

short tpu_channel:
　PSDセンサーとシリアルの同期をとるために使うTPUのチャンネル
　番号を指定します。設定値は、0〜15が有効です。このTPUチャン
　ネルは入力または出力端子として使いません。正確な同期信号を
　生成するために必要な高分解能をもつタイマーとしてのみ使いま
　す。もし２つ以上のPSDセンサーを接続する場合には、各PSDセン
　サーは同じTPUチャンネルを使わなければなりません。すべての
　または選択されたPSDセンサーは同じタイミングで測定をすること
　ができます。PSDセンサーの位置にもよりますが、正しい距離デー
　タを得るために接近しているセンサーの測定周期を近づけないよ
　うにしてください。

BYTE* in_pin_address:
　PSDセンサーからのデータを受信する8ビットのレジスター／ラッチ
　のポインターを指定します。

short in_pin_bit:
　in_pin_addressで指定したレジスター／ラッチにおいてPSD信号を受
　信するポートのビット番号を指定します。設定値は、0〜7が有効です。

short in_logic:
　受信するPSDデータ形式を指定します。設定値は、AHとALが有効です。
　レジスターによっては入力データが無効になるものがあります。その
　場合にはアクティブ・ロー(AL)設定をしてください。

BYTE* out_pin_address:
　PSDセンサーへ制御信号を送信するための8ビットのレジスター／ラッチ
　のポインターを指定します。もし２つ以上のPSDセンサーを接続する場合
　には同じ出力端子を使うことができます。これにより、レジスター上のビ
　ット信号を有効に使うことができます。

short out_pin_bit:
　out_pin_addressで指定したレジスター／ラッチにおいてPSD制御信号を
　送信するポートのビット番号を指定します。設定値は、0〜7が有効です。

short out_logic:
　送信するPSD制御信号形式を指定します。設定値は、AHとALが有効です。
　レジスターによっては出力データが無効になるものがあります。その
　場合にはアクティブ・ロー(AL)設定をしてください。

short* dist_table:
　距離変換表のポインターを指定します。PSDセンサーは8ビットの測定
　値を生成します。不正確さがあるため上位7ビットの結果だけを使いま
　す（半分になります）。mmで距離を表すために128の値をもつ検索表が
　必要になります。どのPSDセンサーもわずかに測定値にばらつきがあり、
　測定値を保障するためにはPSDセンサーごとにその変換表が必要になり
　ます。表は各自が「手で」作成しなければなりません。RoBiOSのテスト
　プログラムでは、実際に測定した距離を表す8ビットの生データが表示
　されます。センサーから測定面をゆっくりと遠ざけると、それに従って
　生データが変化します。各生データに対応する距離をmm単位で測定し
　それを記述することで変換表を作ることができます。


パルスエンコーダー
------------------
typedef struct
{
	int     driver_version;
	int     master_tpu_channel;
	int     slave_tpu_channel;
    DeviceSemantics motor;
    unsigned int clicksPerMeter;
    float   maxspeed;       /* (in m/s) only needed for VW-Interface */
}quad_type;

例：
quad_type decoder0 = {0, 3, 2, MOTOR_LEFT, 1234, 2.34};

int driver_version: 
　互換性のあるドライバーの最大バージョン数を指定します。
　新しいドライバーほど多くの情報を必要としており、このタグ
　によってドライバーが必要以上の情報を読み取ることを防止
　します。

int master_tpu_channel:
　パルスエンコーダーで使用する第１TPUチャンネル番号を指定
　します。設定値は、0〜15が有効です。モーターのエンコーダー
　信号を処理するために、２つの連続したTPUチャンネルが使われ
　ます。使用する２つのチャンネルの接続順番を変えることにより
　測定している回転方向を反転させることができます。

int slave_tpu_channel:
　パルスエンコーダーで使用する第２TPUチャンネル番号を指定
　します。設定値は、master_tpu_channelで設定した値の±１が
　有効です。

DeviceSemantics motor:
　接続されているモーターの名前を指定します。RoBiOSに内蔵さ
　れている関数である特定のエンコーダーをテストするときに、
　接続されているモーターの名前が必要です。

unsigned int clicksPerMeter:
　このパラメータはモーターで車輪を駆動する場合にのみ使われ
　ます。1mの距離を進むときに得られるエンコーダーのカウント数
　を指定します。

float maxspeed:
　このパラメータはモーターで車輪を駆動する場合にのみ使われ
　ます。車輪の最大速度をm/sの単位で指定します。


無線遠隔制御
--------------
　無線遠隔操作の設定を行うのに使います。

typedef struct
{
    int version;
    short robi_id;
    short remote_control;
    short interface;
    short serspeed;
    short imagemode;
} remote_type;

例：
remote_type remote = {0, ID, REMOTE_ON, SERIAL2, SER115200, IMAGE_FULL};

int version: 
　互換性のあるドライバーの最大バージョン数を指定します。
　新しいドライバーほど多くの情報を必要としており、このタグ
　によってドライバーが必要以上の情報を読み取ることを防止
　します。

short robi_id;
　EyeBot用にユーザーが決めた独自のID番号を指定します。設定
　値は、0〜255が有効です。このID番号は単に情報として使用さ
　れ、RoBiOSのメインメニューで表示されます。OSMachineID()関
　数を使って呼び出すことができます。メニューからHrd/Set/Rmt
　を順に操作することによって一時的に変更することもできます。

short remote_control:
　EyeBot用にデフォルトの制御モードを指定します。設定値は、
　REMOTE_ON (画面が転送され、遠隔パソコンからキーコマンド
　が送信されます）、REMOTE_OFF (通常モードです)、REMOTE_PC 
　(パソコンからデータを転送するだけです。すなわち、ボタン
　入力のみが使えます。）、REMOTE_EYE (Eyebotのみがデータを
　送ります。すなわち画面情報のみが送られてきます。)が有効
　です。

short interface:
　無線通信用のデフォルトのシリアルインターフェースを指定し
　ます。設定値は、SERIAL1、SERIAL2、SERIAL3が有効です。

short serspeed:
　選択されたシリアルインターフェースにおけるデフォルトの
　通信速度を指定します。設定値は、SER9600、SER19200、
　SER38400、SER57600、SER115200が有効です。

short imagemode:
　カメラ画像をパソコンに転送するためのモードをを指定します。
　設定値は、IMAGE_OFF(画像なし)、IMAGE_REDUCED (画質を低下
　させた画像)、IMAGE_FULL (撮影したままの画像)が有効です。


サーボモーター
-----------------
typedef struct
{
  int     driver_version;
  int     tpu_channel;
  int     tpu_timer;
  int     pwm_period;
  int     pwm_start;
  int     pwm_stop;
}servo_type;

例：
servo_type servo0 = {1,  0, TIMER2, 20000, 700, 1700};

int driver_version: 
　互換性のあるドライバーの最大バージョン数を指定します。
　新しいドライバーほど多くの情報を必要としており、このタグ
　によってドライバーが必要以上の情報を読み取ることを防止
　します。

int tpu_channel:
　サーボモーターが取り付けられているTPUのチャンネル番号を
　指定します。設定値は、0〜15が有効です。各サーボモーター
　は回転角度を変えるためにPWM(pulse width modulated)信号が
　必要です。MC68332チップのTPUは16チャンネルまでの信号を
　生成することができます。ここで入力する値hあ実際の回路に
　基づいて決めます。

int tpu_timer:
　TPUタイマーを指定する必要があります。指定値は、TIMER1と
　TIMER2が有効です。PWM信号は内部タイマーに基づいて生成され
　ます。２種類のタイマーがあり、PWM信号の周期を決めるのに
　使うことができます。TIMER1はCPUクロック周波数に依存して
　4MHzから8MHzまでの速度で機能し、信号周期はCPUが4MHzの場合
　には128Hz〜4MHz、8MHzの場合には256Hz〜8MHzになります。
　TIMER2はCPUクロック周波数に依存して512KHzから1MHzまでの
　速度で機能し、信号周期はCPUが512KHzの場合には16Hz〜512KHz、
　1MHzの場合には32Hz〜1MHzになります。

　実際にTIMERxの速度を決定するには下記の式を使います。：
　　TIMER1[MHz] = 4MHZ * (16MHz + (CPUクロック周波数[MHz] % 16))/16
　　TIMER2[MHz] = 512KHZ * (16MHz + (CPUクロック周波数[MHz] % 16))/16

int pwm_period:
　１つのPWM信号の周期をマイクロ秒(μs)で指定します。通常の
　サーボモーターは20msすなわち20000μsのPWM周期が必要です。
　他の異なるサーボを使用するときには、それにあわせてこの値を
　変えることができます。サーボの正確な位置信号を生成するため
　に常にTIMER2を使用してください。この値はCPUクロック周波数と
　は別のある特定の間隔を表す値（モーターの説明書を参照）です。

int pwm_start:
　PWM信号におけるハイレベルの最小時間間隔をμsで指定します。
　設定値は、0〜pwm_periodで指定した値が有効です。サーボの
　位置決めを行うために、２つの極端な位置を定義する必要が
　あります。通常の場合、サーボは0.7ms (700μs)のハイレベル
　の最小時間間隔が各PWM信号の初めに必要で、この値がその極端
　な位置信号の一つになります。

int pwm_stop:
　PWM信号におけるハイレベルの最大時間間隔をμsで指定します。
　設定値は、0〜pwm_periodで指定した値が有効です。サーボの
　回転方向によって、pwm_startより小さな値あるいは大きな値
　を選択することができます。サーボの位置決めを行うために、
　２つの極端な位置を定義する必要があります。通常の場合、
　サーボは1.7ms (1700μs)のハイレベルの最大時間間隔が各PWM
　信号の初めに必要で、この値もその極端な位置信号の一つにな
　ります。これにより

　ヒント：もしもサーボのもつ最大回転範囲を動かす必要のない
　　　　　場合には、このstartとstopパラメータを調整すること
　　　　　ができます。これにより、1ms〜1.5msのようにより幅の
　　　　　小さなPWM信号が得られ、より分解能を高くすることが
　　　　　できます。逆に、幅の大きなPWM信号にして大きな範囲
　　　　　の回転をさせることもできます。：
　　　　　例えば、210度の回転範囲をもつサーボを使ってみまし
　　　　　ょう。単純にstopを1.9msに設定します。ここで、0から
　　　　　210の値を設定すると、実際の角度に対応して、最低から
　　　　　最大角度まで変化させることができます。210以上の値を
　　　　　指定すると、210を指定した結果と同じになります。


スタートアップ画像
--------------------
typedef BYTE image_type[16*64];

例：
image_type startimage = {0xB7,0x70,0x1C,...0x00};

　バイト配列データによって、ユーザー独自のスタートアップ画像
　を指定することができます。設定値は、各ビットが画素に対応す
　る128x64画素の白黒画像データです。


スタートアップ音楽
-------------------
no typedef

例：
int startmelody[] = {1114,200, 2173,200, 1114,200, 1487,200, 1669,320, 0};

　スタートアップ時に演奏されるユーザー独自の音楽を指定します。
　設定値は、ペアになった整数値のリストです。最初の値が周波数、
　２番目の値が1/100sの単位で表される維持時間です。リストの最後
　の値は０を１つ記入しなければなりません。


車輪の駆動
----------
typedef struct
{
	int     version;
    int     drive_type;
    drvspec drive_spec; /* -> diff_data */
}vw_type;

    typedef struct
    {
        DeviceSemantics quad_left;
        DeviceSemantics quad_right;
        float           wheel_dist; /* meters */
    }diff_data;

例：
vw_type drive = {0, DIFFERENTIAL_DRIVE, {QUAD_LEFT, QUAD_RIGHT, 0.21}};

int driver_version: 
　互換性のあるドライバーの最大バージョン数を指定します。
　新しいドライバーほど多くの情報を必要としており、このタグ
　によってドライバーが必要以上の情報を読み取ることを防止
　します。

int drive_type:
　駆動方法を指定します。設定値は、DIFFERENTIAL_DRIVE (ACKERMAN_DRIVE、
　SYNCHRO_DRIVE、TRICYCLE_DRIVE)が有効です。以下のパラメーターは
　選択された駆動方法によって変わります。

DIFFERENTIAL_DRIVEの場合：
　作動駆動方式は、平行で運動中心がその中間にある独立した
　２つの車輪で構成されています。モータに接続するために
　２つのエンコーダーが必要になります。

    DeviceSemantics quad_left:
　　　左車輪に使っているエンコーダーの名前を指定します。

    DeviceSemantics quad_right:
　　　右車輪に使っているエンコーダーの名前を指定します。

    float wheel_dist:
　　　運動中心を決定するために２つの車輪の間隔(m)を指定します。


ウェイト状態
--------------
typedef struct
{
	short     version;
	short     rom_ws;
	short     ram_ws;
	short     lcd_ws;
	short     io_ws;
	short     serpar_ws;
}waitstate_type;


例：
waitstate_type waitstates = {0,3,0,1,0,2};

int version: 
　互換性のあるドライバーの最大バージョン数を指定します。
　新しいドライバーほど多くの情報を必要としており、このタグ
　によってドライバーが必要以上の情報を読み取ることを防止
　します。

short rom_ws:
　ROMアクセスのウェイト状態を指定します。設定値は、下記が
　有効です（他のパラメータについても同様です）。
　　waitstates = 0〜13、
　　Fast Termination = 14、
　　External = 15

short ram_ws:
　RAMアクセスのウェイト状態を指定します。

short lcd_ws:
　LCDアクセスのウェイト状態を指定します。

short io_ws:
　入出力用ラッチのアクセスのウェイト状態を指定します。

short serpar_ws:
　16c552のシリアル／パラレルポートのアクセスのウェイト
　状態を指定します。


