/**********************************************************************

    Motorola 6850 ACIA interface and emulation

    This function is a simple emulation of a pair of MC6850
    Asynchronous Communications Interface Adapters.

	This is a temporary driver, the plan is to combine this with
	mc6850.c in MESS to provide a full emulation.
	
	TODO:
	Add support for all functions.
	Make support generic, so that we can use this instead of all the
	individual 6850 implementations.
	
**********************************************************************/
#include "6850test.h"

//vid=1 norm=2
extern UINT8 m6850_irq_state; // referenced from machine/mpu4.c
void update_mpu68_interrupts(void); // referenced from machine/mpu4.c

#define LOG_SERIAL	  // log serial communication
#define  UART_LOG //enable UART data logging
#define LOG_CTRL	  // log serial communication

static int get_uart1_status(void);
static int get_uart2_status(void);
static int uart1_status;	  // MC6850 status
static int uart2_status;	  // MC6850 status

int uart1_dataflag;
int uart1_data;			// data
int uart2_dataflag;
int uart2_data;			// data

int uart1_triggered; // flag <>0, ACIA receive IRQ
int uart2_triggered; // flag <>0, ACIA receive IRQ

int aciadata;
int ctrl;
int vid_rx;

int vid_data_from_norm;
int norm_data_from_vid;
int vid_acia_triggered;
///////////////////////////////////////////////////////////////////////////
void send_to_uart1(int data)
{
  uart1_dataflag = 1;		// set flag, data from MPU4 board available
  norm_data_from_vid = 1;		// set flag, data from MPU4 board available
  uart1_data     = data;	// store data

  uart1_status |= 0x83; 	//TX full, RX empty, IRQ

  uart1_triggered = 1;		// set flag, acia IRQ triggered
  vid_acia_triggered = 1;		// set flag, acia IRQ triggered

  m6850_irq_state = 1;
  update_mpu68_interrupts();
  //cpunum_set_input_line(1, 2, HOLD_LINE );    // trigger IRQ

  #ifdef LOG_SERIAL
  logerror("s->uart1  %02X  (%c)\n",data, data );
  #endif
}

///////////////////////////////////////////////////////////////////////////

void send_to_uart2(int data)
{
  uart2_dataflag = 1;		// set flag, data from adder available
  vid_data_from_norm =1;
  uart2_data     = data;	// store data

  uart1_status |= 0x83; 	//TX full, RX empty, IRQ

  uart2_triggered = 1;		// set flag, acia IRQ triggered
  
  //m6850_irq_state = 1;
  //update_mpu68_interrupts();
  //cpunum_set_input_line(1, 2, HOLD_LINE );    // trigger IRQ

  #ifdef LOG_SERIAL
  logerror("s->uart2  %02X  (%c)\n",data, data );
  #endif
}

///////////////////////////////////////////////////////////////////////////

int read_from_uart1(void)
{
  int data = uart1_data;

  uart1_dataflag = 0;	  // clr flag,
  norm_data_from_vid = 0;	  // clr flag,
  #ifdef LOG_SERIAL
  logerror("r<-uart1:%02X(%c)\n",data, data );
  #endif

  return data;
}

///////////////////////////////////////////////////////////////////////////

int read_from_uart2(void)
{
  int data = uart2_data;

  uart2_dataflag = 0;	  // clr flag,
  vid_data_from_norm =0;
  #ifdef LOG_SERIAL
  logerror("r<-uart2:%02X  (%c)\n",data, data );
  #endif

  return data;
}

///////////////////////////////////////////////////////////////////////////

int get_uart1_status(void)
{

//  if ( uart2_dataflag ) uart1_status |= 0x01;  // receive  buffer full
//  if ( vid_data_from_norm ) uart1_status |= 0x01; // transmit buffer empty
//  if ( !uart1_dataflag ) uart1_status |= 0x02; // transmit buffer empty
//  if ( !norm_data_from_vid ) uart1_status |= 0x02; // transmit buffer empty

  #ifdef LOG_SERIAL
 logerror("Uart1 control status(%02X)\n",uart1_status);
  #endif

  return uart1_status;
}

///////////////////////////////////////////////////////////////////////////

int get_uart2_status(void)
{

//  if ( uart1_dataflag ) uart2_status |= 0x01;  // receive  buffer full
//  if ( norm_data_from_vid ) uart2_status |= 0x01;
//  if ( !uart2_dataflag ) uart2_status |= 0x02; // transmit buffer empty
//  if ( !vid_data_from_norm ) uart2_status |= 0x02; // transmit buffer empty
  #ifdef LOG_SERIAL
 logerror("Uart2 control status(%02X)\n",uart2_status);
  #endif

  return uart2_status;
}

