/*****************************************************************************/
/*                                                                           */
/*   VECTREX HP3000 Software Emulator              Copyright K.Wilkins 1996  */
/*                                                                           */
/*****************************************************************************/
/*                                                                           */
/*   Title      : VECTREX HP3000 Analog CRT X,Y,Z & Compare Emulation Module */
/*                                                                           */
/*   File Name  : ANALOG.C                                                   */
/*                                                                           */
/*   Author     : Keith Wilkins / small changes by C.S.                      */
/*                                                                           */
/*   Version    : 1.20                                                       */
/*                                                                           */
/*   Desciption : The functions is this module are designed to emulate the   */
/*                analog portion of the Vectrex that generates the CRT X,Y   */
/*                and Z signals and the COMPARE signal that is used to       */
/*                perform the AtoD function for the Controller Pads.         */
/*                                                                           */
/*                The main fAnalogTick() function in this block emulates     */
/*                the analog functions for N ticks where a tick is the       */
/*                smallest unit of activity in the alanog block. It is the   */
/*                responsibility of the Sequencer to call this function at   */
/*                the appropriate time with an appropriate value for N       */
/*                                                                           */
/*   Functions  : fAnalogInit() - Initialise the Analog block                */
/*                fAnalogTick() - Simulate N time units                      */
/*                                                                           */
/*****************************************************************************/
/*                                                                           */
/*   Revision History:                                                       */
/*                                                                           */
/*   Version    Date    Who  Description of changes                          */
/*   -------    ----    ---  ----------------------                          */
/*                                                                           */
/*    0.01    13/03/93  K.W  Creation                                        */
/*    1.00    05/08/96  K.W  Public release of DVE V1.0                      */
/*    1.20    20/10/96  C.S  Public release of DVE V1.2                      */
/*                                                                           */
/*****************************************************************************/

#ifdef _NO_DEBUG_INFORMATION_

#include <stdlib.h>
#include <math.h>

#include <tools.h>
#include <standard.h>

//#include "font.h"
#include "display.h"
#include "emu6522.h"
#include "emu6809.h"
#include "keyboard.h"
#include "joystick.h"
#include "vdebug.h"
#include "verror.h"
#include "vectrex.h"
#include "analog.h"

T_SCHAR lXSampleHold=0; //T_SLONG
T_SCHAR lYSampleHold=0; //T_SLONG
T_UCHAR tZSampleHold=0;

T_SCHAR tIntegratorOffset=0;
T_SLONG lSIGDEF_XOUTPUT=0;
T_SLONG lSIGDEF_YOUTPUT=0;
T_UCHAR tSIGDEF_ZOUTPUT=0;

T_SLONG DAC_lookup[256];

T_SLONG lOldXSH=-1;
T_SLONG lOldYSH=-1;
T_UCHAR tOldZSH=-1;

T_SLONG lOldSigX=-1;
T_SLONG lOldSigY=-1;
T_UCHAR tOldSigZ=-1;

T_UCHAR tOldBlank=0;
T_UCHAR tOldRamp=123;
T_UCHAR tOldZero=123;
T_UCHAR tOldSel=123;
T_UCHAR tOldShold=123;

T_SCHAR tOldIntegratorOffset=-1;
T_UCHAR tOldLastRamp=-1;

T_SCHAR dac_offset=0;
T_SWORD integrator_offset_y=0;
T_SWORD integrator_offset_x=0;


/************************************************************************/
/* some variables changed to globales... since fAnalogTick is sometimes */
/* inline now...                                                        */
/************************************************************************/

T_ULONG lwTickMark=0;
T_UCHAR tLastRamp=0;
T_SLONG lX1=0,lY1=0;
T_UCHAR tBright=0;;

static  T_SLONG anajoyx1=0,anajoyy1=0;
static  T_SLONG anajoyx2=0,anajoyy2=0;

T_VOID (* fAnalogTick)(T_VOID);
T_VOID (* fAnalogJoystickUpdate)(T_VOID);


#endif //#ifdef _NO_DEBUG_INFORMATION_

#ifndef _NO_DEBUG_INFORMATION_
/*****************************************************************************/
/*                                                                           */
/*   Function    : fAnalogInit()                                             */
/*                                                                           */
/*   Author      : K.W                                                       */
/*                                                                           */
/*   Description : This function initialises the variables and workings of   */
/*                 the module that simulates the analog functions of the     */
/*                 Vectrex.                                                  */
/*                                                                           */
/*   Accepts     : nothing                                                   */
/*                                                                           */
/*   Returns     : BYTE of initialisation status T_TRUE/T_FALSE                  */
/*                                                                           */
/*****************************************************************************/

