What and why is the HDT
=======================

HDT stand for Hardware Description Table and is a concept to
enable hardware drivers to easily detect and use hardware 
components like servos, motors or sensors attached to the 
"EyeCon" EyeBot Controller.

HDT consists of two main parts.
1.) HDT access procedures
2.) HDT data structures


HDT access procedures
---------------------
These procedures are part of RoBIOS and are used by hardware
drivers to determine where and if a hardware component exists.
Currently there are four basic procedures that can be found
in /mc/robios/hdt.c.

int HDT_Validate(void);
/* is used by RoBIOS to check and initialize the HDT data structure */

void *HDT_FindEntry(TypeID typeid,DeviceSemantics semantics);
/* is used by device drivers to search for first entry that matches semantics
   and returns a pointer to the corresponding data structure */

DeviceSemantics HDT_FindSemantics(TypeID typeid, int x);
/* look for xth entry of given Typ and return its semantics */

int HDT_TypeCount(TypeID typeid);
/* count entries of given Type */

char *HDT_GetString(TypeID typeid,DeviceSemantics semantics)
/* get semantic string */

These procedures can not be used by user programs !


HDT data structure
------------------
The HDT data structure is a separate data file (/mc/hdtdata).
Each EyeBot or other hardware configuration needs its own
HDT data. These data files contain all the information about where
a hardware component is attached to the EyeBot and how to control it.

The HDT data structure itself consists of two main parts:
1.) the data structures of various hdt components
2.) the HDT list itself

1.) the data structure for a component, like a motor, contains
	all information a driver needs to know.
e.g.:
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

These xxxx_type structures are defined in /mc/robios/include/hdt.h.

2.) the HDT list itself contains all the hardware components attached
	and their semantics.

e.g.:
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
};

e.g. first line:
MOTOR           : it is a motor
MOTOR_LEFT      : its semantics
"LEFT"          : a readable string for testroutines
&motor0         : a pointer to the motor0 data structure


The INFO and END_OF_HDT entries are mandatory!
The semantics and all other constants are defined in /mc/robios/include/hdt.h.


How it works
------------
This is demonstrated in the motor-demo (/mc/demos/motor).
At first you need a handle for your motor:

MotorHandle     leftmotor;

Then you have to initialize this handle, by calling MOTORInit with the
semantics of the motor you want to initialize. MOTORInit now searches
the HDT for a motor with the given semantics and if found calls the 
motor driver to initialize the motor.

leftmotor = MOTORInit(LEFTMOTOR);

Now you can use the motor by setting a speed value. This function
calls the motor driver and sets a previously initialized motor
to the given speed.

MOTORDrive (leftmotor,50);

After using the motor you have to release it again. This function
calls the motor drivers which than released the motor.

MOTORRelease (leftmotor);

Using all other hardware components works in a similar way.
Consult "/mc/docs/library.html" for further details about the functions.


Flashing/Downloading
--------------------

Flashing:

With the HDT-concept the flashing procedure has changed a little bit.
The HDT has to be flashed seperately behind the ROBIOS.

The procedure depends on the size of the used flashrom.

1 Mbit:
The 1 Mbit flash is physically divided into 8 blocks of 16KB each. It is possible
to erase and program each block seperately. The first 7 blocks are destined to
hold the RoBIOS. The last block is reserved for the HDT data structure that 
therefore can grow up to a maximum size of 16KB, which is fairly enough.
 
Flash RoBIOS with:
flash 11111110 robios.hex 0

and the hdt with:
flash 00000001 hdtdata.hex $1c000 


