lpt_driver Documentation An Linux LPT user-space driver for hacking with external LCD displays and DS1620 Temp Sensors. 30 May 98 Version 0.27 Carl D. Walker Copywrite (c) under GPL
NOTE: RUN AS ROOT! (Needed for ioperm() call to work) Command Line: lpt_driver [-offset [-][degrees_c]] The -offset switch, followed by a offset in degrees C, can be used to bias the reported temp. from a DS1620, if one is found when the program starts up. ***** NOTE ***** This project needs a better name than 'lpt_driver'. If you think of one, please drop me an email (lpt_driver@icmp.com). Thanks. Version 0.28 Another cleanup release. Fixed some minor text display bugs, for things like up-time over 1000 Hours and - temp. Nothing major. Version 0.27 Added some new display modes for text based load display, Min/Max Temp., current PID of the driver. Cleaned up some things. This still needs work regarding the display line size. There is support for 20x2 and 24x2 type displays, but the development is done with the 24x2. If it's a problem using a 20x2 display, then you should shorten some of the strings that are displayed. I will look into doing a better job for the next major version. This still needs a lot of work to be useful: 1: Signal handler functions *** 4/26/98 Added clean-up signals & temp display mode change signal CW *** 2: Signal to change default temp reporting F/C (And display mode control) *** 4/26/98 Done. Send a SIGHUP to the process to change the temp display mode. SIGHUP can be sent from the command line with 'kill -HUP pid#' SIGHUP may not be the best signal to use here, but I am open to sugestions CW *** *** Added DISPLAY_MODE control 4/27/98 CW *** There is now a DISPLAY_MODE control function for two basic modes: The default mode shows Uptime and Procs on the top line of the display. The second mode displays the date and time on the first line. Both modes display the temp and system load on the lower line of the display. DISPLAY_MODE switching is done by sending the driver a SIGUSR1 signal. SIGUSR1 can be sent from the command line with 'kill -USR1 pid#' 3: Named pipe input for display. If pipe goes inactive for 2 seconds, display default information. Auto-restore pipe info display when active again *** 2/25/98 Named pipe added '/dev/lpt_driver_in' CW *** *** 3/23/98 Added the pipe driver code CW *** Note: The pipe driver code still needs some work to make sure that nothing 'funny' can happen if the FIFO gets bombarded with data, or the writing applications stalls between writing lines (non-Atomic). The code now assumes that there will be two lines of data to display in the buffer. It will take the first two lines from the pipe, and display them, discarding anything else that may be in the pipe after them. (Lines are terminated by '\n') 3.5: String filtering. Take data from the FIFO and filter out control chars that can't function normally on the LCD display. Things like /n, /r, form-feed, etc. Change the chars to display control functions where it can be done. *** 3/23/98 Added this function with the pipe driver code. CW *** Note: The String Filtering only strips chars that are < 0x20 | > 0x7e. 4: Smart display of data on various types of displays. Now setup for 2x40 display, but it should also handle 2x16 and 2x20 display types for installation in normal PC disk-drive bay *** There is now a simple flag for 2x20 or 2x40 displays, set at compile time. This area still needs some work. 5: Load-up the char gen ram in the display, and make a bar-graph display of system load *** 2/16/98 Done. CW *** *** Fixed a problem in main.c that overflowed the display when the temp was neg. CW 04/12/98 *** 6: temp logging to the syslog at some predefined interval. Also logging on demand using a signal to trigger the event *** 4/27/98 Signal SIGUSR2 now makes the driver log the temp to the syslog in whatever display mode we are now using (C|F) CW *** 7: A new mode to handle graphic type LCD displays (I have to order some to play with) 8: General clean-up of the code, replace magic numbers with defines, etc. *** 5/25/98 Cleaned up a bunch of things in the code. Added better way to define display size. Now supporting 20x2 and 24x2 displays (see the header file for the enums). Need to add support for 40x2 displays as well. CW *** Compile like this; gcc -O -o lpt_driver main.c Or, to debug add the -g option gcc -O -g -o lpt_driver main.c (There is also a Makefile. use; make prog for the normal program, or make debug for one with the debugging options enabled) Files used in this program: main.c io.c misc.c dallas.c fifo.c lpt_driver.h Makefile ***************************************************************************************** The lpt port looks something like this..... Addr d7 d6 d5 d4 d3 d2 d1 d0 ----- ----- ----- ----- ----- ----- ----- ----- ----- Base data7 data6 data5 data4 data3 data2 data1 data0 Base+1 ~busy ack pap_out select error - - - (status) Base+2 - - - - ~select init ~autfed ~strobe (control) NOTE: Status7, Control3, Control1, & Control0 are inverted in the hardware And, the way we have wired the port up to the display is: Addr d7 d6 d5 d4 d3 d2 d1 d0 ----- ----- ----- ----- ----- ----- ----- ----- ----- Base data7 data6 data5 data4 data3 data2 data1 data0 Base+1 - - - - - - - - (status) Base+2 - - ext_mod - data/~cntrl Enable ~R/W - (control) ext_mod = extended mode control (r/w for the port hardware). WRITE ONLY, A READ WILL RETURN JUNK! (Don't blame me, talk to IBM!) 0 = Write, 1 = Read. NOTE: I should make changes to add a shadow register for bits like ext_mod..... ANOTHER NOTE: Signal sense takes account of inversions in the hardware! The display does not know about things like CR/LF (\r\n). It only knows about homing (to the upper-left) with the cursor, and using set-address for the cursor. The display addresses for a 2 line X 40 Char display looks like this: 0x00 0x01 0x02 0x03 0x04 0x05 ..... 0x26 0x27 0x40 0x41 0x42 0x43 0x44 0x45 ..... 0x66 0x67 Form-Feed can be simulated by sending a 'clear/home' command to the display (This command takes about 1mS, so I don't like to use it) Some of the more common commands for the LCD displays follow: Function: Byte Value: Action: -------------------------------------------------------------------------------------- display_control 0000_0001 CLEAR DISPLAY, HOME CURSOR display_control 0000_001x HOME CURSOR, MAINTAIN DISPLAY DATA display_control 0000_001 I/D S I=1 D=0 Increment/Decrement cursor after write S=1 Shift display S=0 No shift display display_control 0000_1DCB D=1 Display on, D=0 Display off C=1 Cursor on C=0 Cursor off B=1 Blinking block cursor on B=0 Blinking block cursor off display_control 0001_S/C R/L xx S/C=1 Display shift S/C=0 Cursor move R/L=1 Shift to the Right R/L=0 Shift to the Left display_control 0011_10xx Display 8 bit mode, 2 lines, 5x7 font (Standard for this connection, use this mode) display_control 01aa_aaaa Set Char Gen. RAM address aaaaaa = Binary char. gen. ram address C.G. ram is sent/rcvd after this command display_control 1aaa_aaaa Set display data ram address. Used to pos. cursor. display ram is sent/rcvd after this command display_data ASCII Char display_read BF aaaaaaa BF=1 Busy BF=0 Not busy aaaaaaa = Binary char. ram address (current char) CG RAM looks something like this. Bit: 7 6 5 4 3 2 1 0 Byte0: - - - x x x x x << 5x7 char matrix Byte1: - - - x x x x x Byte2: - - - x x x x x Byte3: - - - x x x x x Byte4: - - - x x x x x Byte5: - - - x x x x x Byte6: - - - x x x x x Byte7: 0 0 0 0 0 0 0 0 Where the x's are the pattern to load, bits 7-5 are always zero, and byte 7 is always zero. Fill the CG ram by setting the CG address to 0 (command 0x40) and loading all 8 chars with 64 bytes of write. Then the char's loaded in this way will be displayed as char data 0x00 to 0x07. Exit the CG ram load mode by setting the mode to data-display (command 0x80) (This is the same as doing a 'display address 0x00') Simple, 'eh? (You can also load a custom char by itself, just by setting the CG ram address, sending the eight bytes of CG char data, and setting the display back to data-display mode.) ***************************************************************************************** (Take a look at the Dallas driver functions in this driver. All of the following primitive functions are there) If a Dallas DS1620 is connected to the display assembly, you can use the following bits: Dallas Port Sense DQ D0 Normal ~RST D1 Normal CLK ~STROBE bit set in port = Dallas clock low (set to clock, reset of bit is the rising edge of the clock) Example access of the DS1620: With the port in the normal output mode, and no display transactions ongoing; take the ~rst bit (D1) low set D1 hi Send the 'protocol' 8 bits, LSB first; set strb bit hi (DS1620 clk goes low) set data bit on D0 set strb bit low continue until done with 8 protocol bits if writing: continue as above until all data bits have been sent after the protocol goto done: if reading: turn port around by setting bit D5 of the port control byte set strb bit hi wait 1uS shift in data from D0 set strb bit low continue until all data bits are shifted in done: clear bit D5 of the control byte take port bit D1 low set D1 hi YOU ARE DONE! ***************************************************************************************** Connection information: parallel Port LCD Display DS1620 DB-25 14 Pin 8 Pin DIP ------------- ----------- --------- 1 ------------------------------------------------------------- 2 2 ----------------------------- 7 ----------------------------- 1 3 ----------------------------- 8 ----------------------------- 3 4 ----------------------------- 9 -------------- 4 5 ----------------------------- 10 | ----------- 8 6 ----------------------------- 11 | | 7 ----------------------------- 12 | | 8 ----------------------------- 13 | | 9 ----------------------------- 14 | | 16 ---------------------------- 6 | | 17 ---------------------------- 4 | | 14 ---------------------------- 5 | | 18-25 ------------------------- 1 --------------- | +5 ------------ 2 ----------------- Gnd -- Vdisp --------- 3 Vdisp is used for LCD display power. The display logic is powered from the normal +5 volt connection. Normal display current is about 3mA maximum. There is no power available from the parallel port connection. The easy way to obtain power in a system is from a disk drive connector.
If you want to connect to the internal 26 pin connector instead of the external DB-25 printer
connector, you can use the following table to translate the pin connections:
26 Pin Connector | DB-25 pin | Signal Name | 26 Pin Connector | DB-25 pin | Signal Name |
1 |
1 |
~Strobe |
2 |
14 |
~AutoFF |
3 |
2 |
D0 |
4 |
15 |
~Error |
5 |
3 |
D1 |
6 |
16 |
~Init |
7 |
4 |
D2 |
8 |
17 |
~Select |
9 |
5 |
D3 |
10 |
18 |
Ground |
11 |
6 |
D4 |
12 |
19 |
... |
13 |
7 |
D5 |
14 |
20 |
... |
15 |
8 |
D6 |
16 |
21 |
... |
17 |
9 |
D7 |
18 |
22 |
... |
19 |
10 |
~ACK |
20 |
23 |
... |
21 |
11 |
Busy |
22 |
24 |
... |
25 |
12 |
Paper out |
24 |
25 |
Ground |
***************************************************************************************** It is interesting to note the following port information: A Kouwell parallel printer card, Model KW-508E, comes with the following addresses for LPT1-6; LPT1 0x3bc-0x3be LPT2 0x378-0x37a LPT3 0x278-0x27a LPT4 0x268-0x26a LPT5 0x27c-0x37e (Typo? It _must_ be 0x27c-0x27e?) LPT6 0x26c-0x26e ***************************************************************************************** For detailed information on the devices (DS1620 and LCD displays) used in this project, have a look at: www.dalsemi.com (Dallas Semiconductor homepage)
www.hantronix.com (Makers of LCD displays)
If you find that this program is of use, or you would like to contribute to code development,
please drop me an email. Thanks ;-)
Enjoy! Carl Walker cwalker@icmp.com