UNDERSTANDING LCDPROC DRIVERS

All of the drivers may be activated and compiled in; which is
activated and used depends on what parameters are given at the command
line.

One can better understand how drivers work by reading the comments
and documentation in drv_base.h.

There is a structure which is used to define all of the command functions
available from each driver.  This command structure is lcd_logical_driver.
The main use of this structure is for the lcd structure, which contains
all of the current drivers functions.

------------------------------ lcd_logical_driver ------------------------------
typedef struct lcd_logical_driver {
	int wid, hgt;			// size of the LCD in characters
	int cellwid, cellhgt;		// size of each LCD char cell in pixels
	char *framebuf;			// storage space for display

	// Functions which might be the same for all drivers...

	void (*clear) ();		// clear screen;
	void (*string)			// string at (x,y)
		(int x, int y, char lcd[]);

	void (*chr)			// character at (x,y)
		(int x, int y, char c);
	void (*vbar)			// vertical bar at (x,y)
		(int x, int y, int len);
	void (*hbar)			// horizontal bar at (x,y)
		(int x, int y, int len);
	void (*init_num) ();		//
	void (*num) (int x, int num);	// display number

	// Functions which should probably be implemented in each driver...

	int (*init)			// initialize driver
		(struct lcd_logical_driver * driver, char *args);
	void (*close) ();		// close
	void (*flush) ();		// flush
	void (*flush_box)		// flush box
		(int lft, int top, int rgt, int bot);
	int (*contrast) (int contrast);	// set contrast
	void (*backlight) (int on);	// set backlight
	void (*output) (int on);	// set outputs
	void (*set_char)		// set special characters
		(int n, char *dat);
	void (*icon)			// set up special icon
		(int which, char dest);
	void (*init_vbar) ();		// initialize vertical bar
	void (*init_hbar) ();		// initialize horizontal bar
	void (*draw_frame) ();		// draw frame

	char (*getkey) ();		// get a key (or 0)

	char * (*getinfo) ();		// get a string of info

} lcd_logical_driver;
------------------------------ lcd_logical_driver ------------------------------

The first thing that is done is that lcd_init (lcd.c) is called.  This function
first sets up basic housekeeping details.  Then it calls lcd_drv_init, which
initializes the basic functions for the lcd structure.

Each function loops through the list of currently loaded and active drivers.
The framebuffer is set to point to the appropriate framebuffer.  Then
the function determines what function to call (for each driver) - which
is one of three possibilities:

1. driver->function() > 0

   Call the driver function contained in driver->function();

2. driver->function() == NULL

   Ignore (no function);

3. driver->function() == -1

   Call the generic driver.

The generic driver functions are drv_base_* and are contained in drv_base.c

Note that these drv_base_* functions are also installed as part of the "base"
driver, and thus could be called not only once, but many times.

So... to clear the screen (after initializing the drivers) one might do
this - and it leads to the sequence of activities shown...

lcd.clear;
    --> lcd_drv_clear;
        --> driver->clear;
            --> drv_base_clear;
	--> driver->clear;
	    --> MtxOrb_clear;
        --> driver->clear;
	    --> drv_base_clear;
	--> driver->clear;

In the first case, the "base" driver is called.  In the second, the "MtxOrb"
driver is called, and it has a function to use.  In the third, an unnamed
driver is called, but it delegates back to the base function.  In the fourth,
the driver has no function; so it is ignored.

SUGGESTED SIMPLIFICATIONS

1. Remove the base driver entirely.

The base driver does not provide any substantial advantage, and significantly
complicates code.

2. Separate the input driver data from the output driver data.

This promotes easier comprehension and allows more specialization of each.
Some drivers may only have input or output components; some may have both.
This also permits coding such that only one output device is allowed
while multiple input devices are allowed.

3. Use only ONE output driver for each invocation of the server.

This simplifies coding - since there is then only one size, one width, one
height.  It also removes the need for scanning a big loop for functions to
execute.

Given these enhancements, all of drv_base.c could be eliminated, and
probably most or all of lcd.c.  It would dramatically reduce all of the
processing overhead necessary to handle screen output.

MORE SUGGESTIONS AND ENHANCEMENTS

1. Make input keys driver-specific.

This permits the use of each and every key without overlap.  For example,
it would keep a joystick button press from conflicting with a LCD display
button.

2. Specify the standard (configurable) set of keys for server actions
   in each driver.

This permits not only a unique standard configuration for each device,
it also hides what that is from the program itself.  If this is configurable,
it also makes it possible to adjust this set of keys during operation.