4 MBit:
The 4 Mbit flash is physically divided into 8 blocks of 64KB each. It is possible
to erase and program each block seperately. The first 2 blocks are destined to
hold the RoBIOS AND the HDT. The remaining 6 block are used to save up to three 
userprograms which is handled by the USR-menue of the RoBIOS. Obviously is there 
no way to store the HDT data structure seperately at the same position like in the 
1MBit case. To avoid the waste of a complete 64KB block (the third block) for holding 
the HDT a detour has to be taken. The HDT with a maximum size of 16KB is flashed at 
the beginning of the third block. Beware, a previously saved userprogram (slot 1) will 
be deleted by this action. After having restarted the EyeBot, the RoBIOS recognizes 
the new HDT and performs a reprogramming of the second block in the following way:
The first 48KB of the second block, containing the second part of the RoBIOS, is
copied into the RAM, now the first 16KB of the third block, containing the new HDT,
is copied directly behind it. This new 64KB block is now flashed back into the second
block and the third block is cleared, ready to hold a new userprogram. With this action
the first 128KB of the flashrom contain compared to the 1Mbit flash the same data at 
identical addresses.

Flash RoBIOS with:
flash 11000000 robios.hex 0

and the hdt with:
flash 00100000 hdtdata.hex $20000 


Downloading:

Since V.1.4 of RoBIOS exists the possibility of downloading the HDT or the RoBioS via 
a serial interface (1-3). There is no difference between the two flash chips with this
method. Enter 'USR' menue and initiate 'LD' just like downloading a USER program.
Initiate the transmission of a hdtxxx.hex or robios.hex file on your remote computer.
RoBIOS detects a new HDT/RoBIOS automatically and flashes it correctly. This is much
faster and easier than the 'flashing'-method above.


Description of all HDT entries
------------------------------

Battery Info
------------
typedef struct
{
    int     version;
   	short   low_limit;
	short   high_limit;
}battery_type;


e.g.
battery_type battery = {0,550,850};

int version: 
The maximum driver version for which this entry is compatible.
Because newer drivers will surely need more information this tag prevents this driver
from reading more information than actually available.

short low_limit: 
The value the AD-converter channel 1 measures shortly before the batteries are empty. 
This defines the lower limit of the tracked battery voltage.

short   high_limit:
The value the AD-converter channel 1 measures with fully loaded batteries. 
This defines the upper limit of the tracked battery voltage.


Bumper
------
typedef struct
{
    int     driver_version;
    int     tpu_channel;
    int     tpu_timer;
    short   transition;
}bump_type;

e.g.
bump_type bumper0 = {0, 6, TIMER2, EITHER};

int driver_version: 
The maximum driver version for which this entry is compatible.
Because newer drivers will surely need more information this tag prevents this driver
from reading more information than actually available.

int tpu_channel:
The tpu channel the bumper is attached to. Valid values are 0..15
Each bumper needs a tpu channel to signal a 'bump'-occurrence.

int tpu_timer:
The tpu timer that has to be used. Valid values are TIMER1, TIMER2
If a 'bump' is detected the corresponding timer-value is stored for later calculations.
TIMER1 runs at a speed of 4MHz-8MHz (depending on CPUclock)
TIMER2 runs at a speed of 512kHz-1MHz (depending on CPUclock)

short transition:
React on a certain transition. Valid values are RISING, FALLING, EITHER
To alter the behaviour of the bumper, the type of transition the TPU reacts on can be choosen.


Compass
-------
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;

e.g.
compass_type compass = {0,13,(void*)IOBase, 2,(void*)IOBase, 4, (BYTE*)IOBase, 0};

short version:
The maximum driver version for which this entry is compatible.
Because newer drivers will surely need more information this tag prevents this driver
from reading more information than actually available.

short channel: 
TPU channel that is connected to the compass for clocking the datatransfer. Valid values are 0..15

void* pc_port:
Pointer to an 8Bit register/latch (out). PC is the start signal for the compass

short pc_pin:
This is the bitnumber in the register/latch addressed by pc_port. Valid values are 0..7

void* cal_port:
Pointer to an 8Bit register/latch (out). CAL is the calibration start signal for the compass.
It can be set to NULL if no calibration is needed (In this case never call the calibration function).

short cal_pin:
This is the bitnumber in the register/latch addressed by cal_port. Valid values are 0..7

void* sdo_port:
Pointer to an 8Bit register/latch (in). SDO is the serial data output connection of the compass.
The driver will read out the serial data timed by the TPU channel.