T_INT fAnalogInit(T_VOID)
{
 T_SWORD   loop;

 /*******************************/
 /* Create DAC log lookup table */
 /*******************************/
/*
 DAC_lookup[0]=0;
 for(loop=1;loop<128;loop++)
 {
  DAC_lookup[loop]=32*log(abs(loop));
  t_printf(E_VERBOSE_NONE,"1DAC_lookup[%i]:=%i\n",loop,DAC_lookup[loop]);
  DAC_lookup[256-loop]=-(32*log(abs(loop)));
 }
 DAC_lookup[128]=-(32*log(abs(128)));
*/

 for(loop=0;loop<256;loop++)
 {
  DAC_lookup[loop]=(loop^0x80)-128;
 }
 return(T_TRUE);
}

/*****************************************************************************/
/*                                                                           */
/*   Function    : fAnalogReset()                                            */
/*                                                                           */
/*   Author      : K.W                                                       */
/*                                                                           */
/*   Description : This function resets the analog block, a hard reset       */
/*                                                                           */
/*   Accepts     : nothing                                                   */
/*                                                                           */
/*   Returns     : nothing                                                   */
/*                                                                           */
/*****************************************************************************/

T_VOID fAnalogReset(T_VOID)
{
 lXSampleHold=0;
 lYSampleHold=0;
 tZSampleHold=0;
 lSIGDEF_XOUTPUT=0;
 lSIGDEF_YOUTPUT=0;
 tSIGDEF_ZOUTPUT=0;
 return;
}
/*****************************************************************************/
/*                                                                           */
/*   Function    : fAnalogJoystickUpdate()                                   */
/*                                                                           */
/*   Author      : K.W                                                       */
/*                                                                           */
/*   Description : This function updates the compare pin based on all of the */
/*                 current switch settings                                   */
/*                                                                           */
/*   Accepts     : nothing                                                   */
/*                                                                           */
/*   Returns     : nothing                                                   */
/*                                                                           */
/*****************************************************************************/

T_VOID fAnalogJoystickUpdateDigital(T_VOID)
{
 T_SCHAR   sbDACVal;
 T_SCHAR   sbJOYVal=0;

 sbDACVal=(T_SCHAR)tSIGDEF_DACBUS;

 switch (tSIGDEF_AMUXSEL)
 {
  case 0: // P1 controller Y axis
    if (fKBDisdown(wGblPly1JoystkRt))
     sbJOYVal=127; //Max negative
    if (fKBDisdown(wGblPly1JoystkLf))
     sbJOYVal=-127; //Max positive
   break;
  case 2: // P1 controller X axis
    if (fKBDisdown(wGblPly1JoystkDn))
     sbJOYVal=-127; //Max negative
    if (fKBDisdown(wGblPly1JoystkUp))
     sbJOYVal=127; //Max positive
   break;
  case 4: // P2 controller Y axis
    if (fKBDisdown(wGblPly2JoystkRt))
     sbJOYVal=127; //Max negative
    if (fKBDisdown(wGblPly2JoystkLf))
     sbJOYVal=-127; //Max positive
   break;
  case 6: // P2 controller X axis
    if (fKBDisdown(wGblPly2JoystkDn))
     sbJOYVal=-127; //Max negative
    if (fKBDisdown(wGblPly2JoystkUp))
     sbJOYVal=127; //Max positive
   break;
  default:
   fDebug(VERROR,("fAnalogTick() Illegal analog mux setting"));
   break;
 }

 /**************/
 /* Do compare */
 /**************/
 tSIGDEF_COMPARE=(sbJOYVal>sbDACVal)?0x20:0;
}

