/****************************************************************************** ** File Name : $RCSfile: vpptools.c $ ** Short Description : Implementation of VideoPort Professional toolkit ** Original Project : VideoPort Professional, MS801/MS802 ** Compiler, Version : Borland C++ 3.1,4.0, Visual C++ 1.0,1.51, ** Watcom C++ 9.5, 10.0 ** Compiler Options : Optimize for speed ** Libraries Used : none ** Original Author : Roar Lauritzsen ** Created (date) : 1995/01/16 ** Last modified by : $Author: Bjorn_Kristensen.NO.MRT $ ** Last modified (date): $Date: 1997/03/19 11:54:44 $ ** Current revision : $Revision: 1.34 $ ($Name: $) ******************************************************************************/ #include #include #include #include #include #include #include "vpptools.h" #ifdef __NT__ #define IOCTL_CODE(DeviceType,Function,Method,Access) (((DeviceType) << 16) | ((Access) << 14) | ((Function) << 2) | (Method)) #define MS80x_DETECT_VIDEO_PORT IOCTL_CODE(0x22,0x800,0,0) // Func 0 #define MS80x_REQ_VIDEO_PORT IOCTL_CODE(0x22,0x801,0,0) // Func 1 #define MS80x_REL_VIDEO_PORT IOCTL_CODE(0x22,0x802,0,0) // Func 2 #define MS80x_TEMP_REPROG_VIDEO_PORT IOCTL_CODE(0x22,0x803,0,0) // Func 3 #define MS80x_PERM_REPROG_VIDEO_PORT IOCTL_CODE(0x22,0x804,0,0) // Func 4 #define MS80x_REQ_CIS_VIDEO_PORT IOCTL_CODE(0x22,0x805,0,0) // Func 5 #define MS80x_READ_I2C_VIDEO_PORT IOCTL_CODE(0x22,0x806,0,0) // Func 6 #define MS80x_WRITE_I2C_VIDEO_PORT IOCTL_CODE(0x22,0x807,0,0) // Func 7 #define MS80x_READ_BYTES_VIDEO_PORT IOCTL_CODE(0x22,0x808,0,0) // Func 8 #define MS80x_READ_WORDS_VIDEO_PORT IOCTL_CODE(0x22,0x809,0,0) // Func 9 #define MS80x_MAP_PHYSICAL_MEM_VIDEO_PORT IOCTL_CODE(0x22,0x900,0,0) // Func 200 #define MS80x_LINK_IRQ_EVENT_VIDEO_PORT IOCTL_CODE(0x22,0xA00,0,0) // Func 300 #define MS80x_UNLINK_IRQ_EVENT_VIDEO_PORT IOCTL_CODE(0x22,0xA01,0,0) // Func 301 #define MS80x_DEBUG_TRANSCRIPT_VIDEO_PORT IOCTL_CODE(0x22,0xAAA,0,0) // Func 100 #else #define MS80x_DETECT_VIDEO_PORT 1 #define MS80x_REQ_VIDEO_PORT 2 #define MS80x_REL_VIDEO_PORT 3 #define MS80x_TEMP_REPROG_VIDEO_PORT 4 #define MS80x_PERM_REPROG_VIDEO_PORT 5 #define MS80x_REQ_CIS_VIDEO_PORT 6 #define MS80x_MAP_PHYSICAL_MEM_VIDEO_PORT 200 #define MS80x_LINK_IRQ_EVENT_VIDEO_PORT 300 #define MS80x_UNLINK_IRQ_EVENT_VIDEO_PORT 301 #define MS80x_DEBUG_TRANSCRIPT_VIDEO_PORT 100 #endif ///////////////////////////////////////////////////////////////////////////////////// #if defined(_Windows) || defined(__WIN32__) #include #endif #if defined(__WIN32__) #define EXPORT __stdcall #elif defined(_Windows) #define EXPORT VPP_far _pascal _export #else #define EXPORT #endif #if defined(__BORLANDC__) || defined(__WATCOMC__) #define _REGS REGS #define _SREGS SREGS #define _int86 int86 #define _int86x int86x #endif typedef signed short VPP_Int; typedef signed long VPP_Long; /* Struct that contains all per-card values */ typedef struct { /* values used by all functions */ #ifdef __WIN32__ HANDLE hCard; /* Handle to WIN32 card hardware */ #endif VPP_Word cardType; /* Type of card (Normal/Junior) */ VPP_Byte VPP_far * volatile ctrlStatus; /* Control-status register */ VPP_Byte VPP_far * volatile dataReg; /* 16 bits data register */ /* values used by videoConfig and snap */ VPP_Bool configured; /* Flag: videoConfig is done */ VPP_VideoStandard videoStd; /* configured videoStandard */ /* values used by enableFlash, disableFlash and snap */ #ifndef VPP_NO_FLASH VPP_FlashFuncPtr flashFn; /* Pointer to flash callback routine */ VPP_FlashSelect flashSel; /* Requested flashes */ VPP_Word flashDly; /* Delay from start of field to flash */ #endif /* values used by snap, startReadout and readLine */ VPP_Bool snapPrepared; /* Flag: snap is prepared */ VPP_Bool snapStarted; /* Flag: snap is started */ VPP_Bool snapFinished; /* Flag: snap is done */ VPP_Word imageWidth; /* Width of image to be read out */ VPP_Word imageHeight; /* Height of image to be read out */ int actualSnapWidth; /* Actual width of snapped image */ int actualSnapHeight; /* Actual height of snapped image */ VPP_Bool xOddStart; /* Flags if line starts on an odd pixel */ VPP_Word yOff; /* yOffset in snapped image */ VPP_Bool interlacedSnap; /* True if interlaced snap mode */ VPP_Bool monoSnap; /* True if monochrome snap mode */ /* values used by startReadout and readLine */ VPP_Bool readoutStarted; /* Flag: readout is started */ VPP_ReadoutMode readMode; /* readoutMode passed to startReadout */ VPP_Word lineNo; /* Current line number during readout */ int actualLineNo; #ifndef VPP_NO_STRETCH_IMAGE int linebuf1line; int linebuf2line; VPP_Byte VPP_far *linebuf1; VPP_Byte VPP_far *linebuf2; #endif /* VPP_STRETCH_IMAGE */ #define MAGIC_COOKIE 0x1234 VPP_Word cookie; /* Magic cookie used to verify validity of struct */ } CardData; /* Global pointer to the current CardData struct */ CardData VPP_far *c = 0; /* Global variables used by all functions */ static char* lastErrorFunction=""; /* Name of function causing error */ static char* currentFunction=""; /* Name of current function */ static int numCardsInitialized=0; /* Number of times init() has been successful */ #ifdef __WIN32__ static HANDLE hMS80x = 0; /* Handle to WIN32 VideoPort driver */ // [jp] static HANDLE tmp_hCard; /* Temporary handle to WIN32 card hardware */ #else static int INTR; /* Interrupt used to access VPPDRIVE */ #endif static VPP_Word tmp_cardType; /* Temporary card type */ /* Global variables used by fillLookupTables and readLineXXX functions */ static VPP_Byte VPP_far *linebuf = 0; #ifndef VPP_NO_STRETCH_IMAGE #define VPP_MAX_WIDTH 3200 #else /* VPP_STRETCH_IMAGE */ #define VPP_MAX_WIDTH 950 #endif /* VPP_STRETCH_IMAGE */ int K[256]; /* Table for YCrCb-RGB conversion */ int Rb[256]; /* Table for YCrCb-RGB conversion */ int Gb[256]; /* Table for YCrCb-RGB conversion */ int Gc[256]; /* Table for YCrCb-RGB conversion */ int Bb[256]; /* Table for YCrCb-RGB conversion */ #ifndef VPP_NO_RGB15 VPP_Word CprR15[280*2+256]; /* Table for 15bit red conversion */ VPP_Word CprG15[280*2+256]; /* Table for 15bit green conversion */ VPP_Word CprB15[280*2+256]; /* Table for 15bit blue conversion */ #endif #ifndef VPP_NO_RGB16 VPP_Word CprR16[280*2+256]; /* Table for 16bit red conversion */ VPP_Word CprG16[280*2+256]; /* Table for 16bit green conversion */ VPP_Word CprB16[280*2+256]; /* Table for 16bit blue conversion */ #ifdef VPP_FAST_RGB16 /* Use fast conversion lookup table */ #if defined(__WATCOMC__) || defined(__WIN32__) /* 32-bit mode, use 128kB lookup table (good color resolution) */ #define YBITS 6 #define CrBITS 5 #define CbBITS 5 #elif defined(_Windows) /* Windows 16-bit mode, use 64kB lookup table (medium color resolution) */ #define YBITS 6 #define CrBITS 5 #define CbBITS 4 #else /* DOS 16-bit mode, use 32kB lookup table (poor color resolution) */ #define YBITS 6 #define CrBITS 4 #define CbBITS 4 #endif VPP_Word VPP_far *Cpr16 = 0; /* Table for 16bit fast conversion */ #endif /* VPP_FAST_RGB16 */ #endif /* VPP_NO_RGB16 */ #if !defined(VPP_NO_RGB24) || !defined(VPP_NO_BGR24) || !defined(VPP_NO_BGR032) VPP_Byte Cpr[280*2+256]; /* Table for YCrCb-RGB conversion */ #endif #ifndef VPP_NO_RGB8 VPP_Byte CprR8[280*2+256]; /* Table for 8bit red conversion */ VPP_Byte CprG8[280*2+256]; /* Table for 8bit green conversion */ VPP_Byte CprB8[280*2+256]; /* Table for 8bit blue conversion */ #endif #ifndef VPP_NO_mono VPP_Byte GamMono[256]; /* Table for monochrome gamma corr. */ #endif /* Predeclarations of local functions */ #ifdef __WIN32__ static VPP_Byte VPP_far * volatile detectVideoPort(VPP_Bool *powerWasOff); static void closeVideoPort(VPP_Bool powerOff); #else static VPP_Word detectVideoPort(VPP_Bool *powerWasOff); static void closeVideoPort(void); #endif /* __WIN32__ */ static VPP_Byte read_csr(void); static VPP_Byte write_csr(VPP_Byte csr_data); static void fillLimits(VPP_VideoStandard videoStandard, VPP_LimitData VPP_far* limitData); static void fillLookupTables(float gamma); #if !defined(VPP_NO_RGB16) && defined(VPP_FAST_RGB16) static void fillFastLookupTable(void); #endif /* VPP_FAST_RGB16 */ static void msleep(VPP_Word msec); // This stays the same to handle calls when MS80x.SYS is absent [jp] static int readI2C(VPP_Word register_no, VPP_Byte *data, int count); static int writeI2C(VPP_Word register_no, VPP_Byte *data, int count); // These functions are used instead of two above to write/read from // the digitizer whenever the MS80x.SYS is present static int NTreadI2C(VPP_Word register_no, VPP_Byte *data, int count); static int NTwriteI2C(VPP_Word register_no, VPP_Byte *data, int count); #ifndef VPP_NO_FLASH static void VPP_far ourFlashFunc(VPP_FlashSelect whichFlash); #endif #ifndef VPP_NO_mono static void readLineMono8(void VPP_far*, unsigned, unsigned); #endif #ifndef VPP_NO_mono4 static void readLineMono4(void VPP_far*, unsigned, unsigned); #endif #ifndef VPP_NO_RGB8 static void readLineRGB8 (void VPP_far*, unsigned, unsigned); #endif #ifndef VPP_NO_RGB15 static void readLineRGB15(void VPP_far*, unsigned, unsigned); #endif #ifndef VPP_NO_RGB16 static void readLineRGB16(void VPP_far*, unsigned, unsigned); #endif #ifndef VPP_NO_RGB24 static void readLineRGB24(void VPP_far*, unsigned, unsigned); #endif #ifndef VPP_NO_BGR24 static void readLineBGR24(void VPP_far*, unsigned, unsigned); #endif #ifndef VPP_NO_BGR032 static void readLineBGR032(void VPP_far*, unsigned, unsigned); #endif #ifndef VPP_NO_YCrCb static void readLineYCrCb(void VPP_far*, unsigned, unsigned); #endif #ifndef VPP_NO_CbYCrY static void readLineCbYCrY(void VPP_far*, unsigned, unsigned); #endif #ifndef VPP_NO_YCbCr static void readLineYCbCr(void VPP_far*, unsigned, unsigned); #endif #if (defined(_Windows) || defined(__WATCOMC__)) && !defined(__WIN32__) static VPP_Byte VPP_far* getDosMemory(VPP_Word segment); static void freeDosMemory(VPP_Byte VPP_far* address); #endif #define RETURN_ERROR(err) { lastErrorFunction=currentFunction; return err; } // // Write/Read Digitizer Macros [jp] // #ifdef TESTMODE #define READI2C(r,d,c) { int _err; if ((_err=readI2C(r,d,c))!=c) RETURN_ERROR(_err==-1?VPP_lostContact:VPP_lostContact2); } #define WRITEI2C(r,d,c) { int _err; if ((_err=writeI2C(r,d,c))!=c) RETURN_ERROR(_err==-1?VPP_lostContact:VPP_lostContact2); } #else #ifdef __NT__ // [jp] define MS80x_SYS (e.g. NT) so the macros now access the Digitizer via the MS80x.SYS #define READI2C(r,d,c) { if (NTreadI2C(r,d,c)!=c) RETURN_ERROR(VPP_lostContact); } #define WRITEI2C(r,d,c) { if (NTwriteI2C(r,d,c)!=c) RETURN_ERROR(VPP_lostContact); } static void NTreadWords(void VPP_far* dst, void VPP_far* src, unsigned count); static void NTreadBytes(void VPP_far* dst, void VPP_far* src, unsigned count); #else // [jp] if MS80x_SYS is not present, therefore proceed as before #define READI2C(r,d,c) { if (readI2C(r,d,c)!=c) RETURN_ERROR(VPP_lostContact); } #define WRITEI2C(r,d,c) { if (writeI2C(r,d,c)!=c) RETURN_ERROR(VPP_lostContact); } #endif /* __NT__ */ // [jp] #endif /* TESTMODE */ #define DG_STATUS 0x00 #define DG_IFORM 0x01 #define DG_TDEC 0x02 #define DG_CROP 0x03 #define DG_VDELAY_LO 0x04 #define DG_VACTIVE_LO 0x05 #define DG_HDELAY_LO 0x06 #define DG_HACTIVE_LO 0x07 #define DG_HSCALE_HI 0x08 #define DG_HSCALE_LO 0x09 #define DG_BRIGHT 0x0A #define DG_CONTROL 0x0B #define DG_CONTRAST_LO 0x0C #define DG_SAT_U_LO 0x0D #define DG_SAT_V_LO 0x0E #define DG_HUE 0x0F #define DG_OFORM 0x12 #define DG_VSCALE_HI 0x13 #define DG_VSCALE_LO 0x14 #define DG_TEST 0x15 #define DG_VPOLE 0x16 #define DG_IDCODE 0x17 #define DG_ADELAY 0x18 #define DG_BDELAY 0x19 #define DG_ADC 0x1A #define DG_SRESET 0x1F #ifdef __NT__ #define CTRL_STATUS 0x99 #endif //__NT__ /****************************************************************************** ** Function name : init ** Description : Locate VideoPort I/O-base and initialize the toolkit ** Parameters : none ** Return value : Errno = success / toolkitInUse / noHardwareDetected ** / driverNotDetected / oldVideoPortDetected / ** / badPointer (Windows only) / lostContact ******************************************************************************/ VPP_Errno EXPORT VPP_init(void) { VPP_Byte tmp; #ifdef __WIN32__ VPP_Byte VPP_far * volatile window; #else VPP_Word window; #endif VPP_Bool powerWasOff; currentFunction = "VPP_init"; #ifndef __WIN32__ if (c != 0) RETURN_ERROR(VPP_toolkitInUse); #endif window = detectVideoPort(&powerWasOff); if ((unsigned)window == 0) RETURN_ERROR(VPP_noHardwareDetected); if ((unsigned)window == 0xFFFE) RETURN_ERROR(VPP_noDriverDetected); if ((unsigned)window == 0xFFFF) RETURN_ERROR(VPP_oldVideoPortDetected); c = (CardData VPP_far *)malloc(sizeof(CardData)); if (c == 0) RETURN_ERROR(VPP_outOfMemory); c->configured = VPP_false; c->snapPrepared = VPP_false; c->snapStarted = VPP_false; c->snapFinished = VPP_false; c->readoutStarted = VPP_false; c->cookie = MAGIC_COOKIE; c->cardType = tmp_cardType; #ifndef VPP_NO_FLASH c->flashFn = 0; #endif #if defined(__WIN32__) c->hCard = tmp_hCard; c->ctrlStatus = window; #elif defined(_Windows) || defined(__WATCOMC__) c->ctrlStatus = getDosMemory(window); if (c->ctrlStatus == 0) { free(c); c = 0; RETURN_ERROR(VPP_badPointer); } #else c->ctrlStatus = (VPP_Byte VPP_far*)MK_FP(window,0); #endif /* __WIN32__ */ c->dataReg = c->ctrlStatus+0x800; tmp = 0x77; if (powerWasOff) #ifdef __NT__ if (NTwriteI2C(0x1F,&tmp,1)!=1) /* Reset digitizer regs to default */ #else if (writeI2C(0x1F,&tmp,1)!=1) /* Reset digitizer regs to default values */ #endif { free(c); c = 0; RETURN_ERROR(VPP_lostContact); } fillLookupTables(1.0f); if (linebuf == 0) { linebuf = (VPP_Byte VPP_far *)malloc(VPP_MAX_WIDTH*2); if (linebuf == 0) { free(c); c = 0; RETURN_ERROR(VPP_outOfMemory); } #ifndef VPP_NO_STRETCH_IMAGE c->linebuf1 = (VPP_Byte VPP_far *)malloc(VPP_MAX_WIDTH*2); if (c->linebuf1 == 0) { free(c); c = 0; free(linebuf); linebuf = 0; RETURN_ERROR(VPP_outOfMemory); } c->linebuf2 = (VPP_Byte VPP_far *)malloc(VPP_MAX_WIDTH*2); if (c->linebuf2 == 0) { free(c->linebuf1); free(c); c = 0; free(linebuf); linebuf = 0; RETURN_ERROR(VPP_outOfMemory); } #endif /* VPP_STRETCH_IMAGE */ } #if !defined(VPP_NO_RGB16) && defined(VPP_FAST_RGB16) if (Cpr16 == 0) { Cpr16 = (VPP_Word VPP_far *) malloc((VPP_DWord)sizeof(VPP_Word)<<(YBITS+CrBITS+CbBITS)); if (Cpr16 == 0) { #ifndef VPP_NO_STRETCH_IMAGE free(c->linebuf1); free(c->linebuf2); #endif /* VPP_STRETCH_IMAGE */ free(c); c = 0; free(linebuf); linebuf = 0; RETURN_ERROR(VPP_outOfMemory); } fillFastLookupTable(); } #endif /* VPP_FAST_RGB16 */ numCardsInitialized++; return VPP_success; } /****************************************************************************** ** Function name : closedown ** Description : Releases the VideoPort (optionally turns power off) ** Parameters : none ** Return value : Errno = success / notInitialized ******************************************************************************/ VPP_Errno EXPORT VPP_closedown(VPP_Bool powerOff) { currentFunction = "VPP_closedown"; if (c == 0) RETURN_ERROR(VPP_notInitialized); numCardsInitialized--; #ifdef __WIN32__ closeVideoPort(powerOff); #else if (powerOff != VPP_false) closeVideoPort(); #endif #if (defined(_Windows) || defined(__WATCOMC__)) && !defined(__WIN32__) freeDosMemory(c->ctrlStatus); #endif if (numCardsInitialized == 0) { free(linebuf); linebuf = 0; #ifndef VPP_NO_STRETCH_IMAGE free(c->linebuf1); c->linebuf1 = 0; free(c->linebuf2); c->linebuf1 = 0; #endif /* VPP_STRETCH_IMAGE */ #if !defined(VPP_NO_RGB16) && defined(VPP_FAST_RGB16) free(Cpr16); Cpr160 = 0; #endif /* VPP_FAST_RGB16 */ } free(c); c = 0; return VPP_success; } /****************************************************************************** ** Function name : getCurrentCardHandle ** Description : Returns the handle of the current card. To be used later ** with setActiveCard in a multi-card application. ** Parameters : cardHandle = pointer to return value ** Return value : Errno = success / badPointer / notInitialized ******************************************************************************/ VPP_Errno EXPORT VPP_getCurrentCardHandle(VPP_CardHandle *cardHandle) { currentFunction = "VPP_getCurrentCardHandle"; if (cardHandle == 0) RETURN_ERROR(VPP_badPointer); *cardHandle = 0; if (c == 0) RETURN_ERROR(VPP_notInitialized); *cardHandle = (VPP_CardHandle)c; return VPP_success; } /****************************************************************************** ** Function name : setActiveCard ** Description : Sets the active card according to the parameter. ** Parameters : cardHandle = handle of new card ** Return value : Errno = success / notInitialized ******************************************************************************/ VPP_Errno EXPORT VPP_setActiveCard(VPP_CardHandle cardHandle) { currentFunction = "VPP_setActiveCard"; c = (CardData VPP_far *)cardHandle; if (c == 0 || c->ctrlStatus == 0 || c->cookie != MAGIC_COOKIE) { c = 0; RETURN_ERROR(VPP_notInitialized); } return VPP_success; } /****************************************************************************** ** Function name : errorString ** Description : Returns a string describing an error ** Parameters : err = Error number ** Return value : Pointer to error string ******************************************************************************/ const char VPP_far* EXPORT VPP_errorString(VPP_Errno err) { switch (err) { case VPP_success: return "No error"; case VPP_toolkitInUse: return "MRT Imaging Card toolkit is already in use"; case VPP_noHardwareDetected: return "No MRT Imaging Card detected"; case VPP_noDriverDetected: return "No MRT Imaging Card driver detected"; case VPP_oldVideoPortDetected: return "This toolkit works only with MS801 and MS802"; case VPP_notInitialized: return "Toolkit is not initialized"; case VPP_notConfigured: return "Video digitizer is not configured"; case VPP_noSignalDetected: return "No video signal detected"; case VPP_snapNotPrepared: return "Attempt to start snap before snap prepared"; case VPP_snapNotStarted: return "Attempt to finish snap before snap started"; case VPP_snapNotFinished: return "Attempt to read image before snap finished"; case VPP_noColorSnapped: return "Attempt to read monochrome image as colour"; case VPP_readoutNotStarted: return "Attempt to read image before startReadout"; case VPP_readoutOutsideSnappedImage: return "Attempt to read outside snapped image"; case VPP_parameterOutOfRange: return "Parameter to function is out of range"; case VPP_imageWidthOutOfRange: return "Image width is out of range"; case VPP_imageHeightOutOfRange: return "Image height is out of range"; case VPP_badPointer: return "Bad pointer (possibly NULL)"; case VPP_outOfMemory: return "Could not claim the memory needed in function"; case VPP_fileIOError: return "An error while reading or writing to file"; #ifdef TESTMODE case VPP_lostContact: return "Lost contact with digitizer (no acknowledge)"; case VPP_lostContact2: return "IęC-timer not running"; #else case VPP_lostContact: return "Lost contact with MRT Imaging Card"; #endif default: return "Unknown error"; } } /****************************************************************************** ** Function name : lastErrorFunctionName ** Description : Returns the name of the last function causing an error ** Parameters : none ** Return value : Pointer to function name string ******************************************************************************/ const char VPP_far* EXPORT VPP_lastErrorFunctionName(void) { return lastErrorFunction; } #define MAGIC_AX 31416U #define MAGIC_BX 21071U #define INTR1 0x11 #define INTR2 0x12 /****************************************************************************** ** Function name : getCardIdStrings ** Description : Retrieve the identification strings stored in the ** MRT Imaging Card. There are four strings which will be ** filled into the string buffer separated by newlines. The ** last string is zero-terminated. ** Parameters : stringBuf = buffer to return strings in ** bufSize = size of stringBuf in bytes. The buffer should ** be big enough to hold four strings of about 80 chars ** each. If the buffer is not big enough, the buffer ** will not contain all the strings, but it will still be ** zero-terminated. ** Return value : Errno = success / notInitialized / badPointer / ** parameterOutOfRange / outOfMemory ** If the string buffer is empty this indicates a problem ** in the hardware driver. ******************************************************************************/ VPP_Errno EXTERN VPP_getCardIdStrings(VPP_Char VPP_far* stringBuf, VPP_Word bufSize) { currentFunction = "VPP_getCardIdStrings"; if (c == 0) RETURN_ERROR(VPP_notInitialized); if (stringBuf == 0) RETURN_ERROR(VPP_badPointer); if (bufSize == 0) RETURN_ERROR(VPP_parameterOutOfRange); #ifdef __WIN32__ { DWORD inBuf[1]; DWORD outSize; inBuf[0] = (DWORD)c->hCard; outSize = 0; if (!DeviceIoControl(hMS80x, MS80x_REQ_CIS_VIDEO_PORT /* Request CIS strings */, (LPVOID)inBuf, 1*sizeof(DWORD), (LPVOID)stringBuf, bufSize, &outSize, NULL)) stringBuf[0] = 0; } return VPP_success; #elif defined(__WATCOMC__) stringBuf[0] = 0; /* I have not figured out how to do this in Watcom C yet */ return VPP_success; #else { static union _REGS regs; regs.x.ax = MAGIC_AX; regs.x.bx = MAGIC_BX; regs.x.cx = 5; /* Retrieve CIS strings */ regs.x.dx = bufSize; #ifdef _Windows { DWORD dosMem; WORD selector,dosSeg; VPP_Char VPP_far* dosBuf; dosMem = GlobalDosAlloc(bufSize); if (dosMem == 0) { stringBuf[0] = 0; RETURN_ERROR(VPP_outOfMemory); } dosSeg = (WORD)(dosMem>>16); selector = (WORD)(dosMem&0xFFFF); dosBuf = MK_FP(selector,0); dosBuf[0] = 0; regs.x.si = dosSeg; regs.x.di = 0; _int86(INTR,®s,®s); _fstrcpy(stringBuf,dosBuf); GlobalDosFree(selector); } #else stringBuf[0] = 0; regs.x.si = FP_SEG(stringBuf); regs.x.di = FP_OFF(stringBuf); _int86(INTR,®s,®s); #endif } return VPP_success; #endif /* __WATCOMC__ */ } /****************************************************************************** ** Function name : videoConfig ** Description : Configure video digitizer, reset signal present bit. ** After calling this function, delay 500-1000 ms before ** calling snap, to let the digitizer circuit stabilize. ** Parameters : inputChannel = [0..1] ** videoStandard = NTSC/PAL ** signalType = composite/S-video/monochrome ** Return value : Errno = success / notInitialized / parameterOutOfRange ** / badPointer / lostContact ******************************************************************************/ VPP_Errno EXPORT VPP_videoConfig(VPP_Byte inputChannel, VPP_SignalType signalType, VPP_VideoStandard VPP_far* videoStandard) { static VPP_Byte st[3] = { 0, 0x40U, 0x80U }; VPP_Byte buf[3]; currentFunction = "VPP_videoConfig"; c->configured = VPP_false; c->snapPrepared = VPP_false; c->snapStarted = VPP_false; c->snapFinished = VPP_false; c->readoutStarted = VPP_false; if (c == 0) RETURN_ERROR(VPP_notInitialized); if (videoStandard == 0) RETURN_ERROR(VPP_badPointer); if (inputChannel > 1 || signalType < VPP_composite || signalType > VPP_monochrome) RETURN_ERROR(VPP_parameterOutOfRange); READI2C(DG_STATUS,buf,1); c->videoStd = ((buf[0] & 0x10) != 0) ? VPP_PAL : VPP_NTSC; *videoStandard = ((buf[0] & 0x80) == 0x80) ? c->videoStd : VPP_noSignal; /* Reset signal present bit */ buf[0] = buf[0] & (VPP_Byte) (0x7FU); /* Set input channel */ buf[1] = (VPP_Byte) (0x58U | (inputChannel * 0x20)); /* Reset temporal decimation */ buf[2] = 0; WRITEI2C(DG_STATUS,buf,3); /* Set signal type */ READI2C(DG_CONTROL,buf,1); buf[0] = (VPP_Byte) ((buf[0] & 0x07U) | st[signalType] | 0x20U); WRITEI2C(DG_CONTROL,buf,1); /* Set output format register */ buf[0] = 0x06; WRITEI2C(DG_OFORM,buf,1); /* Set Video Timing Polarity */ buf[0] = 0; WRITEI2C(DG_VPOLE,buf,1); /* Set AGCDelay, BurstDelay and ADC interface registers */ buf[0] = (VPP_Byte) (c->videoStd==VPP_PAL ? 0x80U : 0x68U); buf[1] = (VPP_Byte) (c->videoStd==VPP_PAL ? 0x72U : 0x5DU); buf[2] = (VPP_Byte) (signalType == VPP_Svideo ? 0x80 : 0x82); WRITEI2C(DG_ADELAY,buf,3); c->configured = VPP_true; return VPP_success; } /****************************************************************************** ** Function name : testSignal ** Description : Test if, and what kind of video signal is present ** Parameters : videoStandard = pointer to return value ** Return value : Errno = success / badPointer / notInitialized / lostContact ******************************************************************************/ VPP_Errno EXPORT VPP_testSignal(VPP_VideoStandard VPP_far* videoStandard) { VPP_Byte status; VPP_VideoStandard vst; currentFunction = "VPP_signalPresent"; if (videoStandard == 0) RETURN_ERROR(VPP_badPointer); if (c == 0) RETURN_ERROR(VPP_notInitialized); *videoStandard = VPP_false; READI2C(DG_STATUS,&status,1); vst = ((status & 0x10) != 0) ? VPP_PAL : VPP_NTSC; *videoStandard = ((status & 0x80) == 0x80) ? vst : VPP_noSignal; status &= 0x7FU; WRITEI2C(DG_STATUS,&status,1); return VPP_success; } /****************************************************************************** ** Function name : setBrightness ** Description : Sets the brightness control register of the digitizer ** Parameters : brightness = [-128..127] (0 = normal) ** Return value : Errno = success / notInitialized / lostContact ******************************************************************************/ VPP_Errno EXPORT VPP_setBrightness(VPP_Char brightness) { currentFunction = "VPP_setBrightness"; if (c == 0) RETURN_ERROR(VPP_notInitialized); WRITEI2C(DG_BRIGHT,(VPP_Byte*)&brightness,1); return VPP_success; } /****************************************************************************** ** Function name : setContrast ** Description : Sets the contrast control register of the digitizer ** Parameters : contrast = [-128..127] (0 = normal) ** Return value : Errno = success / notInitialized / lostContact ******************************************************************************/ VPP_Errno EXPORT VPP_setContrast (VPP_Char contrast) { VPP_Int contr; VPP_Byte buf[2]; currentFunction = "VPP_setContrast"; if (c == 0) RETURN_ERROR(VPP_notInitialized); if (contrast<=0) contr = (VPP_Int)(((VPP_Long)contrast*216+216L*128)/128); else contr = (VPP_Int)((VPP_Long)contrast*(511-216)/127+216); READI2C(DG_CONTROL,buf,1); buf[0] = (VPP_Byte)((buf[0] & 0xFB) | ((contr>>8)<<2)); buf[1] = (VPP_Byte)(contr & 0xFF); WRITEI2C(DG_CONTROL,buf,2); return VPP_success; } /****************************************************************************** ** Function name : setSaturation ** Description : Sets the color saturation control reg. of the digitizer ** Parameters : saturation = [-128..127] (0 = normal) ** Return value : Errno = success / notInitialized / lostContact ******************************************************************************/ VPP_Errno EXPORT VPP_setSaturation(VPP_Char saturation) { VPP_Int satu,satv; VPP_Byte buf[2]; currentFunction = "VPP_setSaturation"; if (c == 0) RETURN_ERROR(VPP_notInitialized); if (saturation<=0) { satu = (VPP_Int)((((VPP_Long)saturation)*254+254L*128)/128); satv = (VPP_Int)((((VPP_Long)saturation)*180+180L*128)/128); } else { satu = (VPP_Int)((VPP_Long)saturation*(511-254)/127+254); satv = (VPP_Int)((VPP_Long)saturation*(362-180)/127+180); } READI2C(DG_CONTROL,buf,1); buf[0] = (VPP_Byte)((buf[0] & 0xFC) | ((satu>>8)<<1) | (satv>>8)); WRITEI2C(DG_CONTROL,buf,1); buf[0] = (VPP_Byte)(satu & 0xFF); buf[1] = (VPP_Byte)(satv & 0xFF); WRITEI2C(DG_SAT_U_LO,buf,2); return VPP_success; } /****************************************************************************** ** Function name : setHue ** Description : Sets the hue control register of the digitizer (works ** for NTSC video signals only) ** Parameters : hue: ** -128 = -90 degrees ** 0 = 0 degrees ** 127 = +89.3 degrees ** Return value : Errno = success / notInitialized / lostContact ******************************************************************************/ VPP_Errno EXPORT VPP_setHue(VPP_Char hue) { currentFunction = "VPP_setHue"; if (c == 0) RETURN_ERROR(VPP_notInitialized); WRITEI2C(DG_HUE,(VPP_Byte*)&hue,1); return VPP_success; } /****************************************************************************** ** Function name : setGamma ** Description : Sets the gamma correction value ** Parameters : gamma = Power (0.0 = normal) ** Return value : Errno = success / notInitialized / parameterOutOfRange ******************************************************************************/ VPP_Errno EXPORT VPP_setGamma(float gamma) { currentFunction = "VPP_setGamma"; if (c == 0) RETURN_ERROR(VPP_notInitialized); if (gamma == 0) RETURN_ERROR(VPP_parameterOutOfRange); fillLookupTables(gamma); return VPP_success; } /****************************************************************************** ** Function name : getBrightnes ** Description : Gets the brightness control register of the digitizer ** Parameters : brightness = pointer to return value ** Return value : Errno = success / notInitialized / badPointer ** / lostContact ******************************************************************************/ VPP_Errno EXPORT VPP_getBrightness(VPP_Char VPP_far* brightness) { VPP_Byte br; currentFunction = "VPP_getBrightness"; if (c == 0) RETURN_ERROR(VPP_notInitialized); if (brightness == 0) RETURN_ERROR(VPP_badPointer); READI2C(DG_BRIGHT,&br,1); *brightness = (VPP_Char)br; return VPP_success; } /****************************************************************************** ** Function name : getContrast ** Description : Gets the contrast control register of the digitizer ** Parameters : contrast = pointer to return value ** Return value : Errno = success / notInitialized / badPointer ** / lostContact ******************************************************************************/ VPP_Errno EXPORT VPP_getContrast(VPP_Char VPP_far* contrast) { VPP_Byte buf[2]; VPP_Long contr; currentFunction = "VPP_getContrast"; if (c == 0) RETURN_ERROR(VPP_notInitialized); if (contrast == 0) RETURN_ERROR(VPP_badPointer); READI2C(DG_CONTROL,buf,2); contr = (((VPP_Long)buf[0] & 0x04) << 6) + buf[1]; if (contr<=216) *contrast = (VPP_Char)((contr-216)*128/216); else *contrast = (VPP_Char)(((contr-216)*127+(511-216)/2)/(511-216)); return VPP_success; } /****************************************************************************** ** Function name : getSaturation ** Description : Gets the saturation control register of the digitizer ** Parameters : saturation = pointer to return value ** Return value : Errno = success / notInitialized / badPointer ** / lostContact ******************************************************************************/ VPP_Errno EXPORT VPP_getSaturation(VPP_Char VPP_far* saturation) { VPP_Byte buf[2]; VPP_Long sat; currentFunction = "VPP_getSaturation"; if (c == 0) RETURN_ERROR(VPP_notInitialized); if (saturation == 0) RETURN_ERROR(VPP_badPointer); READI2C(DG_CONTROL,buf,1); READI2C(DG_SAT_U_LO,buf+1,1); sat = (((VPP_Long)buf[0] & 0x02) << 7) + buf[1]; if (sat<=254) *saturation = (VPP_Char)((sat-254)*128/254); else *saturation = (VPP_Char)(((sat-254)*127+(511-254)/2)/(511-254)); return VPP_success; } /****************************************************************************** ** Function name : getHue ** Description : Gets the hue control register of the digitizer ** Parameters : hue = pointer to return value ** Return value : Errno = success / notInitialized / badPointer ** / lostContact ******************************************************************************/ VPP_Errno EXPORT VPP_getHue(VPP_Char VPP_far* hue) { VPP_Byte hu; currentFunction = "VPP_getHue"; if (c == 0) RETURN_ERROR(VPP_notInitialized); if (hue == 0) RETURN_ERROR(VPP_badPointer); READI2C(DG_HUE,&hu,1); *hue = (VPP_Char)hu; return VPP_success; } #ifndef VPP_NO_FLASH /****************************************************************************** ** Function name : enableFlash ** Description : Enables flash callback routine during snap ** Parameters : flashSelect = number of callbacks requested during snap ** oddFieldFlash = callback for odd field ** evenFieldFlash = callback for even field ** bothFieldsFlash = callback for both fields ** flashFunc = pointer to callback routine ** If flashFunc == 0, the default flash routine is used ** Parameters: whichFlash = oddFieldFlash ** during integr. of odd field ** whichFlash = evenFieldFlash ** during integr. of even field ** Return value: none ** flashDelay = delay in milliseconds between start of ** field and the flash. This value is camera-dependent. ** Legal values are 0-16 for NTSC and 0-20 for PAL. ** Typical value is 8 (=VPP_DEFAULT_FLASH_DELAY). ** Return value : Errno = success / notInitialized / parameterOutOfRange ******************************************************************************/ VPP_Errno EXPORT VPP_enableFlash(VPP_FlashSelect flashSelect, VPP_FlashFuncPtr flashFunc, VPP_Word flashDelay) { currentFunction = "VPP_enableFlash"; if (c == 0) RETURN_ERROR(VPP_notInitialized); if ((flashSelect != VPP_oddFieldFlash && flashSelect != VPP_evenFieldFlash && flashSelect != VPP_bothFieldsFlash) || (flashDelay > (c->videoStd == VPP_NTSC ? 16U : 20U))) RETURN_ERROR(VPP_parameterOutOfRange); if (flashFunc == 0) flashFunc = ourFlashFunc; c->flashFn = flashFunc; c->flashSel = flashSelect; c->flashDly = flashDelay; return VPP_success; } /****************************************************************************** ** Function name : disableFlash ** Description : Disables flash callback routine ** Parameters : none ** Return value : Errno = success ******************************************************************************/ VPP_Errno EXPORT VPP_disableFlash(void) { currentFunction = "VPP_disableFlash"; c->flashFn = 0; return VPP_success; } #endif /* VPP_NO_FLASH */ /****************************************************************************** ** Function name : getLimits ** Description : Gets the area limits for the given video standard and ** the current type of VideoPort. ** Parameters : videoStandard = Video standard ** limitData = Output struct ** Return value : Errno = success / notInitialized / notConfigured / ** parameterOutOfRange / badPointer ******************************************************************************/ VPP_Errno EXPORT VPP_getLimits(VPP_VideoStandard videoStandard, VPP_LimitData VPP_far* limitData) { currentFunction = "VPP_getLimits"; /* Check input data */ if (c == 0) RETURN_ERROR(VPP_notInitialized); if (videoStandard != VPP_PAL && videoStandard != VPP_NTSC && videoStandard != VPP_noSignal) RETURN_ERROR(VPP_parameterOutOfRange); if (limitData == 0) RETURN_ERROR(VPP_badPointer); fillLimits(videoStandard,limitData); return VPP_success; } #define CSR_HOME 0x80U #define CSR_NEWLINE 0x40U #define CSR_16_BIT_MONO 0x20U #define CSR_YCRCB 0x00U #define CSR_CAPTURE_CMD 0x10U #define CSR_FRAME_MODE 0x08U #define CSR_I2C_DIR 0x04U #define CSR_I2C_DATA 0x02U #define CSR_I2C_CLOCK 0x01U #define CSR_CAPTURE_FLAG 0x80U #define CSR_FIELD 0x40U #define CSR_I2C_TIMER 0x01U /****************************************************************************** ** Function name : prepareSnap ** Description : Set up digitizer registers for the following snaps ** Because the register setup is time consuming, this ** function should not be called for each snap when speed ** is important. ** Parameters : snapData = Input struct ** xOffset : X offset in active video area ** xActive : Width of active video area ** xPixels : Width of digitized area in pixels ** yOffset : Y offset in active video area ** yActive : Height of active video area ** yPixels : Height of digitized area in pixels ** interlaced : Flag to turn on interlaced snap ** monochrome : Flag to turn on monochrome snap ** Return value : Errno = success / notInitialized / notConfigured ** / imageWidthOutOfRange / imageHeightOutOfRange ** / badPointer / lostContact ******************************************************************************/ VPP_Errno EXPORT VPP_prepareSnap(const VPP_SnapData VPP_far* snapData) { VPP_Word xPixels,yPixels; VPP_Word HDELAY,HACTIVE,HSCALE,VDELAY,VACTIVE,VSCALE; static VPP_Word hDelay[2] = { 126/*Bt DEFAULT:135*/, 176/*Bt default:186*/ }; VPP_Byte buf[7]; VPP_LimitData limitData; currentFunction = "VPP_prepareSnap"; /* Check input data */ if (c == 0) RETURN_ERROR(VPP_notInitialized); if (!c->configured) RETURN_ERROR(VPP_notConfigured); if (snapData == 0) RETURN_ERROR(VPP_badPointer); fillLimits(c->videoStd,&limitData); if ((snapData->xOffset+snapData->xActive > limitData.xActiveMax) || #ifdef VPP_NO_STRETCH_IMAGE (snapData->xPixels > snapData->xActive) || #endif /* VPP_STRETCH_IMAGE */ (snapData->xPixels > limitData.xPixelsMax) || ((long)snapData->xPixels*limitData.xActiveRatio < (long)snapData->xActive*limitData.xPixelsRatio)) RETURN_ERROR(VPP_imageWidthOutOfRange); if (((snapData->yOffset+snapData->yActive)* (snapData->interlaced == VPP_true ? 1 : 2) > limitData.yActiveMax) || #ifdef VPP_NO_STRETCH_IMAGE (snapData->yPixels > snapData->yActive) || #endif /* VPP_STRETCH_IMAGE */ (snapData->yPixels > limitData.yPixelsMax) || ((long)snapData->yPixels*limitData.yActiveRatio < (long)snapData->yActive*limitData.yPixelsRatio)) RETURN_ERROR(VPP_imageHeightOutOfRange); c->snapPrepared = VPP_false; c->snapStarted = VPP_false; c->snapFinished = VPP_false; c->readoutStarted = VPP_false; xPixels = snapData->xPixels; yPixels = snapData->yPixels; #ifndef VPP_NO_STRETCH_IMAGE if (xPixels > snapData->xActive) xPixels = snapData->xActive; if (yPixels > snapData->yActive) yPixels = snapData->yActive; if (c->cardType != 0) { if (xPixels > 510) xPixels = 510; if (yPixels > 510) yPixels = 510; } #endif HSCALE = (VPP_Word)(4096L*snapData->xActive/xPixels-4096); HACTIVE = xPixels; HDELAY = (VPP_Word)(((long)(hDelay[c->videoStd]+snapData->xOffset))* xPixels/snapData->xActive); VSCALE = (VPP_Word)((0x10000L-(512L*snapData->yActive/yPixels- 512))&0x1FFF); VACTIVE = snapData->yActive; VDELAY = (VPP_Word) (snapData->yOffset+2); c->xOddStart = ((HDELAY&1) == 1); if ((HACTIVE&1) == 1) HACTIVE++; if (!snapData->interlaced) { VACTIVE *= (VPP_Word) (2); VDELAY *= (VPP_Word) (2); } c->yOff = 0; if ((VDELAY&1) == 1) { VDELAY--; VACTIVE++; c->yOff = 1; } c->imageWidth = snapData->xPixels; c->imageHeight = snapData->yPixels; c->actualSnapWidth = xPixels; c->actualSnapHeight = yPixels; c->monoSnap = snapData->monochrome; c->interlacedSnap = snapData->interlaced; /* Set image resolution values */ buf[0] = (VPP_Byte)(((VDELAY>>8)<<6)+((VACTIVE>>8)<<4)+ ((HDELAY>>8)<<2)+(HACTIVE>>8)); buf[1] = (VPP_Byte)(VDELAY); buf[2] = (VPP_Byte)(VACTIVE); buf[3] = (VPP_Byte)(HDELAY); buf[4] = (VPP_Byte)(HACTIVE); buf[5] = (VPP_Byte)(HSCALE >> 8); buf[6] = (VPP_Byte)(HSCALE); WRITEI2C(DG_CROP,buf,7); buf[0] = (VPP_Byte) ((VPP_Byte)(VSCALE >> 8) | (snapData->interlaced ? 0x20U : 0U) | (HACTIVE > 768U ? 0x80U : 0x40U)); buf[1] = (VPP_Byte)(VSCALE); WRITEI2C(DG_VSCALE_HI,buf,2); /* Set optional 3 MHz lowpass filter */ READI2C(DG_CONTROL,buf,1); buf[0] = (VPP_Byte) ((buf[0] & 0xDFU) | (snapData->xPixels*2 < snapData->xActive ? 0 : 0x20U)); WRITEI2C(DG_CONTROL,buf,1); c->snapPrepared = VPP_true; return VPP_success; } /****************************************************************************** ** Function name : startSnap ** Description : Start the process of snapping a new image ** Parameters : none ** Return value : Errno = success / notInitialized / snapNotPrepared ******************************************************************************/ VPP_Errno EXPORT VPP_startSnap(void) { VPP_Byte frameMode; currentFunction = "VPP_startSnap"; c->snapStarted = VPP_false; c->snapFinished = VPP_false; c->readoutStarted = VPP_false; /* Check input data */ if (c == 0) RETURN_ERROR(VPP_notInitialized); if (!c->snapPrepared) RETURN_ERROR(VPP_snapNotPrepared); frameMode = (VPP_Byte) (((c->interlacedSnap == VPP_true) ? CSR_FRAME_MODE : 0) | ((c->monoSnap == VPP_true) ? CSR_16_BIT_MONO : 0)); // /* Reset both counters */ // *c->ctrlStatus = CSR_HOME; // *c->ctrlStatus = 0; // /* Capture-mode, full frame or one field */ // *c->ctrlStatus = (VPP_Byte) (CSR_CAPTURE_CMD | frameMode); // /* Reset Capture-mode */ // *c->ctrlStatus = frameMode; // Reset both counters write_csr(CSR_HOME); write_csr(0); // Capture-mode, full frame or one field write_csr((VPP_Byte)(CSR_CAPTURE_CMD | frameMode)); // Reset Capture-mode write_csr(frameMode); c->snapStarted = VPP_true; return VPP_success; } /****************************************************************************** ** Function name : finishSnap ** Description : Finish the snapping process ** Parameters : none ** Return value : Errno = success / notInitialized / snapNotStarted / ** noSignalDetected ******************************************************************************/ VPP_Errno EXPORT VPP_finishSnap(void) { int cntr; int timeout=100; currentFunction = "VPP_finishSnap"; c->snapFinished = VPP_false; c->readoutStarted = VPP_false; /* Check input data */ if (c == 0) RETURN_ERROR(VPP_notInitialized); if (!c->snapStarted) RETURN_ERROR(VPP_snapNotStarted); /* Wait for end of frame */ for (cntr=0; cntrctrlStatus & CSR_CAPTURE_CMD) == 0) if ((read_csr() & CSR_CAPTURE_CMD) == 0) break; msleep(1); } if (cntr >= timeout) RETURN_ERROR(VPP_noSignalDetected); /* 6C Reset counters */ // *c->ctrlStatus = CSR_HOME; // *c->ctrlStatus = 0; write_csr(CSR_HOME); write_csr(0); /* Set global variables */ c->snapFinished = VPP_true; c->snapStarted = VPP_false; #ifndef VPP_NO_STRETCH_IMAGE c->linebuf1line = -1; c->linebuf2line = -1; #endif return VPP_success; } #ifndef VPP_NO_FLASH /****************************************************************************** ** Function name : flashSnap ** Description : Snapping with flashes ** Parameters : none ** Return value : Errno = success / notInitialized / snapNotPrepared / ** noSignalDetected ******************************************************************************/ VPP_Errno EXPORT VPP_flashSnap(void) { int cntr; int timeout=100; VPP_Byte frameMode; currentFunction = "VPP_flashSnap"; c->snapStarted = VPP_false; c->snapFinished = VPP_false; c->readoutStarted = VPP_false; /* Check input data */ if (c == 0) RETURN_ERROR(VPP_notInitialized); if (!c->snapPrepared) RETURN_ERROR(VPP_snapNotPrepared); /* Flash during integration of odd field if enabled */ if (c->flashFn != 0 && (c->flashSel & VPP_oddFieldFlash)) { /* Wait for odd field */ for (cntr=0; cntrctrlStatus & CSR_FIELD) == 0) if ((read_csr() & CSR_FIELD) == 0 ) break; msleep(1); } if (cntr >= timeout) RETURN_ERROR(VPP_noSignalDetected); /* Wait for even field */ for (cntr=0; cntrctrlStatus & CSR_FIELD) != 0) if ((read_csr() & CSR_FIELD) != 0) break; msleep(1); } if (cntr >= timeout) RETURN_ERROR(VPP_noSignalDetected); msleep(c->flashDly); /* Delay a period into the field */ /* Do the flash */ c->flashFn(VPP_oddFieldFlash); } frameMode = (VPP_Byte) (((c->interlacedSnap == VPP_true) ? CSR_FRAME_MODE : 0) | ((c->monoSnap == VPP_true) ? CSR_16_BIT_MONO : 0)); /* Reset both counters */ // *c->ctrlStatus = CSR_HOME; // *c->ctrlStatus = 0; write_csr(CSR_HOME); write_csr(0); /* Capture-mode, full frame or one field */ // *c->ctrlStatus = (VPP_Byte) (CSR_CAPTURE_CMD | frameMode); write_csr((VPP_Byte) (CSR_CAPTURE_CMD | frameMode)); /* Wait for new frame */ for (cntr=0; cntrctrlStatus & CSR_CAPTURE_FLAG) != 0) if ((read_csr() & CSR_CAPTURE_FLAG) != 0) break; msleep(1); } if (cntr >= timeout) RETURN_ERROR(VPP_noSignalDetected); /* Reset Capture-mode */ // *c->ctrlStatus = frameMode; write_csr(frameMode); /* Flash during integration of even field if enabled */ if (c->flashFn != 0 && (c->flashSel & VPP_evenFieldFlash)) { msleep(c->flashDly); /* Delay a period into the field */ c->flashFn(VPP_evenFieldFlash); } /* Wait for end of frame */ for (cntr=0; cntrctrlStatus & CSR_CAPTURE_CMD) == 0) if ((read_csr() & CSR_CAPTURE_CMD) == 0 ) break; msleep(1); } if (cntr >= timeout) RETURN_ERROR(VPP_noSignalDetected); /* 6C Reset counters */ // *c->ctrlStatus = CSR_HOME; // *c->ctrlStatus = 0; write_csr(CSR_HOME); write_csr(0); /* Set global variables */ c->snapFinished = VPP_true; c->snapStarted = VPP_false; #ifndef VPP_NO_STRETCH_IMAGE c->linebuf1line = -1; c->linebuf2line = -1; #endif return VPP_success; } #endif /* VPP_NO_FLASH */ /****************************************************************************** ** Function name : extTrigSnap ** Description : Wait for external trigger before snapping. ** Parameters : msecTimeout = timeout value. If no external trigger ** is detected within msecTimeout milliseconds, the ** snap is performed anyway and the function returns. ** Return value : Errno = success / notInitialized / snapNotPrepared / ** noSignalDetected ******************************************************************************/ VPP_Errno EXPORT VPP_extTrigSnap(VPP_Word msecTimeout) { int cntr; int timeout=100; VPP_Byte frameMode; currentFunction = "VPP_extTrigSnap"; c->snapStarted = VPP_false; c->snapFinished = VPP_false; c->readoutStarted = VPP_false; /* Check input data */ if (c == 0) RETURN_ERROR(VPP_notInitialized); if (!c->snapPrepared) RETURN_ERROR(VPP_snapNotPrepared); /* Wait for external trigger */ /* Cannot use msleep. Must poll constantly not to miss the trigger pulse */ #ifdef _Windows { DWORD start; start = GetTickCount(); while ((*(c->ctrlStatus+2) & 1) != 1) if ((GetTickCount() - start) >= (DWORD)msecTimeout) break; } #else { clock_t start,clockTimeout; start = clock(); clockTimeout = (clock_t)((float)msecTimeout*CLK_TCK/1000.0); while ((*(c->ctrlStatus+2) & 1) != 1) if ((clock() - start) >= clockTimeout) break; } #endif /* Wait for even field before snapping, to avoid snapping the wrong (preceding) image */ for (cntr=0; cntrctrlStatus & CSR_FIELD) != 0) if ((read_csr() & CSR_FIELD) !=0) break; msleep(1); } if (cntr >= timeout) RETURN_ERROR(VPP_noSignalDetected); frameMode = (VPP_Byte) (((c->interlacedSnap == VPP_true) ? CSR_FRAME_MODE : 0) | ((c->monoSnap == VPP_true) ? CSR_16_BIT_MONO : 0)); /* Reset both counters */ // *c->ctrlStatus = CSR_HOME; // *c->ctrlStatus = 0; write_csr(CSR_HOME); write_csr(0); /* Capture-mode, full frame or one field */ // *c->ctrlStatus = (VPP_Byte) (CSR_CAPTURE_CMD | frameMode); write_csr((VPP_Byte) (CSR_CAPTURE_CMD | frameMode)); /* Reset Capture-mode */ // *c->ctrlStatus = frameMode; write_csr(frameMode); /* Wait for end of frame */ for (cntr=0; cntrctrlStatus & CSR_CAPTURE_CMD) == 0) if ((read_csr() & CSR_CAPTURE_CMD) == 0) break; msleep(1); } if (cntr >= timeout) RETURN_ERROR(VPP_noSignalDetected); /* 6C Reset counters */ // *c->ctrlStatus = CSR_HOME; // *c->ctrlStatus = 0; write_csr(CSR_HOME); write_csr(0); /* Set global variables */ c->snapFinished = VPP_true; c->snapStarted = VPP_false; #ifndef VPP_NO_STRETCH_IMAGE c->linebuf1line = -1; c->linebuf2line = -1; #endif return VPP_success; } /****************************************************************************** ** Function name : startReadout ** Description : Initialize the readout of the snapped image ** Parameters : readoutMode: (format) (size factor) ** mono Byte I... 1 ** mono4 Nibble IIII(2)... 1/2 ** RGB8 Byte RRRGGGBB(2)... 1 ** RGB15 Word 0RRRRRGGGGGBBBBB(2)... 2 ** RGB16 Word RRRRRGGGGGGBBBBB(2)... 2 ** RGB24 Byte R,G,B... 3 ** BGR24 Byte B,G,R... 3 ** BGR032 Byte B,G,R,0... 4 ** YCrCb Byte Y,Cr,Cb... 3 ** CbYCrY Byte Cb,Y,Cr,Y... 2 ** YCbCr Byte Y,Cb,Cr... 3 ** lineSize = pointer to value, on return containing ** neccessary size of buffer for reading one line. ** lineSize may be 0. ** Return value : Errno = success / notInitialized / snapNotFinished / ** parameterOutOfRange ******************************************************************************/ VPP_Errno EXPORT VPP_startReadout(VPP_ReadoutMode readoutMode, VPP_Word VPP_far* lineSize) { static VPP_Word sizeFac[13] = { 0,2,1,2,4,4,6,6,8,6,4,3,4 }; currentFunction = "VPP_startReadout"; c->readoutStarted = VPP_false; if (c == 0) RETURN_ERROR(VPP_notInitialized); if (!c->snapFinished) RETURN_ERROR(VPP_snapNotFinished); switch (readoutMode) { #ifndef VPP_NO_mono case VPP_mono : break; #endif #ifndef VPP_NO_mono4 case VPP_mono4: break; #endif #ifndef VPP_NO_RGB8 case VPP_RGB8 : if (c->monoSnap) RETURN_ERROR(VPP_noColorSnapped); break; #endif #ifndef VPP_NO_RGB15 case VPP_RGB15: if (c->monoSnap) RETURN_ERROR(VPP_noColorSnapped); break; #endif #ifndef VPP_NO_RGB16 case VPP_RGB16: if (c->monoSnap) RETURN_ERROR(VPP_noColorSnapped); break; #endif #ifndef VPP_NO_RGB24 case VPP_RGB24: if (c->monoSnap) RETURN_ERROR(VPP_noColorSnapped); break; #endif #ifndef VPP_NO_BGR24 case VPP_BGR24: if (c->monoSnap) RETURN_ERROR(VPP_noColorSnapped); break; #endif #ifndef VPP_NO_BGR032 case VPP_BGR032: if (c->monoSnap) RETURN_ERROR(VPP_noColorSnapped); break; #endif #ifndef VPP_NO_YCrCb case VPP_YCrCb: if (c->monoSnap) RETURN_ERROR(VPP_noColorSnapped); break; #endif #ifndef VPP_NO_CbYCrY case VPP_CbYCrY: if (c->monoSnap) RETURN_ERROR(VPP_noColorSnapped); break; #endif #ifndef VPP_NO_YCbCr case VPP_YCbCr: if (c->monoSnap) RETURN_ERROR(VPP_noColorSnapped); break; #endif default: RETURN_ERROR(VPP_parameterOutOfRange); } c->readMode = readoutMode; c->lineNo = 0; /* Reset line and pixel counter */ // *c->ctrlStatus = CSR_HOME; // *c->ctrlStatus = 0; write_csr(CSR_HOME); write_csr(0); c->actualLineNo = 0; if (lineSize != 0) { int evenWidth = 0; #if !defined(VPP_NO_mono) && defined(VPP_FAST_MONO) if (readoutMode == VPP_mono && c->monoSnap) evenWidth = 1; #endif #ifndef VPP_NO_CbYCrY if (readoutMode == VPP_CbYCrY) evenWidth = 1; #endif if (evenWidth) *lineSize = (VPP_Word) (sizeFac[readoutMode]*((c->imageWidth+1)&(~1))/2); else *lineSize = (VPP_Word) ((sizeFac[readoutMode]*c->imageWidth+1)/2); } c->readoutStarted = VPP_true; return VPP_success; } /****************************************************************************** ** Function name : readLine ** Description : Read the next line from the snapped image ** Parameters : destination = Far pointer to buffer. Buffer must be ** lineSize (returned from startReadout) bytes long. ** Return value : Errno = success / notInitialized / readoutNotStarted / ** readoutOutsideSnappedImage / badPointer / ** parameterOutOfRange ******************************************************************************/ VPP_Errno EXPORT VPP_readLine(void VPP_far* destination, VPP_Word offset, VPP_Word length) { currentFunction = "VPP_readLine"; if (c == 0) RETURN_ERROR(VPP_notInitialized); if (!c->readoutStarted) RETURN_ERROR(VPP_readoutNotStarted); if (offset+length > c->imageWidth || c->lineNo >= c->imageHeight) RETURN_ERROR(VPP_readoutOutsideSnappedImage); if (destination == 0) RETURN_ERROR(VPP_badPointer); switch (c->readMode) { #ifndef VPP_NO_mono case VPP_mono : readLineMono8(destination, offset, length); break; #endif #ifndef VPP_NO_mono4 case VPP_mono4: readLineMono4(destination, offset, length); break; #endif #ifndef VPP_NO_RGB8 case VPP_RGB8 : readLineRGB8 (destination, offset, length); break; #endif #ifndef VPP_NO_RGB15 case VPP_RGB15: readLineRGB15(destination, offset, length); break; #endif #ifndef VPP_NO_RGB16 case VPP_RGB16: readLineRGB16(destination, offset, length); break; #endif #ifndef VPP_NO_RGB24 case VPP_RGB24: readLineRGB24(destination, offset, length); break; #endif #ifndef VPP_NO_BGR24 case VPP_BGR24: readLineBGR24(destination, offset, length); break; #endif #ifndef VPP_NO_BGR032 case VPP_BGR032: readLineBGR032(destination,offset, length); break; #endif #ifndef VPP_NO_YCrCb case VPP_YCrCb: readLineYCrCb(destination, offset, length); break; #endif #ifndef VPP_NO_CbYCrY case VPP_CbYCrY: readLineCbYCrY(destination,offset, (length+1)&(~1)); break; #endif #ifndef VPP_NO_YCbCr case VPP_YCbCr: readLineYCbCr(destination, offset, length); break; #endif default: RETURN_ERROR(VPP_parameterOutOfRange); } /* Increment linecounter */ c->lineNo++; return VPP_success; } /****************************************************************************** ** Function name : skipLines ** Description : Skips the next lines from the snapped image ** Parameters : linesToSkip = number of lines to skip ** Return value : Errno = success / notInitialized / readoutNotStarted ******************************************************************************/ VPP_Errno EXPORT VPP_skipLines(VPP_Word linesToSkip) { currentFunction = "VPP_skipLines"; if (c == 0) RETURN_ERROR(VPP_notInitialized); if (!c->readoutStarted) RETURN_ERROR(VPP_readoutNotStarted); c->lineNo += linesToSkip; return VPP_success; } /****************************************************************************** ** Function name : readWords ** Description : Reads words from VideoPort and stores it in a buffer ** Parameters : dst = Far pointer to buffer ** n = number of words to read ** Return value : none ******************************************************************************/ #if defined(__WATCOMC__) && !defined(VPP_NO_ASM) void readWords(void VPP_far* dst, int num, void VPP_far* src); #pragma aux readWords = \ "cld", \ "rep movsw" \ parm [EDI] [ECX] [ESI] \ modify [ECX EDI ESI]; #else static void readWords(void VPP_far* dst, unsigned num, void VPP_far* src) { #ifdef VPP_NO_ASM register VPP_Word VPP_far* d = (VPP_Word VPP_far*)dst; register VPP_Word VPP_far* s = (VPP_Word VPP_far*)src; register VPP_Word n = (VPP_Word) (num); if (n>0) do *d++ = *s; while (--n); #elif __NT__ NTreadWords(dst, src, num); #elif defined(__WIN32__) _asm mov ecx,num _asm mov esi,src _asm mov edi,dst _asm cld _asm rep movsw #else _asm push ds _asm mov cx,num _asm lds si,dword ptr src _asm les di,dword ptr dst _asm cld /* WORD readout: (always works, but is slower) */ _asm rep movsw // /* DWORD readout: (may produce noisy image) */ // _asm inc cx // _asm shr cx,1 // _asm db 0x66 // _asm rep movsw // /* QWORD readout: (works only on 486/DX and higher, may produce noise) */ // _asm add cx,3 // _asm shr cx,2 //lokke: // _asm wait // _asm fld qword ptr ds:[si] // _asm fstp qword ptr es:[di] // _asm add di,8 // _asm loop lokke _asm pop ds #endif /* VPP_NO_ASM */ } #endif /* __WATCOMC__ && !VPP_NO_ASM */ /****************************************************************************** ** Function name : autoCrop ** Description : This function snaps an image and analyzes it to find ** the area of the video signal that contains information. ** The function analyzes a minimal portion of the image, ** so to get a correct result, the image must be bright ** along all four edges. ** The function inspects the cropData->interlaced value ** and divides yOffset and yActive by 2 if set to false. ** Parameters : cropData = Output struct ** xOffset : X offset in active video area ** xActive : Width of active video area ** xPixels : min(previous value,xActive) ** yOffset : Y offset in active video area ** yActive : Height of active video area ** yPixels : min(previous value,yActive) ** interlaced : previous value ** monochrome : previous value ** Return value : Errno = success / notInitialized / notConfigured ** / badPointer / lostContact ******************************************************************************/ VPP_Errno EXPORT VPP_autoCrop(VPP_SnapData VPP_far* cropData) { #define THRESHOLD 24 VPP_LimitData limitData; VPP_SnapData snapData; VPP_Errno err; VPP_Word left,right,top,bottom; VPP_Word x,y; currentFunction = "VPP_autoCrop"; /* Check input data */ if (c == 0) RETURN_ERROR(VPP_notInitialized); if (!c->configured) RETURN_ERROR(VPP_notConfigured); if (cropData == 0) RETURN_ERROR(VPP_badPointer); fillLimits(c->videoStd,&limitData); top = left = 100; right = (VPP_Word) (limitData.xActiveMax-100); bottom = (VPP_Word) (limitData.yActiveMax-100); /* Snap image */ snapData.xPixels = limitData.xActiveMax; if (c->cardType != 0 && snapData.xPixels > 510) snapData.xPixels = 510; snapData.xActive = snapData.xPixels; snapData.xOffset = 0; snapData.yPixels = limitData.yActiveMax; if (c->cardType != 0 && snapData.yPixels > 510) snapData.yPixels = 510; snapData.yActive = snapData.yPixels; snapData.yOffset = 0; snapData.interlaced = VPP_true; snapData.monochrome = VPP_true; if ((err = VPP_prepareSnap(&snapData)) != VPP_success) return err; if ((err = VPP_startSnap()) != VPP_success) return err; if ((err = VPP_finishSnap()) != VPP_success) return err; /* Reset line and pixel counter */ // *c->ctrlStatus = CSR_HOME; // *c->ctrlStatus = 0; write_csr(CSR_HOME); write_csr(0); /* Search for top-left corner */ for (y=0; y < top+100; y++) { if (y < top) { readWords(linebuf,(limitData.xActiveMax/4+1)/2,c->dataReg); for (x=0; x= THRESHOLD) { top = y; break; } } else { readWords(linebuf,(left+1)/2,c->dataReg); for (x=0; x= THRESHOLD) left = x; } /* Increment linecounter */ // *c->ctrlStatus = CSR_NEWLINE; // *c->ctrlStatus = 0; write_csr(CSR_NEWLINE); write_csr(0); } if (c->cardType == 0) { /* Increment linecounter to bottom-100 */ for (; yctrlStatus = CSR_NEWLINE; // *c->ctrlStatus = 0; write_csr(CSR_NEWLINE); write_csr(0); } } else { /* Snap a new image */ snapData.xPixels = (VPP_Word) (limitData.xActiveMax-right+100); snapData.xActive = snapData.xPixels; snapData.xOffset = (VPP_Word) (right-100); snapData.yPixels = (VPP_Word) (limitData.yActiveMax-bottom+100); snapData.yActive = snapData.yPixels; snapData.yOffset = (VPP_Word) (bottom-100); snapData.interlaced = VPP_true; snapData.monochrome = VPP_true; if ((err = VPP_prepareSnap(&snapData)) != VPP_success) return err; if ((err = VPP_startSnap()) != VPP_success) return err; if ((err = VPP_finishSnap()) != VPP_success) return err; /* Reset line and pixel counter */ // *c->ctrlStatus = CSR_HOME; // *c->ctrlStatus = 0; write_csr(CSR_HOME); write_csr(0); y = bottom-100; } for (; y<=bottom+1 && ydataReg); for (x=(VPP_Word) (limitData.xActiveMax-1); x>right; x--) if (linebuf[x-snapData.xOffset] >= THRESHOLD) right = x; if (y > bottom) { x = (VPP_Word) (limitData.xActiveMax*3/4); if (x < snapData.xOffset) x = snapData.xOffset; for (; x= THRESHOLD) { bottom = y; break; } } /* Increment linecounter */ // *c->ctrlStatus = CSR_NEWLINE; // *c->ctrlStatus = 0; write_csr(CSR_NEWLINE); write_csr(0); } left++; /* Remove those weak lines to the left and right */ right--; cropData->xActive = (VPP_Word) (right-left+1); cropData->xOffset = left; cropData->yActive = (VPP_Word) (bottom-top+1); cropData->yOffset = top; if (!cropData->interlaced) { cropData->yActive /= (VPP_Word) (2); cropData->yOffset /= (VPP_Word) (2); } #ifdef VPP_NO_STRETCH_IMAGE if (cropData->xPixels > cropData->xActive) cropData->xPixels = cropData->xActive; if (cropData->yPixels > cropData->yActive) cropData->yPixels = cropData->yActive; #endif /* VPP_STRETCH_IMAGE */ return VPP_success; } /****************************************************************************** ** Function name : convertCbYCrYToBGR24 ** Description : This function can be used to post-process an image ** from CbYCrY format to BGR24 format one line at a time. ** Parameters : pBGR24 = destination line buffer ** pCbYCrY = source line buffer ** length = length of line ** Return value : Errno = success / notInitialized / badPointer ******************************************************************************/ #ifndef VPP_NO_CbYCrY VPP_Errno EXPORT VPP_convertCbYCrYToBGR24(void VPP_far* pBGR24, void VPP_far* pCbYCrY, VPP_Word length) { VPP_Byte VPP_far* d = (VPP_Byte VPP_far*)pBGR24; VPP_Byte VPP_far* buf = (VPP_Byte VPP_far*)pCbYCrY; int x0, x1, x2, Yt; VPP_Byte odd; if (c == 0) RETURN_ERROR(VPP_notInitialized); if (pBGR24 == 0 || pCbYCrY == 0) RETURN_ERROR(VPP_badPointer); odd = (VPP_Byte)(length&1); if (odd) length--; while (length>0) { x0 = buf[0]; x2 = buf[2]; x1 = Gb[x2]+Gc[x0]; x2 = Rb[x2]; x0 = Bb[x0]; Yt = K[buf[1]]; d[0] = Cpr[Yt+x0]; d[1] = Cpr[Yt+x1]; d[2] = Cpr[Yt+x2]; Yt = K[buf[3]]; d[3] = Cpr[Yt+x0]; d[4] = Cpr[Yt+x1]; d[5] = Cpr[Yt+x2]; d += 6; buf += 4; length -= 2; } if (odd) { x0 = buf[0]; x2 = buf[-2]; Yt = K[buf[1]]; d[0] = Cpr[Yt+Bb[x0]]; d[1] = Cpr[Yt+Gc[x0]+Gb[x2]]; d[2] = Cpr[Yt+Rb[x2]]; } return VPP_success; } #endif /* VPP_NO_CbYCrY */ #ifndef VPP_NO_LOW_LEVEL /****************************************************************************** ** Function name : setControlStatus ** Description : Set Control-Status register (low-level interface) ** Parameters : value = value to set ** Return value : Errno = success / notInitialized ******************************************************************************/ VPP_Errno EXPORT VPP_setControlStatus(VPP_Byte value) { currentFunction = "VPP_setControlStatus"; if (c == 0) RETURN_ERROR(VPP_notInitialized); // *c->ctrlStatus = value; write_csr(value); return VPP_success; } /****************************************************************************** ** Function name : getControlStatus ** Description : Get Control-Status register (low-level interface) ** Parameters : value = pointer to return value ** Return value : Errno = success / notInitialized / badPointer ******************************************************************************/ VPP_Errno EXPORT VPP_getControlStatus(VPP_Byte VPP_far* value) { currentFunction = "VPP_getControlStatus"; if (c == 0) RETURN_ERROR(VPP_notInitialized); if (value == 0) RETURN_ERROR(VPP_badPointer); // *value = *c->ctrlStatus; *value = read_csr(); return VPP_success; } /****************************************************************************** ** Function name : getData ** Description : Get Data register (low-level interface) ** Parameters : value = pointer to return value ** Return value : Errno = success / notInitialized / badPointer ******************************************************************************/ VPP_Errno EXPORT VPP_getData(VPP_Word VPP_far* value) { currentFunction = "VPP_getData"; if (c == 0) RETURN_ERROR(VPP_notInitialized); if (value == 0) RETURN_ERROR(VPP_badPointer); *value = *(VPP_Word VPP_far*)c->dataReg; return VPP_success; } /****************************************************************************** ** Function name : setDigitizerRegister ** Description : Set digitizer register (low-level interface) ** Parameters : reg = Digitizer register number ** value = Value to set ** Return value : Errno = success / notInitialized / lostContact ******************************************************************************/ VPP_Errno EXPORT VPP_setDigitizerRegister(VPP_Byte reg, VPP_Byte value) { currentFunction = "VPP_setDigitizerRegister"; if (c == 0) RETURN_ERROR(VPP_notInitialized); WRITEI2C(reg,&value,1); return VPP_success; } /****************************************************************************** ** Function name : getDigitizerRegister ** Description : Set digitizer register (low-level interface) ** Parameters : reg = Digitizer register number ** value = Pointer to return value ** Return value : Errno = success / notInitialized / badPointer ** / lostContact ******************************************************************************/ VPP_Errno EXPORT VPP_getDigitizerRegister(VPP_Byte reg, VPP_Byte VPP_far* value) { VPP_Byte val; currentFunction = "VPP_getDigitizerRegister"; if (c == 0) RETURN_ERROR(VPP_notInitialized); if (value == 0) RETURN_ERROR(VPP_badPointer); READI2C(reg,&val,1); *value = val; return VPP_success; } /****************************************************************************** ** Function name : setDigitizerRegisters ** Description : Set all digitizer registers (low-level interface) ** Parameters : regs = Register struct (register number) ** STATUS 0x00 ** IFORM 0x01 ** TDEC 0x02 ** CROP 0x03 ** VDELAY_LO 0x04 ** VACTIVE_LO 0x05 ** HDELAY_LO 0x06 ** HACTIVE_LO 0x07 ** HSCALE_HI 0x08 ** HSCALE_LO 0x09 ** BRIGHT 0x0A ** CONTROL 0x0B ** CONTRAST_LO 0x0C ** SAT_U_LO 0x0D ** SAT_V_LO 0x0E ** HUE 0x0F ** OFORM 0x12 ** VSCALE_HI 0x13 ** VSCALE_LO 0x14 ** VPOLE 0x16 ** IDCODE 0x17 ** ADELAY 0x18 ** BDELAY 0x19 ** ADC 0x1A ** Return value : Errno = success / notInitialized / badPointer ** / lostContact ******************************************************************************/ VPP_Errno EXPORT VPP_setDigitizerRegisters(const VPP_DigitizerRegisters VPP_far* regs) { VPP_Byte buf[16]; currentFunction = "VPP_setDigitizerRegisters"; if (c == 0) RETURN_ERROR(VPP_notInitialized); if (regs == 0) RETURN_ERROR(VPP_badPointer); buf[0] = regs->STATUS; buf[1] = regs->IFORM; buf[2] = regs->TDEC; buf[3] = regs->CROP; buf[4] = regs->VDELAY_LO; buf[5] = regs->VACTIVE_LO; buf[6] = regs->HDELAY_LO; buf[7] = regs->HACTIVE_LO; buf[8] = regs->HSCALE_HI; buf[9] = regs->HSCALE_LO; buf[10] = regs->BRIGHT; buf[11] = regs->CONTROL; buf[12] = regs->CONTRAST_LO; buf[13] = regs->SAT_U_LO; buf[14] = regs->SAT_V_LO; buf[15] = regs->HUE; WRITEI2C(DG_STATUS,buf,16); buf[0] = regs->OFORM; buf[1] = regs->VSCALE_HI; buf[2] = regs->VSCALE_LO; WRITEI2C(DG_OFORM,buf,3); buf[0] = regs->VPOLE; WRITEI2C(DG_VPOLE,buf,1); buf[0] = regs->ADELAY; buf[1] = regs->BDELAY; buf[2] = regs->ADC; WRITEI2C(DG_ADELAY,buf,3); return VPP_success; } /****************************************************************************** ** Function name : getDigitizerRegisters ** Description : Get all digitizer registers (low-level interface) ** Parameters : regs = Register struct (see setDigitizerRegisters) ** Return value : Errno = success / notInitialized / badPointer ** / lostContact ******************************************************************************/ VPP_Errno EXPORT VPP_getDigitizerRegisters(VPP_DigitizerRegisters VPP_far* regs) { VPP_Byte buf[0x1B]; currentFunction = "VPP_getDigitizerRegisters"; if (c == 0) RETURN_ERROR(VPP_notInitialized); if (regs == 0) RETURN_ERROR(VPP_badPointer); READI2C(DG_STATUS,buf,0x1B); regs->STATUS = buf[0x00]; regs->IFORM = buf[0x01]; regs->TDEC = buf[0x02]; regs->CROP = buf[0x03]; regs->VDELAY_LO = buf[0x04]; regs->VACTIVE_LO = buf[0x05]; regs->HDELAY_LO = buf[0x06]; regs->HACTIVE_LO = buf[0x07]; regs->HSCALE_HI = buf[0x08]; regs->HSCALE_LO = buf[0x09]; regs->BRIGHT = buf[0x0A]; regs->CONTROL = buf[0x0B]; regs->CONTRAST_LO = buf[0x0C]; regs->SAT_U_LO = buf[0x0D]; regs->SAT_V_LO = buf[0x0E]; regs->HUE = buf[0x0F]; regs->OFORM = buf[0x12]; regs->VSCALE_HI = buf[0x13]; regs->VSCALE_LO = buf[0x14]; regs->VPOLE = buf[0x16]; regs->IDCODE = buf[0x17]; regs->ADELAY = buf[0x18]; regs->BDELAY = buf[0x19]; regs->ADC = buf[0x1A]; return VPP_success; } /****************************************************************************** ** Function name : windowAddress ** Description : Return the memory base address of the VideoPort ** Parameters : window = pointer to return value ** Return value : Errno = success / notInitialized / badPointer ******************************************************************************/ VPP_Errno EXPORT VPP_windowAddress(void VPP_far** window) { currentFunction = "VPP_ioWindowAddress"; if (c == 0) RETURN_ERROR(VPP_notInitialized); if (window == 0) RETURN_ERROR(VPP_badPointer); *window = (void VPP_far*)c->ctrlStatus; return VPP_success; } #endif /* VPP_NO_LOW_LEVEL */ /****************************************************************************** ** Local functions ** ******************************************************************************/ /****************************************************************************** ** Function name : detectVideoPort ** Description : Checks for presence of VideoPort PCMCIA or ISA ** Parameters : none ** Return value : 0 if no VideoPort found, otherwise IO-address of ** VideoPort ** 0xFFFE = VideoPort PCMCIA driver not installed ** 0xFFFF = Old VideoPort detected ******************************************************************************/ #ifdef __WIN32__ #define MS800_FLAG 1 #define MS801_FLAG 2 static VPP_Byte VPP_far * volatile detectVideoPort(VPP_Bool *powerWasOff) { DWORD inBuf[1],outBuf[4]; DWORD outSize; #ifdef __NT__ // Windows NT /* Create a handle to MS80x.SYS */ hMS80x = CreateFile("\\\\.\\MS80x$", GENERIC_READ|GENERIC_WRITE,FILE_SHARE_READ|FILE_SHARE_WRITE,NULL,OPEN_ALWAYS,FILE_ATTRIBUTE_NORMAL,NULL); #elif defined (__WIN32__) //Windows 95 /* Create a handle to MS80x VxD */ hMS80x = CreateFile("\\\\.\\MS80x.VXD", 0,0,0,OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL,0); #endif if ( hMS80x == INVALID_HANDLE_VALUE ) return (VPP_Byte VPP_far * volatile)0xFFFE; /* VideoPort PCMCIA driver not installed */ else { #ifdef GFDEBUG printf("\nhandle for driver created"); #endif outSize = 0; if (!DeviceIoControl(hMS80x, MS80x_DETECT_VIDEO_PORT /* Detect presence of VideoPorts*/, (LPVOID)NULL, 0, (LPVOID)outBuf, 1*sizeof(DWORD), &outSize, NULL)) /* || outSize != 1*sizeof(DWORD)) */ return (VPP_Byte VPP_far * volatile)0xFFFE; /* VideoPort PCMCIA driver not installed */ #ifdef GFDEBUG printf("\ndriver installed"); #endif if ((outBuf[0] & MS801_FLAG)==0 && (outBuf[0] & MS800_FLAG)!=0) return (VPP_Byte VPP_far * volatile)0xFFFF; /* Old VideoPort detected */ else if ((outBuf[0] & MS801_FLAG)==0) return 0; /* No VideoPort found */ #ifdef GFDEBUG printf("\nVideoPort found"); #endif inBuf[0] = MS801_FLAG; outSize = 0; if (!DeviceIoControl(hMS80x, MS80x_REQ_VIDEO_PORT /* Request MS801/MS802 VideoPort */, (LPVOID)inBuf, 1*sizeof(DWORD), (LPVOID)outBuf, 3*sizeof(DWORD), &outSize, NULL)) /* || outSize != 3*sizeof(DWORD)) */ return 0; /* No VideoPort found */ tmp_cardType = (VPP_Word) ((outBuf[1] & 2) ? 1 : 0); *powerWasOff = (VPP_Bool) ((outBuf[1] & 1) ? VPP_true : VPP_false); if (*powerWasOff) Sleep(2000); /* Power has been off => Wait until PAL/NTSC detected */ tmp_hCard = (HANDLE)outBuf[2]; return (VPP_Byte VPP_far * volatile)outBuf[0]; } } #else /* __WIN32__ */ static VPP_Word detectVideoPort(VPP_Bool *powerWasOff) { static union _REGS regs; #ifdef __WATCOMC__ regs.w.ax = MAGIC_AX; regs.w.bx = MAGIC_BX; regs.w.cx = 0; /* Test for driver installed */ INTR = INTR1; int386(INTR,®s,®s); if ((regs.w.ax != 0) || ((regs.w.bx != MAGIC_AX) && (regs.w.bx != MAGIC_AX^0xFFFF))) { /* No driver found on INTR1, try INTR2 */ regs.w.ax = MAGIC_AX; regs.w.bx = MAGIC_BX; regs.w.cx = 0; /* Test for driver installed */ INTR = INTR2; int386(INTR,®s,®s); } if ((regs.w.ax == 0) && (regs.w.bx == MAGIC_AX)) return 0xFFFF; /* Old VideoPort detected */ else if ((regs.w.ax == 0) && (regs.w.bx == MAGIC_AX^0xFFFF)) { regs.w.ax = MAGIC_AX; regs.w.bx = MAGIC_BX; regs.w.cx = 1; /* Request VideoPort */ int386(INTR,®s,®s); *powerWasOff = regs.w.bx; if (regs.w.bx) /* Power has been off => Wait until PAL/NTSC detected */ delay(2000); tmp_cardType = (VPP_Word)regs.w.cx; return (VPP_Word)regs.w.ax; } #else regs.x.ax = MAGIC_AX; regs.x.bx = MAGIC_BX; regs.x.cx = 0; /* Test for driver installed */ INTR = INTR1; _int86(INTR,®s,®s); if ((regs.x.ax != 0) || ((regs.x.bx != MAGIC_AX) && (regs.x.bx != ~MAGIC_AX))) { /* No driver found on INTR1, try INTR2 */ regs.x.ax = MAGIC_AX; regs.x.bx = MAGIC_BX; regs.x.cx = 0; /* Test for driver installed */ INTR = INTR2; _int86(INTR,®s,®s); } if ((regs.x.ax == 0) && (regs.x.bx == MAGIC_AX)) return 0xFFFF; /* Old VideoPort detected */ else if ((regs.x.ax == 0) && (regs.x.bx == ~MAGIC_AX)) { regs.x.ax = MAGIC_AX; regs.x.bx = MAGIC_BX; regs.x.cx = 1; /* Request VideoPort */ _int86(INTR,®s,®s); *powerWasOff = regs.x.bx; if (regs.x.bx) /* Power has been off => Wait until PAL/NTSC detected */ #ifdef _Windows { DWORD start = GetTickCount(); while (GetTickCount() - start < 2000) ; } #else delay(2000); /* NB! Non-standard function */ #endif tmp_cardType = (VPP_Word)regs.x.cx; return (VPP_Word)regs.x.ax; } #endif /* __WATCOMC__ */ return 0xFFFE; /* VideoPort PCMCIA driver not installed */ } #endif /* __WIN32__ */ /****************************************************************************** ** Function name : closeVideoPort ** Description : Turns power off on PCMCIA VideoPort ** Parameters : none ** Return value : none ******************************************************************************/ #ifdef __WIN32__ static void closeVideoPort(VPP_Bool powerOffOnExit) { DWORD inBuf[2],outBuf[1]; DWORD outSize; if (hMS80x != 0) { inBuf[0] = (DWORD)c->hCard; inBuf[1] = powerOffOnExit ? 0 : 1; outSize = 0; DeviceIoControl(hMS80x, MS80x_REL_VIDEO_PORT /* Release VideoPort */, (LPVOID)inBuf, 2*sizeof(DWORD), (LPVOID)outBuf, 1*sizeof(DWORD), &outSize, NULL); if (numCardsInitialized == 0) CloseHandle(hMS80x); } } #else static void closeVideoPort(void) { union _REGS regs; #ifdef __WATCOMC__ regs.w.ax = MAGIC_AX; regs.w.bx = MAGIC_BX; regs.w.cx = 2; int386(INTR,®s,®s); #else regs.x.ax = MAGIC_AX; regs.x.bx = MAGIC_BX; regs.x.cx = 2; _int86(INTR,®s,®s); #endif /* __WATCOMC__ */ } #endif __WIN32__ /****************************************************************************** ** Function name : getLimits ** Description : Gets the area limits for the given video standard and ** the current type of VideoPort. ** Parameters : videoStandard = Video standard ** limitData = Output struct ** Return value : none ******************************************************************************/ static void fillLimits(VPP_VideoStandard videoStandard, VPP_LimitData VPP_far* limitData) { limitData->xActiveMax = (VPP_Word) ((videoStandard == VPP_PAL) ? 950 : 780); limitData->yActiveMax = (VPP_Word) ((videoStandard == VPP_PAL) ? 610 : 510); #ifndef VPP_NO_STRETCH_IMAGE limitData->xPixelsMax = (VPP_Word) 3200; limitData->yPixelsMax = (VPP_Word) 2400; #else /* VPP_STRETCH_IMAGE */ limitData->xPixelsMax = (VPP_Word) ((c->cardType == 0) ? limitData->xActiveMax : 510); limitData->yPixelsMax = (VPP_Word) ((c->cardType == 0) ? limitData->yActiveMax : 510); #endif /* VPP_STRETCH_IMAGE */ limitData->xActiveRatio = 14; limitData->yActiveRatio = 14; limitData->xPixelsRatio = 1; limitData->yPixelsRatio = 1; } #define K1 1.164f #define R2 1.596f #define K2 18.624f #define G2 0.813f #define G3 0.391f #define B2 2.018f /****************************************************************************** ** Function name : fillLookupTables ** Description : Fills global lookuo-tables with values for YCrCb to ** RGB conversion ** Parameters : none ** Return value : none ** Note : ** ** The formulas used are: ** R= K1*Y + R2*Cr - K2 ** G= K1*Y + G2*Cr + G3*Cb - K2 ** B= K1*Y + B2*Cb - K2 ** ** The formulas are implemented in lookuptables as follows: ** R=Cpr[ K[Y] + Rb[Cr] ] ** G=Cpr[ K[Y] + Gb[Cr] + Gc[Cb] ] ** B=Cpr[ K[Y] + Bb[Cb] ] ** ** Cpr converts from int to BYTE, setting negative values to 0 and values ** greater than 255 to 255. Also does gamma-correction. ** ******************************************************************************/ void fillLookupTables(float gamma) { VPP_Int i; VPP_Byte gam; for (i=0; i<256; i++) { K [i]=(VPP_Int)((float)i*K1-K2)+280; Rb[i]=(VPP_Int)(((float)i-128.0)*R2); Gb[i]=(VPP_Int)((128.0-(float)i)*G2); Bb[i]=(VPP_Int)(((float)i-128.0)*B2); Gc[i]=(VPP_Int)((128.0-(float)i)*G3); gam = (VPP_Byte) ((gamma==1.0f) ? (VPP_Byte)i : ((i==0) ? 0 : (VPP_Byte)(255*pow(i/255.0,1.0/gamma)+0.5))); Cpr[i+280] = gam; #ifndef VPP_NO_RGB15 /* 0RRR RRGG GGGB BBBB */ CprR15[i+280] = (VPP_Word) (((VPP_Word)(gam&0xF8U))<<7); CprG15[i+280] = (VPP_Word) (((VPP_Word)(gam&0xF8U))<<2); CprB15[i+280] = (VPP_Word) (((VPP_Word)(gam&0xF8U))>>3); #endif #ifndef VPP_NO_RGB16 /* RRRR RGGG GGGB BBBB */ CprR16[i+280] = (VPP_Word) (((VPP_Word)(gam&0xF8U))<<8); CprG16[i+280] = (VPP_Word) (((VPP_Word)(gam&0xFCU))<<3); CprB16[i+280] = (VPP_Word) (((VPP_Word)(gam&0xF8U))>>3); #endif #ifndef VPP_NO_RGB8 /* RRRG GGBB */ CprR8[i+280] = (VPP_Byte) (gam&0xE0U); CprG8[i+280] = (VPP_Byte) ((gam&0xE0U)>>3); CprB8[i+280] = (VPP_Byte) ((gam&0xC0U)>>6); #endif } for (i=0; i<280; i++) { Cpr[i] = 0; Cpr[i+280+256] = 255; #ifndef VPP_NO_RGB15 /* 0RRR RRGG GGGB BBBB */ CprR15[i] = 0; CprG15[i] = 0; CprB15[i] = 0; CprR15[i+280+256] = (0xF8U)<<7; CprG15[i+280+256] = (0xF8U)<<2; CprB15[i+280+256] = (0xF8U)>>3; #endif #ifndef VPP_NO_RGB16 /* RRRR RGGG GGGB BBBB */ CprR16[i] = 0; CprG16[i] = 0; CprB16[i] = 0; CprR16[i+280+256] = (0xF8U)<<8; CprG16[i+280+256] = (0xFCU)<<3; CprB16[i+280+256] = (0xF8U)>>3; #endif #ifndef VPP_NO_RGB8 /* RRRG GGBB */ CprR8[i] = 0; CprG8[i] = 0; CprB8[i] = 0; CprR8[i+280+256] = 0xE0U; CprG8[i+280+256] = 0x1CU; CprB8[i+280+256] = 0x03U; #endif } #ifndef VPP_NO_mono for (i=0; i<16; i++) { GamMono[i]=0; GamMono[i+256-16]=255; } for (i=16; i<256-16; i++) { GamMono[i]=Cpr[280 + (VPP_Int)((i-16)*255.0/223.0 + 0.5)]; } #endif } #if !defined(VPP_NO_RGB16) && defined(VPP_FAST_RGB16) void fillFastLookupTable() { int Y,Cr,Cb; int Yt,x0,x1,x2; for (Cb=0; Cb<(1<ctrlStatus & (CSR_16_BIT_MONO|CSR_FRAME_MODE)); cs = (VPP_Byte) (read_csr() & (CSR_16_BIT_MONO|CSR_FRAME_MODE)); timerCount = ((VPP_DWord)msec)*timerTicks[c->videoStd]; for (; timerCount > 0; timerCount--) { // *c->ctrlStatus = cs; write_csr(cs); t=500; // while (t>0 && (*c->ctrlStatus & CSR_I2C_TIMER)==0) while (t>0 && (read_csr() & CSR_I2C_TIMER)==0) t--; if (t==0) /* Timeout */ return; } } #ifndef VPP_NO_FLASH /****************************************************************************** ** Function name : ourFlashFunc ** Description : This function sets the two standard output pins on the ** video connector according to the whichFlash parameter. ** During integration of the odd field, pin 12 goes high ** for 1 millisecond, and during integration of the even ** field, both pin 12 and pin 13 goes high for 1 ** millisecond. ** Parameters : whichFlash = this parameter equals oddFieldFlash during ** integration of the odd field, and evenFieldFlash during ** integration of the even field. ** Return value : none ******************************************************************************/ static void VPP_far ourFlashFunc(VPP_FlashSelect whichFlash) { if ((c->flashSel & whichFlash) != 0) { *(c->ctrlStatus+2) = (VPP_Byte) (whichFlash == VPP_oddFieldFlash ? 1 : 3); msleep(1); *(c->ctrlStatus+2) = 0; } } #endif /****************************************************************************** ** Function name : readBytes ** Description : Reads bytes from VideoPort and stores it in a buffer ** Parameters : dst = Far pointer to buffer ** n = number of words to read ** Return value : none ******************************************************************************/ static void readBytes(void VPP_far* dst, unsigned num, void VPP_far* src) { #ifdef __NT__ NTreadBytes(dst, src, num); #elif defined(__WIN32__) register VPP_Byte VPP_far* d = (VPP_Byte VPP_far*)dst; register VPP_Byte VPP_far* volatile s = (VPP_Byte VPP_far*)src; register VPP_Word n = (VPP_Word) (num); if (n>0) do *d++ = *s; while (--n); #endif } #ifndef VPP_NO_STRETCH_IMAGE void stretchLineMono(VPP_Byte VPP_far* line, int inWidth, int outWidth) { int i,index; long inc,pos,offset; if (outWidth<=inWidth || inWidth<2) /* Just in case */ return; inc = (((long)(inWidth-1)<<16)-1)/(long)(outWidth-1); pos = inc*(outWidth-1); for (i=outWidth-1; i>=0; i--) { index = (int)(pos>>16); offset = pos&0xFFFF; line[i] = (VPP_Byte)(((0x10000L-offset)*line[index]+offset*line[index+1])>>16); pos -= inc; } } void stretchLineCbYCrY(VPP_Byte VPP_far* line, int inWidth, int outWidth) { int i,index; long inc,pos,offset; if (outWidth<=inWidth || inWidth<4) /* Just in case */ return; if (inWidth&1) /* Take care of odd lengths */ { line[inWidth*2] = line[inWidth*2-4]; line[inWidth*2+1] = line[inWidth*2-1]; inWidth++; } if (outWidth&1) outWidth++; inc = (((long)(inWidth-1)<<16)-1)/(long)(outWidth-1); pos = inc*(outWidth-1); for (i=((outWidth-1)<<1)+1; i>0; i-=2) { index = (int)((pos>>16)<<1); offset = pos&0xFFFF; line[i] = (VPP_Byte)(((0x10000L-offset)*line[index+1]+offset*line[index+3])>>16); pos -= inc; } inWidth /= 2; outWidth /= 2; inc = (((long)(inWidth-1)<<16)-1)/(long)(outWidth-1); pos = inc*(outWidth-1); for (i=(outWidth-1)<<2; i>=0; i-=4) { index = (int)((pos>>16)<<2); offset = pos&0xFFFF; line[i] = (VPP_Byte)(((0x10000L-offset)*line[index]+offset*line[index+4])>>16); line[i+2] = (VPP_Byte)(((0x10000L-offset)*line[index+2]+offset*line[index+6])>>16); pos -= inc; } } void interpolateLine(VPP_Byte VPP_far* dst, VPP_Byte VPP_far* src1, VPP_Byte VPP_far* src2, long offset, int width) { int i; for (i=0; i>16); } #endif /* VPP_STRETCH_IMAGE */ void gotoLine(int lineNo) { lineNo += c->yOff; if (c->actualLineNo != lineNo) { if (c->actualLineNo > lineNo) { c->actualLineNo = 0; /* Reset line and pixel counter */ // *c->ctrlStatus = CSR_HOME; // *c->ctrlStatus = 0; write_csr(CSR_HOME); write_csr(0); } while (c->actualLineNo < lineNo) { c->actualLineNo ++; /* Increment linecounter */ // *c->ctrlStatus = CSR_NEWLINE; // *c->ctrlStatus = 0; write_csr(CSR_NEWLINE); write_csr(0); } } } void readVirtualLineMono(VPP_Byte VPP_far* dst, int line) { gotoLine(line); if (c->monoSnap) readWords(dst,(c->actualSnapWidth+1)/2,c->dataReg); else readBytes(dst,c->actualSnapWidth,c->dataReg+1); #ifndef VPP_NO_STRETCH_IMAGE if (c->actualSnapWidth < (int)c->imageWidth) stretchLineMono(dst,c->actualSnapWidth,c->imageWidth); #endif /* VPP_STRETCH_IMAGE */ } void readVirtualWordsMono(VPP_Byte VPP_far* dst) { #ifndef VPP_NO_STRETCH_IMAGE if (c->actualSnapHeight < (int)c->imageHeight) { int line1,line2,tmp; long inc,pos,offset; VPP_Byte VPP_far *tmpp; if (c->actualSnapHeight < 2) /* Just in case */ return; inc = (((long)(c->actualSnapHeight-1)<<16)-1)/(long)(c->imageHeight-1); pos = inc*c->lineNo; offset = pos&0xFFFF; line1 = (int)(pos>>16); line2 = line1+1; if (c->linebuf1line == line2 || c->linebuf2line == line1) { tmp = c->linebuf1line, c->linebuf1line = c->linebuf2line, c->linebuf2line = tmp; tmpp = c->linebuf1, c->linebuf1 = c->linebuf2, c->linebuf2 = tmpp; } if (c->linebuf1line != line1) readVirtualLineMono(c->linebuf1,c->linebuf1line = line1); if (c->linebuf2line != line2) readVirtualLineMono(c->linebuf2,c->linebuf2line = line2); interpolateLine(dst,c->linebuf1,c->linebuf2,offset,c->imageWidth); } else #endif /* VPP_STRETCH_IMAGE */ readVirtualLineMono(dst,c->lineNo); } void readVirtualLine(VPP_Byte VPP_far* dst, int line) { gotoLine(line); readWords(dst,c->actualSnapWidth,c->dataReg); #ifndef VPP_NO_STRETCH_IMAGE if (c->actualSnapWidth < (int)c->imageWidth) stretchLineCbYCrY(dst,c->actualSnapWidth,c->imageWidth); #endif /* VPP_STRETCH_IMAGE */ } void readVirtualWords(VPP_Byte VPP_far* dst) { #ifndef VPP_NO_STRETCH_IMAGE if (c->actualSnapHeight < (int)c->imageHeight) { int line1,line2,tmp; long inc,pos,offset; VPP_Byte VPP_far *tmpp; if (c->actualSnapHeight < 2) /* Just in case */ return; if (c->lineNo == c->imageHeight-1) c->linebuf1[0] = 0; inc = (((long)(c->actualSnapHeight-1)<<16)-1)/(long)(c->imageHeight-1); pos = inc*c->lineNo; offset = pos&0xFFFF; line1 = (int)(pos>>16); line2 = line1+1; if (c->linebuf1line == line2 || c->linebuf2line == line1) { tmp = c->linebuf1line, c->linebuf1line = c->linebuf2line, c->linebuf2line = tmp; tmpp = c->linebuf1, c->linebuf1 = c->linebuf2, c->linebuf2 = tmpp; } if (c->linebuf1line != line1) readVirtualLine(c->linebuf1,c->linebuf1line = line1); if (c->linebuf2line != line2) readVirtualLine(c->linebuf2,c->linebuf2line = line2); interpolateLine(dst,c->linebuf1,c->linebuf2,offset,(c->imageWidth+1)*2); } else #endif /* VPP_STRETCH_IMAGE */ readVirtualLine(dst,c->lineNo); } /****************************************************************************** ** Function name : readLineXXXXX ** Description : Reads a line from VideoPort and stores it according to ** readout-mode. ** Parameters : dst = Far pointer to buffer ** off = number of pixels to skip before start reading ** len = number of pixels to read (regardless of skip) ** Return value : none ******************************************************************************/ #ifndef VPP_NO_CbYCrY static void readLineCbYCrY(void VPP_far* dst, unsigned off, unsigned len) { readVirtualWords(linebuf); if (c->xOddStart) off ++; memcpy(dst,linebuf+off*2,((len+1)&(~1))*2); } #endif /* VPP_NO_CbYCrY */ #ifndef VPP_NO_mono static void readLineMono8(void VPP_far* dst, unsigned off, unsigned len) { #ifdef VPP_FAST_MONO readVirtualWordsMono(linebuf); memcpy(dst,linebuf+off,len); #else VPP_Word i; VPP_Byte VPP_far* d = (VPP_Byte VPP_far*)dst; VPP_Byte *buf; readVirtualWordsMono(linebuf); buf = linebuf+off; for (i=0; ilineNo&3]; patternX = 8; readVirtualWordsMono(linebuf); buf = linebuf+off; odd = (VPP_Byte)(len&1); len /= 2; for (i=0; i>4)+(Y1&0xF0U)); buf += 2; } if (odd) { Y1 = Cpr[ 280+buf[0]+pattern ]; d[i] &= 0x0F; d[i] |= (VPP_Byte) ((Y1&0xF0)); } } #endif /* VPP_NO_mono4 */ #ifndef VPP_NO_YCrCb static void readLineYCrCb(void VPP_far* dst, unsigned off, unsigned len) { VPP_Byte Cr, Cb, odd; VPP_Byte VPP_far* d = (VPP_Byte VPP_far*)dst; VPP_Byte *buf; readVirtualWords(linebuf); buf = linebuf+off*2; odd = (VPP_Byte)((len&1)^(c->xOddStart)); if (odd) len--; if (c->xOddStart) { d[0] = buf[1]; d[1] = buf[0]; d[2] = buf[2]; d += 3; buf += 2; len--; } while (len>0) { d[0] = buf[1]; Cb = buf[0]; Cr = buf[2]; d[1] = Cr; d[2] = Cb; d[3] = buf[3]; d[4] = Cr; d[5] = Cb; d += 6; buf += 4; len -= 2; } if (odd) { d[0] = buf[1]; d[1] = buf[-2]; d[2] = buf[0]; } } #endif /* VPP_NO_YCrCb */ #ifndef VPP_NO_YCbCr static void readLineYCbCr(void VPP_far* dst, unsigned off, unsigned len) { VPP_Byte Cr, Cb, odd; VPP_Byte VPP_far* d = (VPP_Byte VPP_far*)dst; VPP_Byte *buf; readVirtualWords(linebuf); buf = linebuf+off*2; odd = (VPP_Byte)((len&1)^(c->xOddStart)); if (odd) len--; if (c->xOddStart) { d[0] = buf[1]; d[1] = buf[2]; d[2] = buf[0]; d += 3; buf += 2; len--; } while (len>0) { d[0] = buf[1]; Cb = buf[0]; Cr = buf[2]; d[1] = Cb; d[2] = Cr; d[3] = buf[3]; d[4] = Cb; d[5] = Cr; d += 6; buf += 4; len -= 2; } if (odd) { d[0] = buf[1]; d[1] = buf[0]; d[2] = buf[-2]; } } #endif /* VPP_NO_YCbCr */ #ifndef VPP_NO_BGR24 static void readLineBGR24(void VPP_far* dst, unsigned off, unsigned len) { VPP_Byte VPP_far* d = (VPP_Byte VPP_far*)dst; int x0, x1, x2, Yt; VPP_Byte odd; VPP_Byte *buf; readVirtualWords(linebuf); buf = linebuf+off*2; odd = (VPP_Byte)((len&1)^(c->xOddStart)); if (odd) len--; if (c->xOddStart) { x0 = buf[2]; x2 = buf[0]; Yt = K[buf[1]]; d[0] = Cpr[Yt+Bb[x0]]; d[1] = Cpr[Yt+Gc[x0]+Gb[x2]]; d[2] = Cpr[Yt+Rb[x2]]; d += 3; buf += 2; len--; } while (len>0) { x0 = buf[0]; x2 = buf[2]; x1 = Gb[x2]+Gc[x0]; x2 = Rb[x2]; x0 = Bb[x0]; Yt = K[buf[1]]; d[0] = Cpr[Yt+x0]; d[1] = Cpr[Yt+x1]; d[2] = Cpr[Yt+x2]; Yt = K[buf[3]]; d[3] = Cpr[Yt+x0]; d[4] = Cpr[Yt+x1]; d[5] = Cpr[Yt+x2]; d += 6; buf += 4; len -= 2; } if (odd) { x0 = buf[0]; x2 = buf[-2]; Yt = K[buf[1]]; d[0] = Cpr[Yt+Bb[x0]]; d[1] = Cpr[Yt+Gc[x0]+Gb[x2]]; d[2] = Cpr[Yt+Rb[x2]]; } } #endif /* VPP_NO_BGR24 */ #ifndef VPP_NO_RGB24 static void readLineRGB24(void VPP_far* dst, unsigned off, unsigned len) { VPP_Byte VPP_far* d = (VPP_Byte VPP_far*)dst; int x0, x1, x2, Yt; VPP_Byte *buf; VPP_Byte odd; readVirtualWords(linebuf); buf = linebuf+off*2; odd = (VPP_Byte)((len&1)^(c->xOddStart)); if (odd) len--; if (c->xOddStart) { x0 = buf[2]; x2 = buf[0]; Yt = K[buf[1]]; d[0] = Cpr[Yt+Rb[x2]]; d[1] = Cpr[Yt+Gc[x0]+Gb[x2]]; d[2] = Cpr[Yt+Bb[x0]]; d += 3; buf += 2; len--; } while (len>0) { x0 = buf[0]; x2 = buf[2]; x1 = Gb[x2]+Gc[x0]; x2 = Rb[x2]; x0 = Bb[x0]; Yt = K[buf[1]]; d[0] = Cpr[Yt+x2]; d[1] = Cpr[Yt+x1]; d[2] = Cpr[Yt+x0]; Yt = K[buf[3]]; d[3] = Cpr[Yt+x2]; d[4] = Cpr[Yt+x1]; d[5] = Cpr[Yt+x0]; d += 6; buf += 4; len -= 2; } if (odd) { x0 = buf[0]; x2 = buf[-2]; Yt = K[buf[1]]; d[0] = Cpr[Yt+Rb[x2]]; d[1] = Cpr[Yt+Gc[x0]+Gb[x2]]; d[2] = Cpr[Yt+Bb[x0]]; } } #endif /* VPP_NO_RGB24 */ #ifndef VPP_NO_RGB8 static void readLineRGB8(void VPP_far* dst, unsigned off, unsigned len) { VPP_Byte VPP_far* d = (VPP_Byte VPP_far*)dst; int yt, x0, x1, x2; VPP_Byte *buf; VPP_Byte odd; VPP_Byte pattern, patternX; static VPP_Byte pinit[4] = { 0,24,6,30 }; pattern = pinit[c->lineNo&3]; patternX = 16; readVirtualWords(linebuf); buf = linebuf+off*2; odd = (VPP_Byte)((len&1)^(c->xOddStart)); if (odd) len--; if (c->xOddStart) { yt = K[buf[1]]; x0 = buf[2]; x2 = buf[0]; d[0] = (VPP_Byte) (CprB8[yt+Bb[x0]+(pattern<<1)] + CprG8[yt+Gc[x0]+Gb[x2]+pattern] + CprR8[yt+Rb[x2]+pattern]); pattern ^= patternX; patternX ^= 4; d++; buf += 2; len--; } while (len>0) { x0 = buf[0]; x2 = buf[2]; x1 = Gb[x2]+Gc[x0]; x2 = Rb[x2]; x0 = Bb[x0]; yt = K[buf[1]]; d[0] = (VPP_Byte) (CprB8[yt+x0+(pattern<<1)] + CprG8[yt+x1+pattern] + CprR8[yt+x2+pattern]); pattern ^= patternX; patternX ^= 4; yt = K[buf[3]]; d[1] = (VPP_Byte) (CprB8[yt+x0+(pattern<<1)] + CprG8[yt+x1+pattern] + CprR8[yt+x2+pattern]); pattern ^= patternX; patternX ^= 4; d += 2; buf += 4; len -= 2; } if (odd) { yt = K[buf[1]]; x0 = buf[0]; x2 = buf[-2]; d[0] = (VPP_Byte) (CprB8[yt+Bb[x0]+(pattern<<1)] + CprG8[yt+Gc[x0]+Gb[x2]+pattern] + CprR8[yt+Rb[x2]+pattern]); } } #endif /* VPP_NO_RGB8 */ #ifndef VPP_NO_RGB15 static void readLineRGB15(void VPP_far* dst, unsigned off, unsigned len) { VPP_Word VPP_far* d = (VPP_Word VPP_far*)dst; int yt, x0, x1, x2; VPP_Byte *buf; VPP_Byte odd; readVirtualWords(linebuf); buf = linebuf+off*2; odd = (VPP_Byte)((len&1)^(c->xOddStart)); if (odd) len--; if (c->xOddStart) { yt = K[buf[1]]; x0 = buf[2]; x2 = buf[0]; d[0] = (VPP_Word) (CprB15[yt+Bb[x0]] + CprG15[yt+Gc[x0]+Gb[x2]] + CprR15[yt+Rb[x2]]); d++; buf += 2; len--; } while (len>0) { x0 = buf[0]; x2 = buf[2]; x1 = Gb[x2]+Gc[x0]; x2 = Rb[x2]; x0 = Bb[x0]; yt = K[buf[1]]; d[0] = (VPP_Word) (CprB15[yt+x0] + CprG15[yt+x1] + CprR15[yt+x2]); yt = K[buf[3]]; d[1] = (VPP_Word) (CprB15[yt+x0] + CprG15[yt+x1] + CprR15[yt+x2]); d += 2; buf += 4; len -= 2; } if (odd) { yt = K[buf[1]]; x0 = buf[0]; x2 = buf[-2]; d[0] = (VPP_Word) (CprB15[yt+Bb[x0]] + CprG15[yt+Gc[x0]+Gb[x2]] + CprR15[yt+Rb[x2]]); } } #endif /* VPP_NO_RGB15 */ #ifndef VPP_NO_RGB16 static void readLineRGB16(void VPP_far* dst, unsigned off, unsigned len) { #ifdef VPP_FAST_RGB16 VPP_Word VPP_far* d = (VPP_Word VPP_far*)dst; int a,b; VPP_Byte *buf; VPP_Byte odd; readVirtualWords(linebuf); buf = linebuf+off*2; odd = (VPP_Byte)((len&1)^(c->xOddStart)); if (odd) len--; if (c->xOddStart) { a = ((buf[0]>>(8-CrBITS))<>(8-CbBITS)); b = ((buf[1]>>(8-YBITS))<<(CrBITS+CbBITS))+a; b = Cpr16[b]; d[0] = b; d++; buf += 2; len--; } len /= 2; do { a = ((buf[2]>>(8-CrBITS))<>(8-CbBITS)); b = ((buf[1]>>(8-YBITS))<<(CrBITS+CbBITS))+a; a = ((buf[3]>>(8-YBITS))<<(CrBITS+CbBITS))+a; b = Cpr16[b]; a = Cpr16[a]; d[0] = b; d[1] = a; buf += 4; d += 2; } while (--len); if (odd) { a = ((buf[-2]>>(8-CrBITS))<>(8-CbBITS)); b = ((buf[1]>>(8-YBITS))<<(CrBITS+CbBITS))+a; b = Cpr16[b]; d[0] = b; } #else /* VPP_FAST_RGB16 */ VPP_Word VPP_far* d = (VPP_Word VPP_far*)dst; int yt, x0, x1, x2; VPP_Byte *buf; VPP_Byte odd; readVirtualWords(linebuf); buf = linebuf+off*2; odd = (VPP_Byte)((len&1)^(c->xOddStart)); if (odd) len--; if (c->xOddStart) { yt = K[buf[1]]; x0 = buf[2]; x2 = buf[0]; d[0] = (VPP_Word) (CprB16[yt+Bb[x0]] + CprG16[yt+Gc[x0]+Gb[x2]] + CprR16[yt+Rb[x2]]); d++; buf += 2; len--; } while (len>0) { x0 = buf[0]; x2 = buf[2]; x1 = Gb[x2]+Gc[x0]; x2 = Rb[x2]; x0 = Bb[x0]; yt = K[buf[1]]; d[0] = (VPP_Word) (CprB16[yt+x0] + CprG16[yt+x1] + CprR16[yt+x2]); yt = K[buf[3]]; d[1] = (VPP_Word) (CprB16[yt+x0] + CprG16[yt+x1] + CprR16[yt+x2]); d += 2; buf += 4; len -= 2; } if (odd) { yt = K[buf[1]]; x0 = buf[0]; x2 = buf[-2]; d[0] = (VPP_Word) (CprB16[yt+Bb[x0]] + CprG16[yt+Gc[x0]+Gb[x2]] + CprR16[yt+Rb[x2]]); } #endif /* VPP_FAST_RGB16 */ } #endif /* VPP_NO_RGB16 */ #ifndef VPP_NO_BGR032 static void readLineBGR032(void VPP_far* dst, unsigned off, unsigned len) { VPP_Byte VPP_far* d = (VPP_Byte VPP_far*)dst; int x0, x1, x2, Yt; VPP_Byte odd; VPP_Byte *buf; readVirtualWords(linebuf); buf = linebuf+off*2; odd = (VPP_Byte)((len&1)^(c->xOddStart)); if (odd) len--; if (c->xOddStart) { x0 = buf[2]; x2 = buf[0]; Yt = K[buf[1]]; d[0] = Cpr[Yt+Bb[x0]]; d[1] = Cpr[Yt+Gc[x0]+Gb[x2]]; d[2] = Cpr[Yt+Rb[x2]]; d[3] = 0; d += 4; buf += 2; len--; } while (len>0) { x0 = buf[0]; x2 = buf[2]; x1 = Gb[x2]+Gc[x0]; x2 = Rb[x2]; x0 = Bb[x0]; Yt = K[buf[1]]; d[0] = Cpr[Yt+x0]; d[1] = Cpr[Yt+x1]; d[2] = Cpr[Yt+x2]; d[3] = 0; Yt = K[buf[3]]; d[4] = Cpr[Yt+x0]; d[5] = Cpr[Yt+x1]; d[6] = Cpr[Yt+x2]; d[7] = 0; d += 8; buf += 4; len -= 2; } if (odd) { x0 = buf[0]; x2 = buf[-2]; Yt = K[buf[1]]; d[0] = Cpr[Yt+Bb[x0]]; d[1] = Cpr[Yt+Gc[x0]+Gb[x2]]; d[2] = Cpr[Yt+Rb[x2]]; d[3] = 0; } } #endif /* VPP_NO_BGR032 */ /****************************************************************************** ** I2C routines ** ******************************************************************************/ #define I2C_data 2 #define I2C_clock 1 #define I2C_direction 4 #define I2C_timer 1 #define I2C_bits (I2C_data | I2C_clock | I2C_direction) #define I2C_read_address 0x89 #define I2C_write_address 0x88 static int timerI2C(void); static int startI2C(void); static int stopI2C(void); static int chipAddressI2C(int Dir); static int registerAddressI2C(int register_no); static int getDataI2C(VPP_Byte *data); static int putDataI2C(VPP_Byte data); static void ackI2C(void); static void nakI2C(void); /* Function for reading one or more contiguos registers in digitizer */ /* Returns: -1 for no contact with digitizer */ /* -2 for no contact with VideoPort CSR (not configured) */ /* number of bytes read if OK */ static int readI2C(VPP_Word register_no, VPP_Byte *data, int count) { int n,i; int status; n=0; do { n++; status = startI2C(); if (status != 0) continue; status = chipAddressI2C(0); if (status != 0) continue; status = registerAddressI2C(register_no); if (status != 0) continue; status = startI2C(); if (status != 0) continue; status = chipAddressI2C(1); if (status != 0) continue; for (i=0; i<(count-1); i++) { status = getDataI2C(data++); if (status != 0) break; ackI2C(); } if (status != 0) continue; status = getDataI2C(data++); if (status != 0) continue; nakI2C(); status = stopI2C(); } while (status != 0 && n<2); if (status != 0) return status; return count; } /* Function for writing one or more contiguos registers in digitizer */ /* Returns: -1 for no contact with digitizer */ /* -2 for no contact with VideoPort CSR (not configured) */ /* number of bytes written if OK */ static int writeI2C(VPP_Word register_no, VPP_Byte *data, int count) { int n,i; int status; n=0; do { n++; status = startI2C(); if (status != 0) continue; status = chipAddressI2C(0); if (status != 0) continue; status = registerAddressI2C(register_no); if (status != 0) continue; for (i=0; ictrlStatus & I2C_timer); } if (j == 500) return -2; else return 0; } static int startI2C(void) /* SDA ----\_____ */ { /* SCL -------\__ */ VPP_Byte I2C_mask; int status =0; I2C_mask = (VPP_Byte) (*c->ctrlStatus & ~I2C_bits & 0x3fU); /* Keep other bits in CSR unchanged */ *c->ctrlStatus = (VPP_Byte) ((I2C_mask | I2C_data | I2C_clock)); /* 011 */ status += timerI2C(); *c->ctrlStatus = (VPP_Byte) ((I2C_mask | I2C_clock)); /* 001 */ status += timerI2C(); *c->ctrlStatus = I2C_mask; /* 000 */ status += timerI2C(); return (status==0 ? 0 : -2); } static int stopI2C(void) /* SDA ______/--- */ { /* SCL ___/------ */ VPP_Byte I2C_mask; int status =0; I2C_mask = (VPP_Byte) (*c->ctrlStatus & ~I2C_bits & 0x3fU); /* Keep other bits in CSR unchanged */ *c->ctrlStatus = I2C_mask; /* 000 */ status += timerI2C(); *c->ctrlStatus = (VPP_Byte) ((I2C_mask | I2C_clock)); /* 001 */ status += timerI2C(); *c->ctrlStatus = (VPP_Byte) ((I2C_mask | I2C_data | I2C_clock)); /* 011 */ status += timerI2C(); return (status==0 ? 0 : -2); } static int chipAddressI2C(int Dir) { VPP_Byte address; int i; VPP_Byte mask =0x80; VPP_Byte I2C_mask; VPP_Byte acknowledge; int status =0; if (Dir == 0) address =I2C_write_address; else address =I2C_read_address; I2C_mask = (VPP_Byte) (*c->ctrlStatus & ~I2C_bits & 0x3f); /* Keep other bits in CSR unchanged */ for (i=0; i<8; i++) { status += timerI2C(); if ((address & mask) ==0) { *c->ctrlStatus = I2C_mask; /* SDA _______________ */ status += timerI2C(); /* SCL ___/------\____ */ *c->ctrlStatus = (VPP_Byte) ((I2C_mask | I2C_clock)); /* 000 */ status += timerI2C(); *c->ctrlStatus = I2C_mask; } else { *c->ctrlStatus = (VPP_Byte) ((I2C_mask | I2C_data)); /* SDA --------------- */ status += timerI2C(); /* SCL ___/------\____ */ *c->ctrlStatus = (VPP_Byte) ((I2C_mask | I2C_data | I2C_clock)); status += timerI2C(); *c->ctrlStatus = (VPP_Byte) ((I2C_mask | I2C_data)); } mask = (VPP_Byte) (mask>>1); } *c->ctrlStatus = (VPP_Byte) ((I2C_mask | I2C_data | I2C_direction)); /* pull data up */ *c->ctrlStatus = (VPP_Byte) ((I2C_mask | I2C_direction)); /* switch to input */ if (status != 0) return -2; else { status += timerI2C(); *c->ctrlStatus = (VPP_Byte) ((I2C_mask | I2C_direction | I2C_clock)); acknowledge = (VPP_Byte) (*c->ctrlStatus & I2C_data); status += timerI2C(); *c->ctrlStatus = (VPP_Byte) ((I2C_mask | I2C_direction)); status += timerI2C(); *c->ctrlStatus = I2C_mask; if (acknowledge != 0) return -1; else return (status==0 ? 0 : -2); } } static int registerAddressI2C(int register_no) { int i; VPP_Byte mask =0x80; VPP_Byte I2C_mask; VPP_Byte acknowledge; int status =0; I2C_mask = (VPP_Byte) (*c->ctrlStatus & ~I2C_bits & 0x3fU); /* Keep other bits in CSR unchanged */ for (i=0; i<8; i++) { status += timerI2C(); if ((register_no & mask) ==0) { *c->ctrlStatus = I2C_mask; /* SDA _______________ */ status += timerI2C(); /* SCL ___/------\____ */ *c->ctrlStatus = (VPP_Byte) ((I2C_mask | I2C_clock)); /* 000 */ status += timerI2C(); *c->ctrlStatus = I2C_mask; } else { *c->ctrlStatus = (VPP_Byte) ((I2C_mask | I2C_data)); /* SDA --------------- */ status += timerI2C(); /* SCL ___/------\____ */ *c->ctrlStatus = (VPP_Byte) ((I2C_mask | I2C_data | I2C_clock)); status += timerI2C(); *c->ctrlStatus = (VPP_Byte) ((I2C_mask | I2C_data)); } mask = (VPP_Byte) (mask>>1U); } *c->ctrlStatus = (VPP_Byte) ((I2C_mask | I2C_data | I2C_direction)); /* pull data up */ *c->ctrlStatus = (VPP_Byte) ((I2C_mask | I2C_direction)); /* switch to input */ if (status != 0) return -2; else { status += timerI2C(); *c->ctrlStatus = (VPP_Byte) ((I2C_mask | I2C_direction | I2C_clock)); acknowledge = (VPP_Byte) (*c->ctrlStatus & I2C_data); status += timerI2C(); *c->ctrlStatus = (VPP_Byte) ((I2C_mask | I2C_direction)); status += timerI2C(); *c->ctrlStatus = (VPP_Byte) ((I2C_mask | I2C_data |I2C_direction)); if (acknowledge != 0) return -1; else return (status==0 ? 0 : -2); } } static int putDataI2C(VPP_Byte data) { int i; VPP_Byte mask =0x80; VPP_Byte I2C_mask; VPP_Byte acknowledge; int status =0; I2C_mask = (VPP_Byte) (*c->ctrlStatus & ~I2C_bits & 0x3fU); /* Keep other bits in CSR unchanged */ for (i=0; i<8; i++) { status += timerI2C(); if ((data & mask) ==0) { *c->ctrlStatus = I2C_mask; /* SDA _______________ */ status += timerI2C(); /* SCL ___/------\____ */ *c->ctrlStatus = (VPP_Byte) ((I2C_mask | I2C_clock)); /* 000 */ status += timerI2C(); *c->ctrlStatus = I2C_mask; } else { *c->ctrlStatus = (VPP_Byte) ((I2C_mask | I2C_data)); /* SDA --------------- */ status += timerI2C(); /* SCL ___/------\____ */ *c->ctrlStatus = (VPP_Byte) ((I2C_mask | I2C_data | I2C_clock)); status += timerI2C(); *c->ctrlStatus = (VPP_Byte) ((I2C_mask | I2C_data)); } mask = (VPP_Byte) (mask>>1U); } *c->ctrlStatus = (VPP_Byte) ((I2C_mask | I2C_data | I2C_direction)); /* pull data up */ *c->ctrlStatus = (VPP_Byte) ((I2C_mask | I2C_direction)); /* switch to input */ if (status != 0) return -2; else { status += timerI2C(); *c->ctrlStatus = (VPP_Byte) ((I2C_mask | I2C_direction | I2C_clock)); acknowledge = (VPP_Byte) (*c->ctrlStatus & I2C_data); status += timerI2C(); *c->ctrlStatus = (VPP_Byte) ((I2C_mask | I2C_direction)); status += timerI2C(); *c->ctrlStatus = I2C_mask; if (acknowledge != 0) return -1; else return (status==0 ? 0 : -2); } } static int getDataI2C(VPP_Byte *data) { int i; VPP_Byte I2C_mask; VPP_Byte d, temp; int status; status = 0; d = 0; I2C_mask = (VPP_Byte) (*c->ctrlStatus & ~(I2C_bits) & 0x3fU); /* Keep other bits in CSR unchanged */ *c->ctrlStatus = (VPP_Byte) ((I2C_mask | I2C_direction)); status += timerI2C(); for (i=0; i<8; i++) { *c->ctrlStatus = (VPP_Byte) ((I2C_mask | I2C_clock | I2C_direction)); temp = (VPP_Byte) (*c->ctrlStatus & I2C_data); status += timerI2C(); d <<= 1; if (temp != 0) d |= 0x01; *c->ctrlStatus = (VPP_Byte) ((I2C_mask | I2C_direction)); status += timerI2C(); *c->ctrlStatus = (VPP_Byte) ((I2C_mask | I2C_direction)); status += timerI2C(); } *data = d; return (status==0 ? 0 : -2); } static void ackI2C(void) { VPP_Byte I2C_mask; I2C_mask = (VPP_Byte) (*c->ctrlStatus & ~(I2C_bits) & 0x3fU); /* Keep other bits in CSR unchanged */ *c->ctrlStatus = I2C_mask; timerI2C(); *c->ctrlStatus = (VPP_Byte) ((I2C_mask | I2C_clock)); timerI2C(); *c->ctrlStatus = I2C_mask; *c->ctrlStatus = (VPP_Byte) ((I2C_mask | I2C_direction)); } void nakI2C(void) { VPP_Byte I2C_mask; I2C_mask = (VPP_Byte) (*c->ctrlStatus & ~(I2C_bits) & 0x3fU); /* Keep other bits in CSR unchanged */ *c->ctrlStatus = (VPP_Byte) ((I2C_mask | I2C_data)); timerI2C(); *c->ctrlStatus = (VPP_Byte) ((I2C_mask | I2C_data | I2C_clock)); timerI2C(); *c->ctrlStatus = (VPP_Byte) ((I2C_mask | I2C_direction)); } #if defined(__WIN32__) #elif defined(__WATCOMC__) void *VPP__mapPhysToLin(unsigned short segAddr); #pragma aux VPP__mapPhysToLin = \ "mov AX,0002H", \ "int 31H", \ "mov BX,AX", \ "mov AX,0006H", \ "int 31H", \ "and EDX,0000FFFFH", \ "shl ECX,16", \ "add ECX,EDX", \ parm [BX] \ value [ECX] \ modify [AX BX ECX EDX]; static VPP_Byte VPP_far* getDosMemory(VPP_Word segment) { return (VPP_Byte VPP_far*)VPP__mapPhysToLin(segment); } static void freeDosMemory(VPP_Byte VPP_far *address) { address = address; /* Keep the compiler happy */ } #elif defined(_Windows) static VPP_Byte VPP_far* getDosMemory(VPP_Word segment) { UINT sel; int rc; void far *data; // Make a new selector with the datasegment selector as a // template. data = &linebuf; sel=AllocSelector(FP_SEG(data)); if(!sel) { MessageBox((HWND)NULL,"Could not allocate selector","GetDOSmemory",MB_OK); return 0; } // Set the new selector's base address. // This is a 32bit linear address. rc=SetSelectorBase(sel,((DWORD)segment)<<4); if(!rc) { MessageBox((HWND)NULL,"Could not set selectorbase","GetDOSmemory",MB_OK); return 0; } // Sel the selectorlimit. // The videoport uses a 4kb window. SetSelectorLimit(sel,8192); // Test the new selector for read/write access. if(IsBadReadPtr(MK_FP(sel,0),4096)) { MessageBox((HWND)NULL,"BadReadPointer","GetDOSmemory",MB_OK); return 0; } if(IsBadWritePtr(MK_FP(sel,0),4096)) { MessageBox((HWND)NULL,"BadWritePointer","GetDOSmemory",MB_OK); return 0; } // Return the selector as a far pointer (sel:off) 32bit return (MK_FP(sel,0)); } static void freeDosMemory(VPP_Byte VPP_far *address) { FreeSelector(FP_SEG(address)); } #endif #ifdef __DLL__ /****************************************************************************** ** DLL LibMain ** ******************************************************************************/ /****************************************************************************** ** Function name : LibMain ** Description : Main entry point for DLL ** Parameters : hInstance : instance handle of DLL ** wDataSeg : Value of data segment register ** cbHeapSize : size of local heap ** lpCmdLine : pointer to command line ** Return value : 1 = success ** 0 = failure ******************************************************************************/ int FAR PASCAL LibMain(HINSTANCE hInstance, WORD wDataSeg, WORD cbHeapSize, LPSTR lpCmdLine) { #ifdef __BORLANDC__ #pragma argsused #else hInstance = hInstance; /* Keep the compiler happy */ wDataSeg = wDataSeg; cbHeapSize = cbHeapSize; lpCmdLine = lpCmdLine; #endif c = 0; return 1; } /****************************************************************************** ** Function name : WEP ** Description : Windows Exit Procedure ** Parameters : nParameter = WEP_SYSTEMEXIT : Windows shutdown ** nParameter = WEP_FREE_DLL : DLL is unloaded ** Return value : 1 = success ******************************************************************************/ int FAR PASCAL WEP(int nParameter) { #ifdef __BORLANDC__ #pragma argsused #else nParameter = nParameter; /* Keep the compiler happy */ #endif VPP_closedown(VPP_true); return 1; } #endif /* __DLL__ */ // // Function: // Writes to Digitizer via MS80x.SYS // // Returns: -1 for no contact with digitizer // -2 for no contact with VideoPort CSR (not configured) // number of bytes written if OK // #ifdef __NT__ static int NTwriteI2C(VPP_Word register_no, VPP_Byte *data, int count) { int iRc = NO_ERROR; // DWORD i; ULONG lOutBufferSize; DWORD dBytesWritten; DWORD InputBuffer[3]; int InBufferSize; // VPP_Byte * pdata; // pdata = data; InputBuffer[0] = (DWORD)register_no; InputBuffer[1]= (DWORD)count; InputBuffer[2] = (DWORD)data; // for(i=0;i<(DWORD)count;i++) // InputBuffer[i+2]= *pdata++; InBufferSize = sizeof(InputBuffer); lOutBufferSize = sizeof(dBytesWritten); // Send Request to device. if(!DeviceIoControl(hMS80x, (DWORD)MS80x_WRITE_I2C_VIDEO_PORT, (LPVOID)InputBuffer, InBufferSize, (LPVOID)&dBytesWritten, lOutBufferSize, &lOutBufferSize, NULL)) iRc = -1; else { if(dBytesWritten != (DWORD)count) iRc = -2; else iRc = dBytesWritten; } return iRc; } // // Function: // Reads from Digitizer via MS80x.SYS // // Returns: -1 for no contact with digitizer // -2 for no contact with VideoPort CSR (not configured) // number of bytes read if OK // static int NTreadI2C(VPP_Word register_no, VPP_Byte *data, int count) { int iRc = NO_ERROR; ULONG lOutBufferSize; DWORD dBytesRead; // BYTE outBuf[64]; DWORD InputBuffer[3]; int InBufferSize; InputBuffer[0] = register_no; // register_no // InputBuffer[1] = (DWORD)data; // Buffer Address InputBuffer[1] = 0; InputBuffer[2] = count; // Count InBufferSize = sizeof(InputBuffer); lOutBufferSize = count; // Send Request to device. // if(!DeviceIoControl(hMS80x, (DWORD)MS80x_READ_I2C_VIDEO_PORT, // (LPVOID)InputBuffer, InBufferSize, // (LPVOID)&dBytesRead, lOutBufferSize, // &lOutBufferSize, NULL)) if(!DeviceIoControl(hMS80x, (DWORD)MS80x_READ_I2C_VIDEO_PORT, (LPVOID)InputBuffer, InBufferSize, (LPVOID)data, lOutBufferSize, &dBytesRead, NULL)) iRc = -1; else { if(count != count) iRc = -2; else iRc = count; } return count; } static void NTreadWords(void VPP_far* dst, void VPP_far* src, unsigned count) { int iRc = NO_ERROR; ULONG lOutBufferSize; // DWORD outBuf[1000]; DWORD InputBuffer[3]; int InBufferSize; // InputBuffer[0] = (DWORD)dst; //Pointer to dest // InputBuffer[1] = (DWORD)src; //Pointer to src // InputBuffer[2] = count; // Count InputBuffer[0] = count; InputBuffer[1]= (DWORD)src; InBufferSize = sizeof(InputBuffer); lOutBufferSize = count; // Send Request to device. // DeviceIoControl(hMS80x, (DWORD)MS80x_READ_WORDS_VIDEO_PORT, // (LPVOID)InputBuffer, InBufferSize, // (LPVOID)&outBuf, lOutBufferSize, // &lOutBufferSize, NULL); DeviceIoControl(hMS80x, (DWORD)MS80x_READ_WORDS_VIDEO_PORT, (LPVOID)InputBuffer, InBufferSize, (LPVOID)dst, lOutBufferSize, &lOutBufferSize, NULL); } static void NTreadBytes(void VPP_far* dst, void VPP_far* src, unsigned count) { int iRc = NO_ERROR; ULONG lOutBufferSize; // DWORD outBuf[1000]; DWORD InputBuffer[3]; int InBufferSize; // InputBuffer[0] = (DWORD)dst; //Pointer to dest // InputBuffer[1] = (DWORD)src; //Pointer to src // InputBuffer[2] = count; // Count InputBuffer[0]= count; InputBuffer[1]= (DWORD)src; InBufferSize = sizeof(InputBuffer); lOutBufferSize = count; // Send Request to device. // DeviceIoControl(hMS80x, (DWORD)MS80x_READ_BYTES_VIDEO_PORT, // (LPVOID)InputBuffer, InBufferSize, // (LPVOID)&outBuf, lOutBufferSize, // &lOutBufferSize, NULL); DeviceIoControl(hMS80x, (DWORD)MS80x_READ_BYTES_VIDEO_PORT, (LPVOID)InputBuffer, InBufferSize, (LPVOID)dst, lOutBufferSize, &lOutBufferSize, NULL); } #endif static VPP_Byte read_csr(void) { VPP_Byte y; #ifdef __NT__ VPP_Byte csr_data; READI2C(0x99,&csr_data,1); y = csr_data; #else y = *c->ctrlStatus; #endif return y; } static VPP_Byte write_csr(VPP_Byte csr_data) { #ifdef __NT__ WRITEI2C(0x99,&csr_data,1); #else *c->ctrlStatus = csr_data; #endif return 0; } ////////////////////////////////////////////////////////////////////////////