short sdo_pin:
This is the bitnumber in the register/latch addressed by sdo_port. Valid values are 0..7


Information
-----------
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;

e.g.
info_type roboinfo0  = {0,VEHICLE,SER115200,RTSCTS,SERIAL2,AUTOLOAD,0,AUTOBRIGHTNESS,BATTERY_ON,16,VERSION,NAME,0};

int version: 
The maximum driver version for which this entry is compatible.
Because newer drivers will surely need more information this tag prevents this driver
from reading more information than actually available.

int id:
The current environment on which RoBIOS is running. Valid values are PLATFORM, VEHICLE, WALKER
It is accessible via OSMachineType().

int serspeed:
The default baudrate for the default serial interface. 
Valid values are SER9600, SER19200, SER38400, SER57600 SER115200

int handshake:
The default handshake mode for the default serial interface. 
Valid values are NONE, RTSCTS

int interface:
The default serial interface for the transfer of userprograms. 
Valid values are SERIAL1, SERIAL2, SERIAL3

int auto_download;
The download mode during the main menu of RoBIOS. After startup of RoBIOS it can
permanently scan the default serial port for a file-download. If it detects a file
it automatically downloads it (set to AUTOLOAD). 
If it should automatically run this file too set the value to (AUTOLOADSTART).
If it is set to NO_AUTOLOAD no scanning is performed.

int res1:
this is a reserved value (formerly it was used for the state of the radio remote control
which has now its own HDT entry. So always set it to 0)

int cammode:
The default camera mode. Valid values are AUTOBRIGHTNESS, NOAUTOBRIGHTNESS

int battery_display:
Switch the battery status display on or off. Valid values are BATTERY_ON, BATTERY_OFF

int CPUclock:
The clock rate(MHz) the MC68332 microprocessor should run with.
It is accessible via OSMachineSpeed().

float user_version:
The user defined version number of the actual HDT. This nr is just for information and
will be displayed in the HRD-menue of the RoBIOS!

String10 name;
The user defined unique name for this EyeBot. This name is just for information and
will be displayed in the main-menue of the RoBIOS! It is accessible via OSMachineName().

unsigned char robi_id;
The user defined unique id for this EyeBot. This id is just for information and will
be displayed in the main-menu of the RoBIOS! Is is accessible via OSMachineID(). It can
temporarily be changed in Hrd/Set/Rmt

unsigned char res2:
this is a reserved value (formerly it was used for the robot-ID of the radio remote control
which has now its own HDT entry. So always set it to 0)


Infrared sensor
---------------
typedef struct
{
    int     driver_version;
    int     tpu_channel;
}ir_type;

e.g.
ir_type   ir0 = {0, 8};

int driver_version: 
The maximum driver version for which this entry is compatible.
Because newer drivers will surely need more information this tag prevents this driver
from reading more information than actually available.

int tpu_channel:
The tpu channel the ir-sensor is attached to. Valid values are 0..15
Each ir-sensor needs a tpu channel to signal the recognition of an obstacle.


Infrared TV Remote
------------------
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;

This is the new extended IRTV struct. RoBIOS can still handle the old version 0-format which will
cause RoBIOS to use the settings for the standard Nokia VCN 620. But only with the new version 1
is it possible to use the IRTV to control the 4 keys in RoBIOS.

old settings (version 0):
e.g. for a SoccerBot:
irtv_type irtv = {0, 11, TPU_HIGH_PRIO};  /* Sensor connected to TPU 11 (=S10) */

e.g. for an EyeWalker:
irtv_type irtv = {0, 0, TPU_HIGH_PRIO};   /* Sensor connected to TPU 0 */

new settings (version 1 for Nokia VCN620 and activated RoBIOS control):
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: 
The maximum driver version for which this entry is compatible.
Because newer drivers will surely need more information this tag
prevents this driver from reading more information than actually available.

