📄 hp400.c
字号:
// Notes:
//
// _inp and _outp are input/output routines to write the
// registers controlling the parallel interface. Replace
// these with the correct opertaions for the target system.
// Also, the port_base and offset values are specific to the
// PC, these may need to be altered as well.
// The data returned by the printer is as follows:
//
// byte 0: number of status byte (should be 6 for the 400)
// the count includes this byte
// byte 1: printer error states
// 0x00 - no error
// 0x01 - out of paper
// 0x02 - jammed
// 0x04 - stalled
// 0x08 - pen out
// 0x10 - aging
// byte 2: printer mode
// 0x01 - busy
// 0x02 - drying
// 0x04 - ASF
// byte 3: pen ID
// 0x00 - no pen
// 0x01 - black pen
// 0x10 - color pen
// byte 4: MSB of mech position
// byte 5: LSB of mech position
#include <windows.h>
#include <types.h>
#include <ceddk.h>
#include "pardbg.h"
#include "cc.h"
#define DATA_OFFSET 0
#define DSR_OFFSET 1
#define DCR_OFFSET 2
/****************************************************************************
* Modification done by Maneesh Gupta
*
* ECR Offsets have been modified for ASPEN/BIGSUR
****************************************************************************/
#define ECR_OFFSET 0x402
/****************************************************************************
* End of Modification done by Maneesh Gupta
****************************************************************************/
#define ECR_COMPATIBLITY_MODE 0x14
#define ECR_PS2 0x34 // allows us to read the data lines
#define CHANNEL_ADDRESS 0x80
// DCR - Compatibility Mode
#define DCR_RESERVED 0xC0 // upper 2 bits are reserved
#define N_DIRECTION_OUT 0x20 // 0 = Data register outputs to printer
#define ENABLE_INTERRUPT 0x10
#define N_SELECT_IN 0x08
#define N_INIT 0x04
#define N_AUTO_FD 0x02
#define N_STROBE 0x01
// DCR - ECP Mode
#define ACTIVE_1284 N_SELECT_IN
#define HOST_BUSY N_AUTO_FD
#define HOST_CLK N_STROBE
#define N_REVERSE_REQUEST N_INIT
#define HOST_ACK N_AUTO_FD
// DSR - Compatibility Mode
// Note:
// Bits 2-0 are undefined. Some parallel ports return 0,
// some 1. Make sure to always mask these bits before
// comparing the DSR to something.
#define BUSY 0x80
#define N_ACK 0x40
#define P_ERROR 0x20
#define SELECT 0x10
#define N_FAULT 0x08
// DSR - ECP Mode
#define PERIPH_ACK BUSY
#define PERIPH_CLK N_ACK
#define N_ACK_REVERSE P_ERROR
#define N_PERIPH_REQUEST N_FAULT
// DCR_INVERT_MASK: cable<->register translation of DCR signal
// values, identifies register signals that are inverted with
// respect to the external cable value.
#define DCR_INVERT_MASK (N_SELECT_IN | N_AUTO_FD | N_STROBE)
#define DCR_MASK (N_SELECT_IN | N_INIT | N_AUTO_FD | N_STROBE)
// The IBM PS/2 H/W Tech. Ref. says we must clear the reserved
// bits. We need to clear nDirectionOut so data register
// outputs are enabled. We want to disable the interrupts,
// since we don't use them
#define DCR_CLEAR (DCR_RESERVED | N_DIRECTION_OUT | ENABLE_INTERRUPT)
// DSR_INVERT_MASK: cable<->register translation of DSR signal
// values, identifies register signals that are inverted with
// respect to the external cable value.
#define DSR_INVERT_MASK BUSY
#define DSR_MASK (BUSY | N_ACK | P_ERROR | SELECT | N_FAULT)
#define IsSet(setMask) (setMask)
#define IsClear(clrMask) (clrMask)
#define DONT_CARE 0
/****************************************************************************
* Modification done by Maneesh Gupta
*
* Multiplier used to access the printer registers.
****************************************************************************/
extern unsigned dwPrinterRegMultiplier;
/****************************************************************************
* End of Modification done by Maneesh Gupta
****************************************************************************/
// Somtimes Delay is defined in the header files too, that leads to compiler
// warning
#ifdef Delay
# undef Delay
#endif Delay
#define Delay(time) \
Sleep(time)
#define BitTest(byStatus, setMask, clrMask) \
((unsigned char)((byStatus) & (unsigned char)((setMask) | (clrMask))) == \
(unsigned char)(((setMask) & (~(clrMask)))))
#define Raise(input_value, target_mask, invert_mask) \
(((input_value) & ~((target_mask) & (invert_mask))) | \
((target_mask) & ~(invert_mask)))
#define Lower(input_value, target_mask, invert_mask) \
(((input_value) & ~((target_mask) & ~(invert_mask))) | \
((target_mask) & (invert_mask)))
#define RaiseDCR(byDCRValue, byTargetMask) \
Raise(byDCRValue, byTargetMask, DCR_INVERT_MASK)
#define LowerDCR(byDCRValue, byTargetMask) \
Lower(byDCRValue, byTargetMask, DCR_INVERT_MASK)
/****************************************************************************
* Modification done by Maneesh Gupta
*
* Modified Register access address for different platform with the help of
* dwPrinterRegMultiplier
****************************************************************************/
#define WriteDCR(port_addr, value) \
WRITE_PORT_UCHAR((PUCHAR)port_addr+ (DCR_OFFSET * dwPrinterRegMultiplier),value)
#define ReadDSR(port_addr) \
(unsigned char) READ_PORT_UCHAR((PUCHAR)port_addr+ (DSR_OFFSET * dwPrinterRegMultiplier))
#define ReadDCR(port_addr) \
(unsigned char) READ_PORT_UCHAR((PUCHAR)port_addr+ (DCR_OFFSET * dwPrinterRegMultiplier))
#define WriteData(port_addr, value) \
WRITE_PORT_UCHAR((PUCHAR)port_addr+ (DATA_OFFSET * dwPrinterRegMultiplier) ,value)
#define ReadData(port_addr) \
(unsigned char) READ_PORT_UCHAR((PUCHAR)port_addr+ (DATA_OFFSET * dwPrinterRegMultiplier))
#define WriteECR(port_addr, value) \
WRITE_PORT_UCHAR((PUCHAR)port_addr+ (ECR_OFFSET * dwPrinterRegMultiplier ),value)
/****************************************************************************
* End of Modification done by Maneesh Gupta
****************************************************************************/
#define BitTestDSR(byDSRValue, bySetMask, byClrMask) \
BitTest(((byDSRValue) ^ DSR_INVERT_MASK), (bySetMask), (byClrMask))
#define EncodeNibble(byDSRValue, byNibbleValue) \
(((((byDSRValue & ~NIBBLE_HI_BIT) | ((byNibbleValue << 4) & NIBBLE_HI_BIT)) \
& ~NIBBLE_LO_BITS) | ((byNibbleValue << 3) & NIBBLE_LO_BITS)) \
^ DSR_INVERT_MASK)
#define ExtractNibble(byDSRValue) \
(((((byDSRValue) ^ DSR_INVERT_MASK) & NIBBLE_HI_BIT) >> 4) | \
((((byDSRValue) ^ DSR_INVERT_MASK) & NIBBLE_LO_BITS) >> 3))
BOOL WaitForPrinter(unsigned long port_base, unsigned char SetMask,
unsigned char ClearMask)
{
unsigned char byDSR;
int i=1000;
while (i>0)
{
byDSR = ReadDSR(port_base);
if (!BitTestDSR(byDSR, SetMask, ClearMask))
Delay(1);
else
return TRUE;
i--;
}
return FALSE;
}
BOOL Enter_1284_ECP_Mode(unsigned long port_base)
{
unsigned char byDCRData;
BOOL ret_val;
byDCRData = ReadDCR(port_base);
// reinitialize the interface
// note: if you reinitialize the interface the
// printer will not return correct pen ID information
// until it finishes resetting. It seems to be OK
// to skip these steps
byDCRData = LowerDCR(byDCRData, N_INIT |
N_SELECT_IN | N_DIRECTION_OUT);
WriteDCR(port_base, byDCRData);
Delay(5);
byDCRData = RaiseDCR(byDCRData, N_INIT | N_SELECT_IN);
WriteDCR(port_base, byDCRData);
Delay(5);
// Set DCR to compatibility mode.
// (ECP event -1)
// *HostAck/*HostClk high, *1284Active low.
// Also *nInit high, as per
// the definition of nInit in the 1284 spec
// (Section 4.9 "Negotiation phase: set high").
byDCRData = RaiseDCR (byDCRData, HOST_ACK |
HOST_CLK | N_INIT);
byDCRData = LowerDCR (byDCRData, ACTIVE_1284);
WriteDCR(port_base, byDCRData);
Delay(5000);
// (ECP event 0)
// Place ECP extensibility request value (0x10)
// on the data lines. See IEEE-1284 Table 4.
WriteData(port_base, 0x10);
Delay(1); // Delay for at least 1 us.
// Enter negotiation: Is peripheral 1284 compliant?
// (ECP event 1)
// *1284Active high, *HostBusy low.
byDCRData = RaiseDCR(byDCRData, ACTIVE_1284);
byDCRData = LowerDCR(byDCRData, HOST_ACK);
WriteDCR(port_base, byDCRData);
// Await 1284-compliant reply
// (ECP event 2)
// (*PError/*nFault/Select high, nAck low)
ret_val = WaitForPrinter(port_base,
P_ERROR | N_FAULT | SELECT, N_ACK);
if (ret_val == FALSE)
{
DEBUGMSG(ZONE_IO,(TEXT("Event 2 failed\n")));
return FALSE;
}
// Strobe extensibility req to peripheral.
// (ECP event 2)
// *HostClk low.
byDCRData = LowerDCR(byDCRData, HOST_CLK);
WriteDCR(port_base, byDCRData);
// *HostClk/*HostBusy high.
// (ECP event 4)
Delay(1); // Delay for at least 1 us.
byDCRData = RaiseDCR(byDCRData, HOST_ACK | HOST_CLK);
WriteDCR(port_base, byDCRData);
// Await 1284-compliant reply
// (ECP event 5 and 6)
// (Select/Nack high, P_error/Busy low)
ret_val = WaitForPrinter(port_base,
SELECT | N_ACK, P_ERROR | BUSY);
if (ret_val == FALSE)
{
DEBUGMSG(ZONE_IO,(TEXT("Event 5&6 failed\n")));
return(FALSE);
}
Delay(1);
// Drop HOST_ACK (ECP event 30)
byDCRData = LowerDCR(byDCRData,HOST_ACK);
WriteDCR(port_base, byDCRData);
//DEBUGMSG(ZONE_IO,(TEXT("droped HOST_ACK, event 30\n")));
ret_val = WaitForPrinter(port_base, P_ERROR, DONT_CARE);
if (ret_val == FALSE)
return FALSE;
return TRUE;
}
BOOL Change_ECP_Channel(unsigned long port_base,int channel)
{
unsigned char byDCRData;
BOOL ret_val;
ret_val = WaitForPrinter(port_base, DONT_CARE, BUSY);
if (ret_val == FALSE)
return FALSE;
// Set HOST_ACK low to indicate ECP mode command
byDCRData = ReadDCR(port_base);
byDCRData = LowerDCR(byDCRData,HOST_ACK);
WriteDCR(port_base,byDCRData);
// Put the data on the bus (ECP event 34)
WriteData(port_base, (UCHAR)(CHANNEL_ADDRESS | channel));
// Set N_STROBE low to send data (ECP event 35)
byDCRData = LowerDCR(byDCRData,N_STROBE);
WriteDCR(port_base,byDCRData);
//DEBUGMSG(ZONE_IO,(TEXT("set N_STROBE low, ECP event 35\n")));
// Wait for Busy to go high (ECP event 36)
ret_val = WaitForPrinter(port_base, BUSY, DONT_CARE);
if (ret_val == FALSE)
return FALSE;
// Set N_STROBE high (ECP Event 37)
Delay(1);
byDCRData = RaiseDCR(byDCRData,N_STROBE);
WriteDCR(port_base,byDCRData);
// Wait for Busy to go low (ECP event 38)
ret_val = WaitForPrinter(port_base, DONT_CARE, BUSY);
if (ret_val == FALSE)
return FALSE;
return TRUE;
}
BOOL Fwd_to_Rev_Trans(unsigned long port_base)
{
unsigned char byDCRData;
BOOL ret_val;
WriteECR(port_base,ECR_PS2);
byDCRData = ReadDCR(port_base);
byDCRData = RaiseDCR(byDCRData,N_DIRECTION_OUT);
WriteDCR(port_base,byDCRData);
byDCRData = LowerDCR(byDCRData,HOST_ACK);
WriteDCR(port_base,byDCRData);
Delay(1); // wait for setup time
byDCRData = LowerDCR(byDCRData,N_INIT);
WriteDCR(port_base,byDCRData);
ret_val = WaitForPrinter(port_base, DONT_CARE, P_ERROR);
if (ret_val == FALSE)
return FALSE;
else
return TRUE;
}
void Rev_to_Fwd_Trans(unsigned long port_base)
{
unsigned char byDCRData;
BOOL ret_val;
byDCRData = ReadDCR(port_base);
byDCRData = RaiseDCR(byDCRData,N_INIT);
WriteDCR(port_base,byDCRData);
ret_val = WaitForPrinter(port_base, N_ACK, DONT_CARE);
if (ret_val == FALSE)
DEBUGMSG(ZONE_IO,(TEXT("ERROR: printer didn't raise N_ACK, event 48!\n")));
ret_val = WaitForPrinter(port_base, P_ERROR, DONT_CARE);
if (ret_val == FALSE)
DEBUGMSG(ZONE_IO,(TEXT("ERROR: printer didn't raise P_ERROR, event 49!\n")));
WriteECR(port_base,ECR_COMPATIBLITY_MODE);
}
BOOL Read_1284_Port(unsigned long port_base,
unsigned char * data_byte)
{
unsigned char byDCRData;
BOOL ret_val;
byDCRData = ReadDCR(port_base);
ret_val = WaitForPrinter(port_base, DONT_CARE, N_ACK);
if (ret_val == FALSE)
return FALSE;
byDCRData = RaiseDCR(byDCRData,HOST_ACK);
WriteDCR(port_base,byDCRData);
ret_val = WaitForPrinter(port_base,N_ACK, DONT_CARE);
if (ret_val == FALSE)
return FALSE;
*data_byte = ReadData(port_base);
byDCRData = LowerDCR(byDCRData,HOST_ACK);
WriteDCR(port_base,byDCRData);
return TRUE;
}
void Exit_1284_ECP_Mode(unsigned long port_base)
{
unsigned char byDCRData;
byDCRData = ReadDCR(port_base);
byDCRData = LowerDCR(byDCRData,N_SELECT_IN);
byDCRData = RaiseDCR(byDCRData,HOST_ACK);
WriteDCR(port_base,byDCRData);
byDCRData = LowerDCR(byDCRData,HOST_ACK);
WriteDCR(port_base,byDCRData);
byDCRData = RaiseDCR(byDCRData,HOST_ACK);
WriteDCR(port_base,byDCRData);
}
int Get_DJ400_Dev_Status(unsigned long port_base,
unsigned char *buffer)
{
int i;
WriteECR(port_base,ECR_COMPATIBLITY_MODE);
DEBUGMSG(ZONE_IO,(TEXT("calling Enter_1284_ECP_Mode()\n")));
if (!Enter_1284_ECP_Mode(port_base))
return 0;
DEBUGMSG(ZONE_IO,(TEXT("calling Change_ECP_Channel()\n")));
if (!Change_ECP_Channel(port_base,32))
return 0;
DEBUGMSG(ZONE_IO,(TEXT("calling Fwd_to_Rev_Trans()\n")));
if (!Fwd_to_Rev_Trans(port_base))
return 0;
if (!Read_1284_Port(port_base,&buffer[0]))
return 0;
for (i=1;i<buffer[0];i++)
{
if (!Read_1284_Port(port_base,&buffer[i]))
break;
}
Rev_to_Fwd_Trans(port_base);
Exit_1284_ECP_Mode(port_base);
return(i);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -