//===========================================================================//
// File:	PCSPAK.hh                                                           //
// Project: MUNGA           Brick: Platform-specific IO                      //
// Contents: PC serial packet interface class                                //
//---------------------------------------------------------------------------//
//   Date    Who  Modification                                               //
// --------  ---  -----------------------------------------------------------//
// 01/16/95  CPB  Initial coding.                                            //
//---------------------------------------------------------------------------//
// Copyright (C) 1995, Virtual World Entertainment, Inc. All rights reserved //
//                      PROPRIETARY and CONFIDENTIAL                         //
//===========================================================================//
#pragma once

//Win32 Serial support: ADB 01/15/07
#include <windows.h>
#include <assert.h>

#include "..\munga\style.h"
#include "L4SERIAL.H"

class PCSerialPacket;
class PCSerialPacketScanner;

//Win32 Serial support: ADB 02/13/07
#define DIE_ON_ERROR 1
#define DIE_ON_OVERFLOW 1
#define WATCH_IRQ 1
#define THE_WAY_IT_WAS 0
//===========================================================================
// Equates
//===========================================================================
#ifdef DIE_ON_ERROR
	#define DISABLE_AND_DIE(errorString) throw errorString
#else
	#define DISABLE_AND_DIE
#endif

//Win32 Serial support: ADB 02/10/07
//TX
#define TX_IDLE_STATE		0
#define TX_RESTART_STATE	1
#define TX_BODY_STATE		2
#define TX_WAIT_STATE		3
//RX
#define RX_IDLE_STATE		0
#define RX_ACTIVE_STATE		1

//
// Lower eight bits reserved for UART status
//
#define ERR_INIT			0x0100
#define TX_EARLY_ERR		0x0200
#define TX_ABANDON			0x0400
#define TX_RESTART			0x0800
#define TX_NAK				0x1000
#define RX_SEQ_ERR			0x2000
#define RX_BAD_CHECKSUM		0x4000
#define RX_COM_ERR			0x8000

#define TXMAXRESET			3
#define TXMAXERROR			3
#define TXMAXIDLE			4

#define MAX_COMMAND_CHAR	0xFB	//largest command code allowed
#define ACK_CHAR			0xFC
#define NAK_CHAR			0xFD
#define RESTART_CHAR		0xFE
#define IDLE_CHAR			0xFF

#define RX_ACK_BIT			0x0001
#define RX_NAK_BIT			0x0002

enum
{
	//Win32 Serial support: ADB 02/10/07
	//PCSPAKInitErrDPMI = -2,
	//PCSPAKInitErrAlloc = -1,
	PCSPAKWin32Err = -1,
	PCSPAKInitOk = 0
};

//Win32 Serial support: ADB 01/15/07
DWORD WINAPI RxThreadProc(LPVOID lpParameter);

//Win32 Serial support: ADB 02/13/07
#define COMBUFSIZE 2048

// This is for INTERNAL USE only (reflects structure in .ASM file)
struct PCSerPackBuf
{
	Word head, tail, tempHead, tempTail, count, tempIn, tempOut;
	//Win32 Serial support: ADB 02/13/07
	BYTE data[COMBUFSIZE];	// was 256 before 7-13-95 cpb
	// WARNING: make ABSOLUTELY SURE this matches pcspak.asm
};

class PCSerialPacket
{
	friend class PCSerialPacketScanner;
	friend DWORD WINAPI RxThreadProc(LPVOID lpParameter);

private:

	//Win32 Serial support: ADB 02/10/07
	//------------------------------------------------
	// COM_INIT macro
	// Initializes COMBUF structure
	//------------------------------------------------
	void COM_INIT(PCSerPackBuf* buffer);

	//Win32 Serial support: ADB 02/13/07
	//------------------------------------------------
	// COM_PUT_AL macro
	// 'Temporarily' puts character in AL into COMBUF
	//------------------------------------------------
	void COM_PUT_AL(PCSerPackBuf* buffer, BYTE al);

	//Win32 Serial support: ADB 02/13/07
	//------------------------------------------------
	// COM_RESTORE_IN macro
	// Discards characters 'temporarily' placed in COMBUF
	//------------------------------------------------
	void COM_RESTORE_IN(PCSerPackBuf* buffer);

	//Win32 Serial support: ADB 02/13/07
	//------------------------------------------------
	// COM_ACCEPT_IN macro
	// Accepts characters 'temporarily' placed in COMBUF
	//------------------------------------------------
	void COM_ACCEPT_IN(PCSerPackBuf* buffer);

	//Win32 Serial support: ADB 02/13/07
	//------------------------------------------------
	// COM_GET_AL macro
	// 'Temporarily' gets character into AL from COMBUF
	//------------------------------------------------
	int COM_GET_AL(PCSerPackBuf* buffer);

	//Win32 Serial support: ADB 02/13/07
	//------------------------------------------------
	// COM_RESTORE_OUT macro
	// Restores characters 'temporarily' removed from COMBUF
	//------------------------------------------------
	void COM_RESTORE_OUT(PCSerPackBuf* buffer);