short channel:
The TPU channel the IRTV-sensor is attached to. Valid values are 0..15.
Normally, the sensor is connected to a free servo port. However on the
EyeWalker there is no free servo connector so the sensor should be
connected to a motor connector (a small modification is needed for this
- see manual).

short priotity:
The IRQ-priority of the assigned TPU channel. This should be set to
TPU_HIGH_PRIO to make sure that no remote commands are missed.

short use_in_robios:
If set to REMOTE_ON, the remote control can be used to control the 4 EyeBot keys in RoBIOS.
Use REMOTE_OFF to disable this feature.

int type:
int length:
int tog_mask:
int inv_mask:
int mode:
int bufsize:
int delay:
These are the settings to configure a certain remote control. They are exactly the same as
the parameters for the IRTVInit() system call. Above is an example for the default Nokia VCN620
control. The settings can be found by using the irca-program.

int code_key1:
int code_key2:
int code_key3:
int code_key4:
These are the codes of the 4 buttons of the remote control that should match the 4 EyeBot keys.
For the Nokia remote control all codes can be found in the header file 'IRnokia.h'.


Latch
-----
With this entry you tell robios where to find the In/Out-Latches and how many of them are installed
typedef struct
{
  short   version;
  BYTE*   out_latch_address;
  short   nr_out;
  BYTE*   in_latch_address;
  short   nr_in;
} latch_type;

e.g.
latch_type latch = {0, (BYTE*)IOBase, 1 , (BYTE*)IOBase, 1};

int version: 
The maximum driver version for which this entry is compatible.
Because newer drivers will surely need more information this tag prevents this driver
from reading more information than actually available.

BYTE*   out_latch_address:
Start address of the out-latches.

short   nr_out:
Amount of 8Bit out-latches

BYTE*   in_latch_address;
Start address of the in-latches.

short   nr_in;
Amount of 8Bit in-latches


motor
-----
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;

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

int driver_version: 
The maximum driver version for which this entry is compatible.
Because newer drivers will surely need more information this tag prevents this driver
from reading more information than actually available.

int tpu_channel:
The tpu channel the motor is attached to. Valid values are 0..15
Each motor needs a pwm (pulse width modulated) signal to drive with different speeds.
The internal TPU of the MC68332 is capable of generating this signal on up to 16 
channels. The value to be entered here is given through the actual hardware design.

int tpu_timer:
The tpu timer that has to be used. Valid values are TIMER1, TIMER2
The tpu generates the pwm signal on an internal timer basis. There are two different
timers that can be used to determine the actual period for the pwm signal.
TIMER1 runs at a speed of 4MHz up to 8MHz depending on the actual CPU-clock
which allows periods between 128Hz and 4MHz (with 4MHz basefrq) up to 256Hz - 8MHz(with 8MHz)
TIMER2 runs at a speed of 512kHz up to 1MHz depending on the actual CPU-clock
which allows periods between 16Hz and 512kHz (512kHz base) up to 32Hz - 1MHz (1MHz base)
To determine the actual TIMERx speed use the following equation:
TIMER1[MHz] = 4MHz * (16MHz + (CPUclock[MHz] % 16))/16
TIMER2[MHz] = 512kHz * (16MHz + (CPUclock[MHz] % 16))/16

int pwm_period:
This value sets the length of one pwm period in Hz according to the selected timer.
The values are independent (in a certain interval) of the actual CPU-clock.
The maximal frequency is the actual TPU-frequency divided by 100 in order 
to guarantee 100 different energy levels for the motor. This implies a maximum period of 
40-80kHz with TIMER1 and 5-10kHz with TIMER2 (depending on the cpuclock). 
The minimal frequency is therefore the Timerclock divided by 32768 which implies
128-256Hz (Timer1) and 16-32Hz (Timer2) as longest periods (depending on CPUclock).
To be independent of the actual CPUclock a safe interval is given by 256Hz - 40kHz (Timer1)
and 32Hz - 5kHz (Timer2).
To avoid a 'stuttering' of the motor, the period should not be set too slow, but on the 
other hand a too fast period reduces the remaining calculation time of the CPU.

