written by Christian Vogelgsang under the GNU Public License V2
The IOWarrior boards (available at www.codemercs.com) are very nice experimental circuit boards connected via USB to you PC (with Linux or Windows) or Mac. They provide digital input and output ports and also an interface for a LCD with dot matrix display of up to 80 characters.
The IOWLCD library provides a small C-library that allows full control of the connected LCD. Furthermore a PERL interface for the library is available. IOWLCD is implemented with the USB Library and runs without special kernel modules on a Linux 2.6 system. Since the USB Library also supports other brands of Unices (including Mac OS X), the IOWLCD library should be portable to these platforms.
Key Features:
Revision 1.3 - 2.5.2004 - iowlcd-1.3.tgz
Revision 1.2 - 1.5.2004 - iowlcd-1.2.tgz
A minimal program using IOWLCD in C looks like this:
#include "iowlcd.h" usb_dev_handle *udh; /* init library */ if(iow_init()==0) puts("no IOWarriors found!"); /* open first warrior (0) */ udh = iow_open(0); if(udh==NULL) puts("can't open IOWarrior 0"); /* setup LCD */ if(iowlcd_setup(udh)==IOW_ERROR) puts("Can't setup LCD"); /* .... now use the LCD ... */ /* shutdown LCD */ iowlcd_shutdown(udh); /* close connection to IOWarrior */ iow_close(udh); iow_free(udh);
This little program just shows how to initialize and shut down the LCD in your program. You can open more IOWarriors simultaneously and just use different udhs.
int status = iowlcd_read_status(udh);
This command reads back the status information of the display. If the value ANDed with IOWLCD_BUSY (0x80) is non-zero then the display is busy. By ANDing the value with IOWLCD_ADDR_MASK (0x7f) the return value gives the current address of the text or character RAM on the display. See the LCD Controller manual for details.
iowlcd_set_text(udh,x,y,len,str); iowlcd_get_text(udh,x,y,len,str);
These two commands allow to write and read back a text string at str with length len to position (x,y) on the display.
With this library you can draw either horizontal or vertical bars to graphically visualize values. Both types of bars on a single display are currently not supported.
Each bar drawing mode must first be initialized by loading up the bar characters:
int iowlcd_load_vbar_chars(usb_dev_handle *udh); int iowlcd_load_hbar_chars(usb_dev_handle *udh);
After setting up the bar characters, the bars can be drawn with the following commands:
int iowlcd_draw_vbar(usb_dev_handle *udh,int x,int y,int h,int val); int iowlcd_draw_vbars(usb_dev_handle *udh,int x,int y,int h,int num,int *vals); int iowlcd_draw_hbar(usb_dev_handle *udh,int x,int y,int w,int val); int iowlcd_draw_hbars(usb_dev_handle *udh,int x,int y,int w,int num,int *vals);
For both types of bars, first the starting position (x,y) is given. For a vertical bar the height in characters and for a horizontal bar the width in characters is given. Then either a single value or an array of values is passed. An array of values draws more bars side by side and is especially for the vbar call a much more efficient way than drawing each bar with a single draw_hbar call.
The range of values that can be displayed in a bar depends on the size of the bar and the size of the characters itself. A LCD character has a layout of 5x8 pixels. Thus the horizontal bar can display 5 values and the vertical bar up to 8 values in a single character. By multiplying this size with the number of characters used for a bar gives the maximum range that can be displayed.
Examples:
The ASCII characters 0 up to 7 represent user-defined chars in an LCD. The bitmaps of these characters can be defined and uploaded to the LCD RAM. The IOWLCD library also allows to define these characters:
int iowlcd_load_chars(usb_dev_handle *udh,int offset,int num,unsigned char *bits);
This command uploads one or more characters to the LCD. offset gives the first character that will be defined (typically: 0). num gives the number of characters to be defined (8 will define all custom characters). Finally bits defines the bitmaps for all characters. Each character is defined by 8 bytes with the first bytes describing the bits of the topmost row. In each byte only the 5 LSBs are valid (due to the 5x8 char layout).
If you use bars (see last section) then some custom characters are already redefined for the bar graphics. Horizontal bars need 4 custom chars and vertical bars 7 chars. They are always allocated starting from offset 0. Thus with bar drawing only chars starting at offset 4 or 7 are user-definable.
The basic commands listed here are directly mapped to internal commands of the LCD controller chip. Therefore this is the low-level access interface to the LCD. They are often not directly used becaus most commands are wrapped into the API listed above for more convenient usage.
int iowlcd_enable(usb_dev_handle *udh); int iowlcd_disable(usb_dev_handle *udh);These two commands control the LCD interface of the IOWarrior chip. The interface must be enabled first on the IOWarrior, otherwise no LCD command will reach the LCD controller.
int iowlcd_read_status(usb_dev_handle *udh); int iowlcd_display_clear(usb_dev_handle *udh); int iowlcd_return_home(usb_dev_handle *udh); int iowlcd_entry_mode_set(usb_dev_handle *udh,int inc,int shift); int iowlcd_display_on_off(usb_dev_handle *udh,int display,int cursor,int blink); int iowlcd_shift(usb_dev_handle *udh,int display,int right); int iowlcd_set_function(usb_dev_handle *udh,int eight_bit,int two_line,int ten_dots); int iowlcd_set_cgram_addr(usb_dev_handle *udh,int addr); int iowlcd_set_ddram_addr(usb_dev_handle *udh,int addr); int iowlcd_write_data(usb_dev_handle *udh,int len,unsigned char *data); int iowlcd_read_data(usb_dev_handle *udh,int len,unsigned char *data);
The commands are listed here for completeness reasons. For an exact description of their usage and the parameters have a look in the manual of your LCD controller. The naming scheme tries to reflect the data sheet notation.
The LCD setup and shutdown in Perl looks like this:
#!/usr/bin/perl -w use iowlcd; package iowlcd; # init iowlcd for first warrior $num_warrior = iow_init(); print "found $num_warrior warriors\n"; $udh = iow_open(0); iowlcd_setup($udh); # ... now use LCD ... # shut down iowlcd iowlcd_shutdown($udh); iow_close($udh); iow_free();
Make sure to have the Perl module components iowlcd.pm and iowlcd.so in your Perl include path.
Similar to the C-API:
$status = iowlcd_read_status($udh); $busy = ($status & $IOWLCD_BUSY == $IOWLCD_BUSY) $addr = ($status & $IOWLCD_ADDR_MASK);
The Perl API is very similar to the C-API. Only the string conversion is more comfortable:
$result = iowlcd_set_text($udh,$x,$y,$string); ($result,$string) = iowlcd_get_text($udh,$x,$y);
The returned result value is either IOWLCD_OK or IOWLCD_ERROR.
Loading the bar characters (only one call is allowed!):
$result = iowlcd_load_hbar_chars($udh); $result = iowlcd_load_vbar_chars($udh);
Draw bars:
@values=(42,21,10); $result = iowlcd_draw_hbar($udh,$x,$y,$height,$value); $result = iowlcd_draw_vbar($udh,$x,$y,$width,$value); $result = iowlcd_draw_hbars($udh,$x,$y,$height,\@values); $result = iowlcd_draw_vbars($udh,$x,$y,$width,\@values);
You can either draw a single bar for a single value or an array of values with a more efficient single draw call.
The maximum displayable value for a bar can be calculated from the width or height:
$v_maxval = $IOWLCD_VBAR_UNITS * $height; $h_maxval = $IOWLCD_HBAR_UNITS * $width;
A new characters at $offset (0..7) can be loaded with:
$bits = "\x00\x01\x02\x03\x04\x05\x06\x07"; $result = iowlcd_load_chars($udh,$offset,1,$bits);
A more convenient way to design your characters might be:
@mychar = ( "00001110", "00010001", "00011011", "00010001", "00011111", "00010001", "00001110", "00000100" ); $bits=""; foreach(@mychar) { $bits.=pack("B8",$_); }