/*****************************************************************************/
/*                                                                           */
/*   Function    : fAnalogJoystickUpdate()                                   */
/*                                                                           */
/*   Author      : K.W                                                       */
/*                                                                           */
/*   Description : This function updates the compare pin based on all of the */
/*                 current switch settings                                   */
/*                                                                           */
/*   Accepts     : nothing                                                   */
/*                                                                           */
/*   Returns     : nothing                                                   */
/*                                                                           */
/*****************************************************************************/
T_VOID fAnalogJoystickUpdateAnalog(T_VOID)
{
 T_SCHAR   sbDACVal;
 T_SCHAR   sbJOYVal=0;

 sbDACVal=(T_SCHAR)tSIGDEF_DACBUS;

 /*******************************************************/
 /* If analog joystick is enabled then process movement */
 /*******************************************************/
  if (fKBDisdown(wGblPly1JoystkRt))
  {
   if (anajoyy1<32767-wGblJoystickSensitivity)
    anajoyy1+=wGblJoystickSensitivity;
  }
  else if (fKBDisdown(wGblPly1JoystkLf))
  {
   if (anajoyy1>-32768+wGblJoystickSensitivity)
    anajoyy1-=wGblJoystickSensitivity;
  }
  else if (bGblJoystickAutoCentre)
  {
   if (anajoyy1>0)
    anajoyy1-=wGblJoystickSensitivity;
   else if(anajoyy1<0)
    anajoyy1+=wGblJoystickSensitivity;
  }
  if (fKBDisdown(wGblPly1JoystkUp))
  {
   if (anajoyx1<32767-wGblJoystickSensitivity)
    anajoyx1+=wGblJoystickSensitivity;
  }
  else if (fKBDisdown(wGblPly1JoystkDn))
  {
   if (anajoyx1>-32768+wGblJoystickSensitivity)
    anajoyx1-=wGblJoystickSensitivity;
  }
  else if (bGblJoystickAutoCentre)
  {
   if (anajoyx1>0)
    anajoyx1-=wGblJoystickSensitivity;
   else if(anajoyx1<0)
    anajoyx1+=wGblJoystickSensitivity;
  }
  if (fKBDisdown(wGblPly2JoystkRt))
  {
   if (anajoyy2<32767-wGblJoystickSensitivity)
    anajoyy2+=wGblJoystickSensitivity;
  }
  else if (fKBDisdown(wGblPly2JoystkLf))
  {
   if (anajoyy2>-32768+wGblJoystickSensitivity)
    anajoyy2-=wGblJoystickSensitivity;
  }
  else if(bGblJoystickAutoCentre)
  {
   if (anajoyy2>0)
    anajoyy2-=wGblJoystickSensitivity;
   else if (anajoyy2<0)
    anajoyy2+=wGblJoystickSensitivity;
  }
  if (fKBDisdown(wGblPly2JoystkUp))
  {
   if(anajoyx2<32767-wGblJoystickSensitivity) anajoyx2+=wGblJoystickSensitivity;
  }
  else if (fKBDisdown(wGblPly2JoystkDn))
  {
   if (anajoyx2>-32768+wGblJoystickSensitivity)
    anajoyx2-=wGblJoystickSensitivity;
  }
  else if (bGblJoystickAutoCentre)
  {
   if (anajoyx2>0)
    anajoyx2-=wGblJoystickSensitivity;
   else if (anajoyx2<0)
    anajoyx2+=wGblJoystickSensitivity;
  }
 switch (tSIGDEF_AMUXSEL)
 {
  case 0: // P1 controller Y axis
   sbJOYVal=anajoyy1>>8;
   break;
  case 2: // P1 controller X axis
   sbJOYVal=anajoyx1>>8;
   break;
  case 4: // P2 controller Y axis
   sbJOYVal=anajoyy2>>8;
   break;
  case 6: // P2 controller X axis
   sbJOYVal=anajoyx2>>8;
   break;
  default:
   fDebug(VERROR,("fAnalogTick() Illegal analog mux setting"));
   break;
 }
 /**************/
 /* Do compare */
 /**************/
 tSIGDEF_COMPARE=(sbJOYVal>sbDACVal)?0x20:0;
}

T_VOID fAnalogJoystickUpdatePCJoystickAnalog(T_VOID)
{
 T_SCHAR   sbDACVal;
 T_SCHAR   sbJOYVal=0;

 sbDACVal=(T_SCHAR)tSIGDEF_DACBUS;

 positions_analog();

 switch (tSIGDEF_AMUXSEL)
 {
  case 0: // P1 controller X axis
   sbJOYVal=joy1x;
   break;
  case 2: // P1 controller Y axis
   sbJOYVal=joy1y;
   break;
  case 4: // P2 controller X axis
   sbJOYVal=joy2x;
   break;
  case 6: // P2 controller Y axis
   sbJOYVal=joy2y;
   break;
  default:
   fDebug(VERROR,("fAnalogTick() Illegal analog mux setting"));
   break;
 }
 /**************/
 /* Do compare */
 /**************/
 tSIGDEF_COMPARE=(sbJOYVal>sbDACVal)?0x20:0;
}

T_VOID fAnalogJoystickUpdatePCJoystickDigital(T_VOID)
{
 T_SCHAR   sbDACVal;
 T_SCHAR   sbJOYVal=0;

 sbDACVal=(T_SCHAR)tSIGDEF_DACBUS;
 positions_digital();

 switch (tSIGDEF_AMUXSEL)
 {
  case 0: // P1 controller X axis
   sbJOYVal=joy1x; //Max negative
   break;
  case 2: // P1 controller Y axis
   sbJOYVal=joy1y; //Max negative
   break;
  case 4: // P2 controller X axis
   sbJOYVal=joy2x; //Max negative
   break;
  case 6: // P2 controller Y axis
   sbJOYVal=joy2y; //Max positive
   break;
  default:
   fDebug(VERROR,("fAnalogTick() Illegal analog mux setting"));
   break;
 }
 /**************/
 /* Do compare */
 /**************/
 tSIGDEF_COMPARE=(sbJOYVal>sbDACVal)?0x20:0;
}
#endif //#ifndef _NO_DEBUG_INFORMATION_