BYTE* out_pin_address:
The I/O Port address the driver has to use. Valid value is a 32bit address.
To control the direction a motor is spinning a H-bridge is used. This type of hardware 
is normally connected via two pins to a latched output. The outlatches of the EyeBot-
plattform are for example located at OUTBASE and the succeeding addresses.
One of these two pins is set for forward movement and the other for backward movement.

short out_pin_fbit:
The portbit for forward drive. Valid values are 0..7
This is the bitnumber in the latch addressed by out_pin_address.

short out_pin_bbit:
The portbit for backward drive. Valid values are 0..7
This is the bitnumber in the latch addressed by out_pin_address.

BYTE* conv_table: 
The pointer to a conversion table to adjust different motors. 
Valid values are NULL or a pointer to a table containing 101 bytes.
Usually two motors behave slightly differently when they get exactly the same amount of
energy. This will for example show up in a differential drive, when a vehicle should
drive in a straight line but moves in a curve. To adjust one motor to another a conversion
table is needed. For each possible speed (0..100%) an appropriate value has to be entered
in the table to obtain the same speed for both motors. It is wise to adapt the faster 
motor because at high speeds the slower one can't keep up, you would need speeds of more
than 100% ! 
Note: The table can be generated by software using the connected encoders.


Position Sensitive Device (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;

e.g.
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: 
The maximum driver version for which this entry is compatible.
Because newer drivers will surely need more information this tag prevents this driver
from reading more information than actually available.

short tpu_channel:
The master TPU channel for serial timing of the PSD communication. Valid values are 0..15
This TPU channel is not used as an in- or output. It is just used as a high resolution timer
needed to generate exact communication timing. If there are more than 1 PSD connected to
the hardware each PSD has to use the same TPU channel. The complete group or just a selected 
subset of PSDs can 'fire' simultaneously. Depending on the position of the PSDs it is 
preferable to avoid measure cycles of adjacent sensors to get correct distance values.

BYTE* in_pin_address:
Pointer to an 8Bit register/latch to receive the PSD measuring result.

short in_pin_bit:
The portbit for the receiver. Valid values are 0..7
This is the bitnumber in the register/latch addressed by in_pin_address.

short in_logic:
Type of the received data. Valid values are AH, AL
Some registers negate the incoming data. To compensate this, active low(AL) has to be selected.

BYTE* out_pin_address:
Pointer to an 8Bit register/latch to transmit the PSD control signal.
If two or more PSDs are always intended to measure simultaneously the same outpin can be 
connected to all of these PSDs. This saves valuable register bits.  

short out_pin_bit:
The portbit for the transmitter. Valid values are 0..7
This is the bitnumber in the register/latch addressed by out_pin_address.

short out_logic:
Type of the transmitted data. Valid values are AH, AL
Some registers negate the outgoing data. To compensate this, active low(AL) has to be selected.

short* dist_table:
The pointer to a distance conversion table.
A PSD delivers an 8bit measure result which is just a number. Due to inaccuracy of the 
result only the upper 7 bits are used (div 2). To obtain the corresponding distance in mm
a lookup table with 128 entries is needed. Since every PSD slightly deviates in its measured 
distance from each other, each PSD needs its own conversion table to guarantee correct
distances. The tables have to be generated 'by hand'. The testprogram included in RoBIOS
shows the raw 8bit PSD value for the actual measured distance. By slowly moving a plane object
away from the sensor the raw values change accordingly. Now take every second raw value and
write down the corresponding distance in mm. That's it.  


Quadrature encoder
------------------
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;

e.g.
quad_type decoder0 = {0, 3, 2, MOTOR_LEFT, 1234, 2.34};

int driver_version: 
The maximum driver version for which this entry is compatible.
Because newer drivers will surely need more information this tag prevents this driver
from reading more information than actually available.

int master_tpu_channel:
The first TPU channel used for quadrature decoding. Valid values are 0..15
To perform decoding of the motor encoder signals the TPU occupies two adjacent channels.
By changing the order of the two channels the direction of counting can be inverted.

int slave_tpu_channel:
The second TPU channel used for quadrature decoding. Valid values are master_tpu_channel +|- 1

DeviceSemantics motor:
The semantics of the attached motor.
To test a specific encoder via the internal RoBIOS function the semantics of the coupled 
motor is needed.

unsigned int clicksPerMeter:
This parameter is used only if the connected motor powers a driving wheel.
It is the number of clicks that are delivered by the encoder covering the distance of 1 meter. 

float maxspeed:
This parameter is used only if the connected motor powers a driving wheel.
It is the maximum speed of this wheel in m/s. 


Remote Control
--------------
With this entry you can specify the default behaviour of the remote radio control

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

e.g.
remote_type remote = {0, ID, REMOTE_ON, SERIAL2, SER115200, IMAGE_FULL};

int version: 
The maximum driver version for which this entry is compatible.
Because newer drivers will surely need more information this tag prevents this driver
from reading more information than actually available.

short robi_id;
The user defined unique id (0-255) for this EyeBot. This id is just for information and will
be displayed in the main-menu of the RoBIOS! Is is accessible via OSMachineID(). It can
temporarily be changed in Hrd/Set/Rmt

short remote_control:
The default control mode for the EyeBot. Valid values are:
REMOTE_ON  (the display is forwarded to and the keys are send from a remote PC)
REMOTE_OFF (normal mode), 
REMOTE_PC  (only the PC sends data i.e. button press is activated only)
REMOTE_EYE (only the EyeBot sends data i.e. display information only)

short interface:
The default serial interface for the radio transfer
Valid values are SERIAL1, SERIAL2, SERIAL3

short serspeed:
The default baudrate for the selected serial interface. 
Valid values are SER9600, SER19200, SER38400, SER57600, SER115200

short imagemode:
The mode in which the images of the camera should be transferred to the PC.
Valid values are IMAGE_OFF (no image), IMAGE_REDUCED (reduced quality), IMAGE_FULL (original frame)


Servo
-----
typedef struct
{
  int     driver_version;
  int     tpu_channel;
  int     tpu_timer;
  int     pwm_period;
  int     pwm_start;
  int     pwm_stop;
}servo_type;

e.g.
servo_type servo0 = {1,  0, TIMER2, 20000, 700, 1700};

int driver_version: 
The maximum driver version for which this entry is compatible.
Because newer drivers will surely need more information this tag prevents this driver
from reading more information than actually available.

int tpu_channel:
The tpu channel the servo is attached to. Valid values are 0..15
Each servo needs a pwm (pulse width modulated) signal to turn into different positions.
The internal TPU of the MC68332 is capable of generating this signal on up to 16 
channels. The value to be entered here is given through the actual hardware design.

int tpu_timer:
The tpu timer that has to be used. Valid values are TIMER1, TIMER2
The tpu generates the pwm signal on an internal timer basis. There are two different
timers that can be used to determine the actual period for the pwm signal.
TIMER1 runs at a speed of 4MHz up to 8MHz depending on the actual CPU-clock
which allows periods between 128Hz and 4MHz (with 4MHz basefrq) up to 256Hz - 8MHz (with 8MHz)
TIMER2 runs at a speed of 512kHz up to 1MHz depending on the actual CPU-clock
which allows periods between 16Hz and 512kHz (512kHz base) up to 32Hz - 1MHz (1MHz base)
To determine the actual TIMERx speed use the following equation:
TIMER1[MHz] = 4MHz * (16MHz + (CPUclock[MHz] % 16))/16
TIMER2[MHz] = 512kHz * (16MHz + (CPUclock[MHz] % 16))/16

int pwm_period:
This value sets the length of one pwm period in microseconds (us).
A normal servo needs a pwm_period of 20ms which equals 20000us. For any
exotic servo this value can be changed accordingly. It is always preferable
to take TIMER2 because only here are enough discrete steps available to position
the servo accurately.
The values are in a certain interval (see motor) independent of the CPUclock.

int pwm_start:
This is the minimal hightime of the pwm period in us. Valid values are 0..pwm_period
To position a servo the two extreme positions for it have to be defined. In the normal
case a servo needs to have a minimal hightime of 0.7ms (700us) at the beginning of each pwm
period. This is also one of the two extreme positions a servo can take.

int pwm_stop:
This is the maximum hightime of the pwm period. Valid values are 0..pwm_period.
Depending on the rotation direction of a servo, one may choose pwm_stop less than
or greater than pwm_start.
To position a servo the two extreme positions for it have to be defined. In the normal
case a servo needs to have a maximum hightime of 1.7ms (1700us) at the beginning of each
pwm period. This is also one of the two extreme positions a servo can take. 
All other positions of the servo are linear interpolated in 256 steps between these two 
extremes. 
Hint: If you don't need the full range the servo offers you can adjust the start and stop
parameters to a smaller 'window' like 1ms to 1.5ms and gain a higher resolution in this
bounds. Or the other way round, you can enlarge the 'window' to adjust the values to the
real degrees the servo changes its position: 
Take for example a servo that covers a range of 210 degrees. Simply adjust the stop value
to 1.9ms. If you now set values between 0 and 210 you will reach the two extremes in steps
corresponding to the real angles. Values higher than 210 would not differ from the result 
gained by the value of 210!


Startimage
-----------
typedef BYTE image_type[16*64];

e.g.
image_type startimage = {0xB7,0x70,0x1C,...0x00};

Here you can enter your own startup image as a bytearray (16*64 = 1024Bytes). 
It is a 128x64 Pixel B/W picture where each pixel is represented by a bit.


Startmelody 
-----------
no typedef

e.g.
int startmelody[] = {1114,200, 2173,200, 1114,200, 1487,200, 1669,320, 0};

Here you can enter your own melody that will be played at startup.
It is a list of integer pairs.  The first value indicates the frequency,
the second the duration in 1/100s of the tone. As last value there must
be single 0 in the list.


VW Drive
--------
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;

e.g.
vw_type drive = {0, DIFFERENTIAL_DRIVE, {QUAD_LEFT, QUAD_RIGHT, 0.21}};

int driver_version: 
The maximum driver version for which this entry is compatible.
Because newer drivers will surely need more information this tag prevents this driver
from reading more information than actually available.

int drive_type:
Define the type of the actual used drive.
Valid values are DIFFERENTIAL_DRIVE (ACKERMAN_DRIVE, SYNCHRO_DRIVE, TRICYCLE_DRIVE)
The following parameters depend on the selected drive type.

DIFFERENTIAL_DRIVE:
The differential drive is made up of two parallel independent wheels with the kinematic 
center right between them. Obviously two encoders with the connected motors are needed.

    DeviceSemantics quad_left:
    The semantics of the encoder used for the left wheel. 

    DeviceSemantics quad_right:
    The semantics of the encoder used for the right wheel.
    
    float wheel_dist:
    The distance (meters) between this two wheels to determine the kinematic center.


Waitstates
----------
typedef struct
{
	short     version;
	short     rom_ws;
	short     ram_ws;
	short     lcd_ws;
	short     io_ws;
	short     serpar_ws;
}waitstate_type;


e.g.
waitstate_type waitstates = {0,3,0,1,0,2};

int version: 
The maximum driver version for which this entry is compatible.
Because newer drivers will surely need more information this tag prevents this driver
from reading more information than actually available.

short rom_ws:
Waitstates for the ROM access
Valid values (for all waitstates):
waitstates = 0..13, Fast Termination = 14, External = 15

short ram_ws:
Waitstates for the RAM access

short lcd_ws:
Waitstates for the LCD access

short io_ws:
Waitstates for the Input/Output latches access

short serpar_ws:
Waitstates for the 16c552 Serial/Parallel Port Interface access


------------------------
Thomas Bräunl, Klaus Schmitt, Michael Kasper, 1996-2003