///////////////////////////////////////////////////////////////////////////
// serial port ////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////

static READ8_HANDLER( uart1data_r )
{
	{
		if (uart1_status & 0x01)
		{
  			return read_from_uart2();
		}
	uart1_status &= 0x7e; // Clear the IRQ and the RDR Full
	}
}
///////////////////////////////////////////////////////////////////////////

static WRITE8_HANDLER( uart1ctrl_w )
{
      switch (data & 0x03)
      {
      case 0x00:
         logerror("#1 Uart clock: x1\n");
         break;
      case 0x01:
         logerror("#1 Uart clock: x16\n");
         break;
      case 0x02:
         logerror("#1 Uart clock: x32\n");
         break;
      case 0x03:
	     logerror("Resetting #1 Uart\n");
	     uart1_status = 0x02;
         break;
      }
      switch (data & 0x1c)
      {
      case 0x00:
         logerror("#1 Uart - Bits :7 Parity: Even Stop Bits: 2\n");
         break;
      case 0x04:
         logerror("#1 Uart - Bits :7 Parity: Odd Stop Bits: 2\n");
         break;
      case 0x08:
         logerror("#1 Uart - Bits :7 Parity: Even Stop Bits: 1\n");
         break;
      case 0x0c:
         logerror("#1 Uart - Bits :7 Parity: Odd Stop Bits: 1\n");
         break;
      case 0x10:
         logerror("#1 Uart - Bits :8 Parity: None Stop Bits: 2\n");
         break;
      case 0x14:
         logerror("#1 Uart - Bits :8 Parity: None Stop Bits: 1\n");
         break;
      case 0x18:
         logerror("#1 Uart - Bits :8 Parity: Even Stop Bits: 1\n");
         break;
      case 0x1c:
         logerror("#1 Uart - Bits :7 Parity: Odd Stop Bits: 1\n");
         break;
      }
      switch (data & 0x60)
      {
      case 0x00:
         logerror("#1 Uart - /RTS=0, TX IRQ=0\n");
         break;
      case 0x20:
         logerror("#1 Uart - /RTS=0, TX IRQ=1\n");
         //Add Transmit IRQ function here
         break;
      case 0x40:
         logerror("#1 Uart - /RTS=1, TX IRQ=0\n");
         break;
      case 0x60:
         logerror("#1 Uart - /RTS=0, TX break level, TX IRQ=0\n");
         break;
      }
      if (data & 0x80)
      {
         logerror("#1 Uart - RX IRQ=1\n");
         //Add Receive IRQ function here
      }
      else
      {
         logerror("#1 Uart - RX IRQ=0\n");
      }
#ifdef LOG_SERIAL
logerror("Uart1 control reg (%02X)\n",data);
#endif

}




///////////////////////////////////////////////////////////////////////////

static WRITE8_HANDLER( uart1data_w )
{
	uart1_status &= 0x7d;// Clear the IRQ and the TDR Empty
	#ifdef UART_LOG
	logerror("uart1:%c\n", data);
	#endif
}

///////////////////////////////////////////////////////////////////////////

static READ8_HANDLER( uart2data_r )
{
	{
		if (uart2_status & 0x01)
		{
  			return read_from_uart1();
		}
	uart2_status &= 0x7e; // Clear the IRQ and the RDR Full
	}
}

///////////////////////////////////////////////////////////////////////////

