ain@j.cc.purdue.edu (Patrick White) (01/10/88)
Program Name: tek4695 printer driver
Submitted By: Phil Staub <phils%tekig.tek.com@relay.cs.net>
Summary: This is an updated tek4695 printer driver -- fixes some
bugs and adds some new capabilities.
Poster Boy: Pat White (ain@j.cc.purdue.edu)
Untested.
NOTES:
I didn't assemble this program, so it is untested.
-- Pat White (co-moderator comp.sources/binaries.amiga)
UUCP: j.cc.purdue.edu!ain BITNET: PATWHITE@PURCCVM PHONE: (317) 743-8421
U.S. Mail: 320 Brown St. apt. 406, West Lafayette, IN 47906
========================================
Here are the sources for an updated version of a Tektronix 4695 printer
driver I wrote a while back. It fixes a few bugs and adds a few new
capabilities.
One of the bugs it fixes sort of prompted one of the new features: It now
supports the set foreground and set background color escape sequences for
text printing. These escape sequences used to crash the machine.
Another bug fixed is that I had some reports of some programs guru'ing when
finishing up a graphic dump. This was apparently due to function #4 being
called in render() more than once without an intervening call on the
function which allocates the buffers (I think it's function 1). Since this
function frees a couple of buffers, it's not nice to call the function
multiple times.
Also, I re-arranged render() to minimize the overhead in plotting pixels,
since that happens *many* times. I'm not sure how much effect this has, but
at least it "feels" a little quicker.
Finally, I added support for underlined characters in text mode. This is
something which I don't think was there before, but I can't remember for
sure.
Enjoy
Phil
==============================
#!/bin/sh
# shar: Shell Archiver
# Run the following text with /bin/sh to create:
# data.c
# dospecial.c
# include.asm
# include.c
# init.asm
# macros.i
# makefile
# printertag.asm
# render.c
# wait.asm
# This archive created: Mon Dec 14 22:45:05 1987
cat << \SHAR_EOF > data.c
/* Tektronix 4695 command table */
/****** printer.device/printers/Tektronix_4695_functions ********************
*
* Name
* Tektronix 4695 functions implemented:
*
* aIND, aNEL,
* aSLPP,
* aTBC0, aTBC3, aTBCALL, aTBSALL
*
* special functions implemented:
* aRIN, aSLRM, aSFC, aSBC
*
**************************************************************************/
char *CommandTable[] = {
"\377", /* reset RIS */
"\377", /* initialize RIN */
"\012", /* index IND */
"\015\012", /* new line NEL */
"\377", /* rev index RI */
"\021", /* norm ch set SGR0 */
"\377", /* italics on SGR3 */
"\377", /* italics off SGR23 */
"\022", /* underline on SGR4 */
"\021", /* underlin off SGR24 */
"\377", /* bold on SGR1 */
"\377", /* bold off SGR22 */
"\377", /* set fore col SFC */
"\377", /* set back col SBC */
"\377", /* norm space SHORP0 */
"\377", /* elite on SHORP2 */
"\377", /* elite off SHORP1 */
"\377", /* fine on SHORP4 */
"\377", /* fine off SHORP3 */
"\377", /* enlarged on SHORP6 */
"\377", /* enlarged off SHORP5 */
"\377", /* shadow print on DEN6 */
"\377", /* shadow print off DEN5 */
"\377", /* double strike on DEN4 */
"\377", /* double strike off DEN3 */
"\377", /* NLQ on DEN2 */
"\377", /* NLQ off DEN1 */
"\377", /* superscript on SUS2 */
"\377", /* superscript off SUS1 */
"\377", /* subscript on SUS4 */
"\377", /* subscript off SUS3 */
"\377", /* normalize the line SUS0 */
"\377", /* partial line up PLU */
"\377", /* partial line down PLD */
"\377", /* US Character Set FNT0 */
"\377", /* French Character set FNT1 */
"\377", /* German Character setFNT2 */
"\377", /* UK character set FNT3 */
"\377", /* Danish I character set FNT4 */
"\377", /* Swedish character set FNT5 */
"\377", /* Italian char set FNT6 */
"\377", /* Spanish char set FNT7 */
"\377", /* Jap char set FNT8 */
"\377", /* Norw char set FNT9 */
"\377", /* Danish II char set FNT10 */
"\377", /* Prop on PROP2 */
"\377", /* Prop off PROP1 */
"\377", /* prop clear PROP0 */
"\377", /* set prop offset TSS */
"\377", /* auto left justify JFY5 */
"\377", /* auto right justify JFY7 */
"\377", /* auto full justify JFY6 */
"\377", /* auto justify off JFY0 */
"\377", /* letter space (justify) JFY3 */
"\377", /* word fill (auto center) JFY1 */
"\377", /* 8LPI VERP0 */
"\377", /* 6LPI VERP1 */
"\377", /* set lines/page SLPP */
"\377", /* perf skip PERF */
"\377", /* perf skip off PERF0 */
"\377", /* left margin set LMS */
"\377", /* right margin set RMS */
"\377", /* top margin set TMS */
"\377", /* bottom margin set BMS */
"\377", /* set t&b margin STBM */
"\377", /* set l&r margin SLRM */
"\377", /* clear all margins CAM */
"\377", /* horizontal tab set HTS */
"\377", /* vertical tab set VTS */
"\377", /* clear horiz tab TBC0 */
"\0332", /* clear all horiz tabs TBC3 */
"\377", /* clear vert tab TBC1 */
"\377", /* clear all vert tabs TBC4 */
"\0332", /* clear all tabs TBCALL */
"\377", /* set default tabs TBSALL */
"\377" /* extended commands EXTEND */
};
SHAR_EOF
cat << \SHAR_EOF > dospecial.c
/* Tektronix 4695 special printer functions */
/******* printer.device/printers/Tektronix_4695_special_functions **********
*
* Name
* Tektronix 4695 special functions implemented:
*
* aRIN, aSLRM, aSFC, aSBC
*************************************************************************/
#include <exec/types.h>
#include <devices/printer.h>
#include <devices/prtbase.h>
#include <clib/macros.h>
extern struct PrinterData *PD;
long
DoSpecial(command,outputBuffer,vline,currentVMI,crlfFlag,Parms)
char *outputBuffer;
UWORD *command;
BYTE *vline;
UBYTE *currentVMI;
BYTE *crlfFlag;
UBYTE Parms[];
{
static BYTE FGColorTable[] =
{'1','3','5','4','7','2','6','0','1','1'};
static BYTE BGColorTable[] =
{'1','3','5','4','7','2','6','0','0','0'};
extern UBYTE TextColors;
char buf[80], shortbuf[3];
buf[0] = shortbuf[2] = '\0';
switch(*command) {
case aRIN: {
/* default text color */
TextColors = 0x70; /* white background, black text */
strcat(buf,"\r\n");
} /* fall through to set default tabs */
case aTBSALL: {
Parms[0] = (PD->pd_Preferences.PrintLeftMargin);
Parms[1] = (PD->pd_Preferences.PrintRightMargin);
/* fall through to set the margins and default tabs */
}
case aSLRM: {
/* actually sets both left and right margins and default tabs */
/* default tabs are set every 8 columns */
register int LeftMargin = Parms[0];
register int RightMargin = 100 - Parms[1];
register int count;
/* ensure that both margins are valid:
* odd numbers
* 5 <= margin <= 95
* (we assume that left margin is to left of right margin)
*/
LeftMargin = MIN(95,(MAX(5,(LeftMargin | 1))));
RightMargin = MIN(95,(MAX(5,(RightMargin | 1))));
/* Build the initialization string */
strcat(buf,"\033W10\033H");
/* put in the number of tabs */
count = (Parms[1] - LeftMargin) / 8;
shortbuf[0] = (count / 10) + '0';
shortbuf[1] = (count % 10) + '0';
strcat(buf,shortbuf);
/* continue by putting in the left margin */
shortbuf[0] = (LeftMargin / 10) + '0';
shortbuf[1] = (LeftMargin % 10) + '0';
strcat(buf,shortbuf);
/* now insert tab specifications */
while (count--)
strcat(buf,"08");
/* finally put in the right margin */
shortbuf[0] = (RightMargin / 10) + '0';
shortbuf[1] = (RightMargin % 10) + '0';
strcat(buf,shortbuf);
/* now copy into the output buffer and return the length */
strcpy(outputBuffer,buf);
return(strlen(buf));
}
case aSFC:
if (Parms[0] < 40)
TextColors = ((TextColors)&240)+(Parms[0]-30);
/* fall through to aSBC */
case aSBC: {
register char *p_out = outputBuffer;
if (Parms[0] >= 40)
TextColors = ((TextColors)&15)+((Parms[0]-40)*16);
*p_out++ = '\033';
*p_out++ = 'C';
*p_out++ = FGColorTable[TextColors&15];
*p_out = BGColorTable[((TextColors&240)/16)];
return(4); /* we just stuffed 4 characters into the output
* buffer. now we return the length */
}
case aSLPP: {
char buf[5];
int len = (Parms[0]+5)/6; /* len is in inches,
* Parms is in lines */
strcpy(buf,"\033L");
buf[2] = (len / 10) + '0';
buf[3] = (len % 10) + '0';
strcpy(outputBuffer,buf);
return(4);
}
case aRIS:
PD->pd_PWaitEnabled = 253;
break;
default:
break;
}
return(0);
}
/* turn this on to get a routine to print things to debugging terminal */
/*
db(num)
{
kprintf("%ld\n",num);
while (KGetChar() != '\r')
;
}
*/
SHAR_EOF
cat << \SHAR_EOF > include.asm
;:ts=8
far code
far data
public .begin
dseg
end
SHAR_EOF
cat << \SHAR_EOF > include.c
#include <exec/types.h>
#include <exec/nodes.h>
#include <exec/lists.h>
#include <exec/memory.h>
#include "devices/printer.h"
#include "devices/prtbase.h"
#include <functions.h>
SHAR_EOF
cat << \SHAR_EOF > init.asm
far code
far data
;
; Excerpt from Amiga ROM Kernel Reference Manual: Libraries and
; Devices. Used by permission, 1987, Phil Staub.
;
;**************************************************************************
; *
; Copyright 1985, Commodore-Amiga Inc. All rights reserved. *
; No part of this program may be reproduced, transmitted *
; transcribed, stored in retrieval system, or translated into *
; any language or computer language, in any form or by any means, *
; electronic, mechanical, magnetic, optical, chemical, *
; manual or ohterwise, without the prior written permission of *
; Commodore-Amiga Incorporated, 983 University Ave. Building #D, *
; Los Gatos, California, 95030 *
; *
;**************************************************************************
section printer
; included files
include "exec/types.i"
include "exec/nodes.i"
include "exec/lists.i"
include "exec/memory.i"
include "exec/ports.i"
include "exec/libraries.i"
include "macros.i"
; imported functions
XREF_EXE CloseLibrary
XREF_EXE OpenLibrary
XREF _AbsExecBase
XREF _PEDData
; exported globals
XDEF _Init
XDEF _Expunge
XDEF _Open
XDEF _Close
XDEF _PD
XDEF _PED
XDEF _SysBase
XDEF _DOSBase
XDEF _GfxBase
XDEF _IntuitionBase
XDEF _TextColors ; Added to avoid using currentVMI to hold color
;***********************************************
section printer,data
_PD DC.L 0
_PED DC.L 0
_SysBase DC.L 0
_DOSBase DC.L 0
_GfxBase DC.L 0
_IntuitionBase DC.L 0
_TextColors DC.L 0 ; Added to avoid using currentVMI to hold color
;***********************************************
section printer,code
_Init:
move.l 4(a7),_PD
lea _PEDData(pc),a0
move.l a0,_PED
move.l a6,-(a7)
move.l _AbsExecBase,a6
move.l a6,_SysBase
; open the dos library
lea DLName(pc),a1
moveq #0,d0
CALLEXE OpenLibrary
move.l d0,_DOSBase
beq.l initDLErr
; open the graphics library
lea GLName(pc),a1
moveq #0,d0
CALLEXE OpenLibrary
move.l d0,_GfxBase
beq.l initGLErr
; open the intuition library
lea ILName(pc),a1
moveq #0,d0
CALLEXE OpenLibrary
move.l d0,_IntuitionBase
beq.l initILErr
move.b #$70,_TextColors ; set default text color: black on white
moveq #0,d0
pdiRTS:
move.l (a7)+,a6
rts
initPAErr:
move.l _IntuitionBase,a1
LINKEXE CloseLibrary
initILErr:
move.l _GfxBase,a1
LINKEXE CloseLibrary
initGLErr:
move.l _DOSBase,a1
LINKEXE CloseLibrary
initDLErr:
moveq #-1,d0
bra.s pdiRTS
ILName:
dc.b 'intuition.library'
dc.b 0
DLName:
dc.b 'dos.library'
dc.b 0
GLName:
dc.b 'graphics.library'
dc.b 0
ds.w 0
;
_Expunge:
move.l _IntuitionBase,a1
LINKEXE CloseLibrary
move.l _GfxBase,a1
LINKEXE CloseLibrary
move.l _DOSBase,a1
LINKEXE CloseLibrary
_Open:
moveq #0,d0
rts
_Close:
moveq #0,d0
rts
end
SHAR_EOF
cat << \SHAR_EOF > macros.i
;**************************************************************************
; printer device macro definitions
;**************************************************************************
; external definition macros
XREF_EXE macro
XREF _LVO\1
endm
XREF_DOS macro
XREF _LVO\1
endm
XREF_GFX macro
XREF _LVO\1
endm
XREF_ITU macro
XREF _LVO\1
endm
; library dispatch macros
CALLEXE macro
CALLLIB _LVO\1
endm
LINKEXE macro
LINKLIB _LVO\1,_SysBase
endm
CALLDOS macro
LINKLIB _LVO\1,_DOSBase
endm
LINKGFX macro
LINKLIB _LVO\1,_GfxBase
endm
LINKITU macro
LINKLIB _LVO\1,_IntuitionBase
endm
SHAR_EOF
cat << \SHAR_EOF > makefile
OBJS = printertag.o init.o wait.o data.o dospecial.o render.o
CFLAGS = +P +Q +Iinclude.pre
all: include.pre Tektronix_4695
Tektronix_4695: $(OBJS)
ln -o Tektronix_4695 $(OBJS) -lcl32
include.pre: include.c
cc -a +P +Q +Hinclude.pre include.c
SHAR_EOF
cat << \SHAR_EOF > printertag.asm
far code
far data
;
; Excerpt from Amiga ROM Kernel Reference Manual: Libraries and
; Devices. Used by permission, 1987, Phil Staub.
;
;**************************************************************************
; *
; Copyright 1985, Commodore-Amiga Inc. All rights reserved. *
; No part of this program may be reproduced, transmitted *
; transcribed, stored in retrieval system, or translated into *
; any language or computer language, in any form or by any means, *
; electronic, mechanical, magnetic, optical, chemical, *
; manual or ohterwise, without the prior written permission of *
; Commodore-Amiga Incorporated, 983 University Ave. Building #D, *
; Los Gatos, California, 95030 *
; *
;**************************************************************************
section printer
include "exec/types.i"
include "exec/nodes.i"
include "exec/strings.i"
include "devices/prtbase.i"
xref _Init
xref _Expunge
xref _Open
xref _Close
xref _CommandTable
xref _DoSpecial
xref _Render
xdef _PEDData
xdef .begin
xdef _main
VERSION EQU 31
REVISION EQU 24
.begin:
_main:
moveq #0,d0
rts
dc.w VERSION
dc.w REVISION
_PEDData:
dc.l printerName
dc.l _Init
dc.l _Expunge
dc.l _Open
dc.l _Close
dc.b PPC_COLORGFX
dc.b PCC_YMCB
dc.b 80
dc.b 1
dc.w 4
dc.l 1024
dc.l 0
dc.w 120
dc.w 120
dc.l _CommandTable
dc.l _DoSpecial
dc.l _Render
dc.l 60
dc.l 0
printerName:
dc.b "Tektronix 4695"
dc.b 0
end
SHAR_EOF
cat << \SHAR_EOF > render.c
/**********************************************************************/
#include <exec/types.h>
#include <exec/nodes.h>
#include <exec/lists.h>
#include <exec/memory.h>
#include "devices/printer.h"
#include "devices/prtbase.h"
#include <functions.h>
extern struct PrinterData *PD;
/* for the Tektronix 4695 */
long Render(ct,x,y,status)
register ULONG ct; /* was UBYTE for Lattice compiler */
register ULONG x,y; /* was UWORD for Lattice compiler */
ULONG status; /* was UBYTE for Lattice compiler */
{
static UWORD ROWSIZE;
static UWORD COLORSIZE;
static UWORD BUFSIZE;
static UWORD colors[4];
static BYTE huns,tens,ones;
static UWORD bufptr;
static UBYTE *initbuf;
register struct PrinterData *pp = PD;
register UBYTE *ptr;
UWORD i;
BYTE err;
/* placing pixels in the row buffers is a *very* time critical task.
* for this reason, we do this here, rather than in the switch below.
*/
if ((UBYTE)status == 1)
{ /* put pixel in buffer (called a max of 16384
* times per print cycle)
*/
register UWORD i;
i = bufptr+(UWORD)x/8+((UWORD)y&3)*ROWSIZE+colors[(UBYTE)ct];
PD->pd_PrintBuf[i] |= (1 << (7-((UWORD)x&7)));
return(0);
}
switch((UBYTE)status) {
/* each case in this switch exits via a "return", so
* there is no "break"
*/
case 0: /* alloc memory for printer buffer (uses dbl buf) */
ROWSIZE = ((UWORD)x+7)/8;
huns = ROWSIZE/100;
tens = (ROWSIZE - huns*100)/10;
ones = (ROWSIZE - huns*100 - tens*10);
ROWSIZE += 6; /* escape sequence overhead */
COLORSIZE = ROWSIZE*4; /* one for each color */
BUFSIZE = COLORSIZE*4+2; /* 4 colors + CR/LF */
/* colors we get are swizzled from the way we
*want them
*/
colors[0] = 6; /* start of color 0 */
colors[1] = COLORSIZE*2+6; /* start of color 1 */
colors[2] = COLORSIZE+6; /* start of color 2 */
colors[3] = COLORSIZE*3+6; /* start of color 3 */
/* allocate a buffer which is used to init the
* print buffers, then initialize it
*/
initbuf = (UBYTE *)
AllocMem((long)BUFSIZE,(long)MEMF_PUBLIC);
if(err = (initbuf==0))
return(err);
/* clear and init buffer */
ptr = initbuf;
for (i = 0; i < BUFSIZE; i++)
*ptr++ = 0;
for (i = 0; i < 16; i++) {
ptr = &initbuf[i*ROWSIZE];
*ptr++ = '\033';
*ptr++ = 'I';
*ptr++ = i+'0';
*ptr++ = huns + '0';
*ptr++ = tens + '0';
*ptr++ = ones + '0';
}
initbuf[BUFSIZE-2] = '\033';
initbuf[BUFSIZE-1] = 'A';
/* try to allocate the print buffer */
pp->pd_PrintBuf = (UBYTE *)
AllocMem((long)BUFSIZE*2,(long)MEMF_PUBLIC);
if(err = (pp->pd_PrintBuf==0))
return(err);
/* 1 second delay */
if(err = PWait(1L,0L))
return(err);
/* set up for first buffer */
bufptr = 0;
return(0);
case 2: /* dump buffer to printer */
if (err =
(*(pp->pd_PWrite))(&pp->pd_PrintBuf[bufptr],
(long)BUFSIZE))
return (err);
bufptr = BUFSIZE - bufptr;
return(0);
case 3: /* re-initialize a buffer */
{
register UBYTE *s, *d;
register UWORD i;
d = &pp->pd_PrintBuf[bufptr];
s = initbuf;
for (i = 0; i < BUFSIZE; i++)
*d++ = *s++;
return(0);
}
case 4: /* free the print buffer memory */
err = (*(pp->pd_PBothReady))();
if (pp->pd_PrintBuf) {
FreeMem(pp->pd_PrintBuf,(long)BUFSIZE*2L);
pp->pd_PrintBuf = 0;
}
if (initbuf) {
FreeMem(initbuf,(long)BUFSIZE);
initbuf = 0;
}
return(err);
default:
return(0);
}
}
SHAR_EOF
cat << \SHAR_EOF > wait.asm
far code
far data
section printer
include 'exec/types.i'
include 'exec/ports.i'
include 'exec/devices.i'
include 'exec/io.i'
include 'devices/timer.i'
XREF_EXE MACRO
XREF _LVO\1
ENDM
XREF_DOS MACRO
XREF _LVO\1
ENDM
XREF_GFX MACRO
XREF _LVO\1
ENDM
XREF_ITU MACRO
XREF _LVO\1
ENDM
CALLEXE MACRO
CALLLIB _LVO\1
ENDM
LINKEXE MACRO
LINKLIB _LVO\1,_SysBase
ENDM
LINKDOS MACRO
LINKLIB _LVO\1,_DOSBase
ENDM
LINKGFX MACRO
LINKLIB _LVO\1,_GfxBase
ENDM
LINKITU MACRO
LINKLIB _LVO\1,_IntuitionBase
ENDM
INCLUDE 'devices/prtbase.i'
XREF_EXE Forbid
XREF_EXE Permit
XREF_EXE WaitIO
XREF _SysBase
XREF _PD
XDEF _PWait
_PWait:
movem.l a4/a6,-(a7)
move.l _PD,a4
move.l pd_PBothReady(a4),a0
jsr (a0)
tst.l d0
bne.s error
lea pd_TIOR(a4),a1
move.w #TR_ADDREQUEST,IO_COMMAND(a1)
move.l 12(a7),IOTV_TIME+TV_SECS(a1)
move.l 16(a7),IOTV_TIME+TV_MICRO(a1)
clr.b IO_FLAGS(a1)
move.l IO_DEVICE(a1),a6
jsr DEV_BEGINIO(a6)
LINKEXE Forbid
lea pd_TIOR(a4),a1
LINKEXE WaitIO
LINKEXE Permit
moveq #0,d0
tst.l d0
error:
movem.l (a7)+,a4/a6
rts
end
SHAR_EOF
# End of shell archive
exit 0