	//Win32 Serial support: ADB 02/13/07
	//------------------------------------------------
	// COM_ACCEPT_OUT macro
	// Discards characters 'temporarily' removed from COMBUF
	//------------------------------------------------
	void COM_ACCEPT_OUT(PCSerPackBuf* buffer);

	//Win32 Serial support: ADB 02/13/07
	//------------------------------------------------
	// COM_EAT_PACKET macro
	// Discards entire buffer item from COMBUF
	//------------------------------------------------
	void COM_EAT_PACKET(PCSerPackBuf* buffer);

	//Win32 Serial support: ADB 02/13/07
	//------------------------------------------------
	// COM_SPACE_IN macro
	// Returns input bytes available in COMBUF
	//------------------------------------------------
	int COM_SPACE_IN(PCSerPackBuf* buffer);

	//Win32 Serial support: ADB 02/13/07
	//------------------------------------------------
	// COM_SPACE_OUT macro
	// Returns output bytes available in COMBUF
	//------------------------------------------------
	int COM_SPACE_OUT(PCSerPackBuf* buffer);

public:
	//Win32 Serial support: ADB 06/23/07
	PCSerialPacket();

	void ShutdownRxThread();

	~PCSerialPacket();

	//Win32 Serial support: ADB 01/15/07
	// Only call Initialize(...) ONCE during the lifetime of the object!
	int Initialize(WORD rate, WORD format, const char* port, BYTE* rxLengths, BYTE rxCount, BYTE* txLengths, BYTE txCount);

	//Win32 Serial support: ADB 01/15/07
	Logical TestInstance();

	//Win32 Serial support: ADB 02/10/07
	//-------------------------------------------------------------------------
	// PCSPAKReceive()
	// Returns packet if available
	//-------------------------------------------------------------------------
	// Enter:
	//		BYTE *destPtr	= pointer to 128-byte destination buffer
	//-------------------------------------------------------------------------
	// Returns:
	//		  int packetSize (or zero if no packet available)
	//-------------------------------------------------------------------------
	int ReceivePacket(BYTE *destPtr);

	//Win32 Serial Support
	//-------------------------------------------------------------------------
	// PCSPAKSend()
	// Transmits packet
	//-------------------------------------------------------------------------
	// Enter:
	//		BYTE *sp_src = pointer to (up to) 128-byte source buffer
	//-------------------------------------------------------------------------
	// Returns:
	//		void
	//-------------------------------------------------------------------------
	void SendPacket(BYTE *srcPtr);

	// error bits returned by PCSerialPacket::Errors()
	enum ErrorBits {
		overrunError=0x0002,
		parityError=0x0004,
		framingError=0x0008,
		breakDetect=0x0010,
		initError=0x0100,
		txEarlyReply=0x0200,
		txAbandonPacket=0x0400,
		txRestart=0x0800,
		txNakReply=0x1000,
		rxSequenceError=0x2000,
		rxChecksumError=0x4000,
		rxCommandError=0x8000
	};

	//Win32 Serial support: ADB 01/15/07
	int ReceiveQueueCount();

	//Win32 Serial support: ADB 01/15/07
	int TransmitQueueCount();

	//Win32 Serial Support: ADB 02/25/2007
	void SetDTR(Logical on);

	//Win32 Serial support: ADB 01/15/2007
	//-------------------------------------------------------------------------
	// PCSPAKActive()
	// Returns transmitter 'active' state (=0 when all transmission is done).
	//-------------------------------------------------------------------------
	// This function is now deprecated.
	int IsActive();

	//Win32 Serial support: ADB 01/15/07
	Word Errors();// returns error value, clears it

protected:
	//Win32 Serial support: ADB 01/15/07
	//Word	portBase;
	HANDLE	hComm;
	WORD	Error;			//error word

	//Win32 Serial support: ADB 02/10/07
	WORD	historyIndex;

	BYTE	enabled;
	BYTE	txHoldOff;
	BYTE	txReply;		//reply char
	BYTE	txState;		//status
	BYTE	txCount;		//maximum dialect transmit index
	BYTE	txResetCount;	//counts down each time a NAK is recieved until 0
	BYTE	txErrorCount;	//counts down each time the RIO errors out
	BYTE	txIdleCount;
	BYTE	txChecksum;
	BYTE	txMaximum;

	BYTE	rxFlags;		//receive flags (ack/nak)
	BYTE	rxState;
	BYTE	rxCount;		//maximum dialect receive index
	BYTE	rxChecksum;
	BYTE	rxMaximum;

	BYTE*	txLengthPtr;	//dialect transmit table pointer
	BYTE*	rxLengthPtr;	//dialect receive table pointer

	LWord intDataPtr;		//pointer to current working packet
//	LWord hackCount;		//WGR previously missing: seen in pcspak.asm

	PCSerPackBuf txBuf;
	PCSerPackBuf rxBuf;

   //Win32 Serial support: ADB 06/23/07
   HANDLE hMutex;
	HANDLE hRxThread;
	HANDLE hRxAbortEvent;
	BOOL bThreadAbort;
   OVERLAPPED overlapSend;
};