static WRITE8_HANDLER( uart2ctrl_w )
{
      switch (data & 0x03)
      {
      case 0x00:
         logerror("#2 Uart clock: x1\n");
         break;
      case 0x01:
         logerror("#2 Uart clock: x16\n");
         break;
      case 0x02:
         logerror("#2 Uart clock: x32\n");
         break;
      case 0x03:
	     logerror("Resetting #2 Uart\n");
	     uart2_status = 0x02;
         break;
      }

      switch (data & 0x1c)
      {
      case 0x00:
         logerror("#2 Uart - Bits :7 Parity: Even Stop Bits: 2\n");
         break;
      case 0x04:
         logerror("#2 Uart - Bits :7 Parity: Odd Stop Bits: 2\n");
         break;
      case 0x08:
         logerror("#2 Uart - Bits :7 Parity: Even Stop Bits: 1\n");
         break;
      case 0x0c:
         logerror("#2 Uart - Bits :7 Parity: Odd Stop Bits: 1\n");
         break;
      case 0x10:
         logerror("#2 Uart - Bits :8 Parity: None Stop Bits: 2\n");
         break;
      case 0x14:
         logerror("#2 Uart - Bits :8 Parity: None Stop Bits: 1\n");
         break;
      case 0x18:
         logerror("#2 Uart - Bits :8 Parity: Even Stop Bits: 1\n");
         break;
      case 0x1c:
         logerror("#2 Uart - Bits :7 Parity: Odd Stop Bits: 1\n");
         break;
      }

      switch (data & 0x60)
      {
      case 0x00:
         logerror("#2 Uart - /RTS=0, TX IRQ=0\n");
         break;
      case 0x20:
         logerror("#2 Uart - /RTS=0, TX IRQ=1\n");
         //Add Transmit IRQ function here
         break;
      case 0x40:
         logerror("#2 Uart - /RTS=1, TX IRQ=0\n");
         break;
      case 0x60:
         logerror("#2 Uart - /RTS=0, TX break level, TX IRQ=0\n");
         break;
      }

      if (data & 0x80)
      {
         logerror("#2 Uart - RX IRQ=1\n");
         //Add Receive IRQ function here
      }
      else
      {
         logerror("#2 Uart - RX IRQ=0\n");
      }

#ifdef LOG_SERIAL
logerror("#2 Uart control reg (%02X)\n",data);
#endif
}

///////////////////////////////////////////////////////////////////////////

static WRITE8_HANDLER( uart2data_w )
{
	uart2_status = uart2_status & 0x7d;// Clear the IRQ and the TDR Empty
	#ifdef UART_LOG
	logerror("uart2:%c\n", data);
	#endif
}

///////////////////////////////////////////////////////////////////////////

static WRITE8_HANDLER( mpu4_uart_tx_w )
{
	uart2_status = uart2_status & 0xfd;// Clear the IRQ and the TDR Empty
	#ifdef LOG_SERIAL
	logerror("transmitting to VidCard (%02X)\n",data);
	#endif
	send_to_uart1(data);
}

///////////////////////////////////////////////////////////////////////////

static WRITE8_HANDLER( mpu4_uart_ctrl_w )
{
      switch (data & 0x03)
      {
      case 0x00:
         logerror("#2 Uart clock: x1\n");
         break;
      case 0x01:
         logerror("#2 Uart clock: x16\n");
         break;
      case 0x02:
         logerror("#2 Uart clock: x32\n");
         break;
      case 0x03:
	     logerror("Resetting #2 Uart\n");
	     uart2_status = 0x02;
         break;
      }

      switch (data & 0x1c)
      {
      case 0x00:
         logerror("#2 Uart - Bits :7 Parity: Even Stop Bits: 2\n");
         break;
      case 0x04:
         logerror("#2 Uart - Bits :7 Parity: Odd Stop Bits: 2\n");
         break;
      case 0x08:
         logerror("#2 Uart - Bits :7 Parity: Even Stop Bits: 1\n");
         break;
      case 0x0c:
         logerror("#2 Uart - Bits :7 Parity: Odd Stop Bits: 1\n");
         break;
      case 0x10:
         logerror("#2 Uart - Bits :8 Parity: None Stop Bits: 2\n");
         break;
      case 0x14:
         logerror("#2 Uart - Bits :8 Parity: None Stop Bits: 1\n");
         break;
      case 0x18:
         logerror("#2 Uart - Bits :8 Parity: Even Stop Bits: 1\n");
         break;
      case 0x1c:
         logerror("#2 Uart - Bits :7 Parity: Odd Stop Bits: 1\n");
         break;
      }

      switch (data & 0x60)
      {
      case 0x00:
         logerror("#2 Uart - /RTS=0, TX IRQ=0\n");
         break;
      case 0x20:
         logerror("#2 Uart - /RTS=0, TX IRQ=1\n");
         //Add Transmit IRQ function here
         break;
      case 0x40:
         logerror("#2 Uart - /RTS=1, TX IRQ=0\n");
         break;
      case 0x60:
         logerror("#2 Uart - /RTS=0, TX break level, TX IRQ=0\n");
         break;
      }

      if (data & 0x80)
      {
         logerror("#2 Uart - RX IRQ=1\n");
         //Add Receive IRQ function here
      }
      else
      {
         logerror("#2 Uart - RX IRQ=0\n");
      }

#ifdef LOG_SERIAL
logerror("#2 Uart control reg (%02X)\n",data);
#endif
}
///////////////////////////////////////////////////////////////////////////

static READ8_HANDLER( mpu4_uart_rx_r )
{
	{
		if (uart2_status & 0x01)
		{
  			return read_from_uart1();
		}
	uart2_status &= 0x7e; // Clear the IRQ and the RDR Full
	}

#ifdef LOG_SERIAL
logerror("Received from VidCard (%02X)\n",uart1_data);
#endif
return uart1_data;
}

///////////////////////////////////////////////////////////////////////////

static READ8_HANDLER( mpu4_uart_ctrl_r )
{
  return get_uart2_status();
}

///////////////////////////////////////////////////////////////////////////


///////////////////////////////////////////////////////////////////////////

static READ16_HANDLER( vidcard_uart_ctrl_r )
{
  return get_uart1_status();
}

///////////////////////////////////////////////////////////////////////////

static WRITE16_HANDLER( vidcard_uart_ctrl_w )
{

  if (ACCESSING_MSB)
  {
  ctrl = ((data >> 8) & 0xff);
  }
  if (ACCESSING_LSB)
  {
  ctrl = (data & 0xff);
  }

     switch (ctrl & 0x03)
      {
      case 0x00:
         logerror("Vid Uart clock: x1\n");
         break;
      case 0x01:
         logerror("Vid Uart clock: x16\n");
         break;
      case 0x02:
         logerror("Vid Uart clock: x32\n");
         break;
      case 0x03:
         logerror("Resetting Vid Uart\n");
         uart1_status = 0x02;
         break;
      }

      switch (ctrl & 0x1c)
      {
      case 0x00:
         logerror("Vid Uart - Bits :7 Parity: Even Stop Bits: 2\n");
         break;
      case 0x04:
         logerror("Vid Uart - Bits :7 Parity: Odd Stop Bits: 2\n");
         break;
      case 0x08:
         logerror("Vid Uart - Bits :7 Parity: Even Stop Bits: 1\n");
         break;
      case 0x0c:
         logerror("Vid Uart - Bits :7 Parity: Odd Stop Bits: 1\n");
         break;
      case 0x10:
         logerror("Vid Uart - Bits :8 Parity: None Stop Bits: 2\n");
         break;
      case 0x14:
         logerror("Vid Uart - Bits :8 Parity: None Stop Bits: 1\n");
         break;
      case 0x18:
         logerror("Vid Uart - Bits :8 Parity: Even Stop Bits: 1\n");
         break;
      case 0x1c:
         logerror("Vid Uart - Bits :7 Parity: Odd Stop Bits: 1\n");
         break;
      }

      switch (ctrl & 0x60)
      {
      case 0x00:
         logerror("Vid Uart - /RTS=0, TX IRQ=0\n");
         break;
      case 0x20:
         logerror("Vid Uart - /RTS=0, TX IRQ=1\n");
         // Add Transmit IRQ Function here
         break;
      case 0x40:
         logerror("Vid Uart - /RTS=1, TX IRQ=0\n");// In this situation, we need to trigger our RTS function
         break;
      case 0x60:
         logerror("Vid Uart - /RTS=0, TX break level, TX IRQ=0\n");
         break;
      }

      if (ctrl & 0x80)
      {
         logerror("Vid Uart - RX IRQ=1\n");
         // Add Receive IRQ Function here
      }
      else
      {
         logerror("Vid Uart - RX IRQ=0\n");
      }

  #ifdef LOG_CTRL
  logerror("VID uart ctrl:%02X\n", ctrl);
  #endif
}

///////////////////////////////////////////////////////////////////////////

static READ16_HANDLER( vidcard_uart_rx_r )
{
if (uart1_status & 0x01)
{
  aciadata = read_from_uart2();
}
uart1_status = uart1_status & 0x7e; // Clear the IRQ and the RDR Full

  return (aciadata << 8) | 0x00ff;

#ifdef LOG_SERIAL
  logerror("Received from NORM (%02X)\n",aciadata);
#endif

}

///////////////////////////////////////////////////////////////////////////

static WRITE16_HANDLER( vidcard_uart_tx_w )
{
uart1_status = uart1_status & 0xfd;//0x7d;// Clear the IRQ and the TDR Empty

  if (ACCESSING_MSB)
  send_to_uart2((data >> 8) & 0xff);
  if (ACCESSING_LSB)
  send_to_uart2(data & 0xff); //Fill TDR
}

///////////////////////////////////////////////////////////////////////////
