#include "pcfx.h"
#include "v810_cpu.h"
#include "scsicd.h"

typedef struct
{
 uint8 DB; // Data bus
 bool BSY, ACK, RST, MSG, SEL, CD, REQ, IO;

 // These variables contain how long the lines above have been at the state they are currently at.
 uint64 BSY_time, ACK_time, RST_time, SEL_time, CD_time, REQ_time, IO_time;

 uint32 Bus_Phase;
 #define BP_BUS_FREE 	0
 #define BP_ARBITRATION	1
 #define BP_SELECTION	2
 #define BP_RESELECTION	3
 #define BP_COMMAND	4
 #define BP_DATA_IN	5
 #define BP_DATA_OUT	6
 #define BP_STATUS	7
 #define BP_MESSAGE_IN	8
 #define BP_MESSAGE_OUT	9

 uint32 lastts;
} scsicd_t;

scsicd_t cd;

// Cycles // nanoseconds
static const int Arbitration_Delay = 47; //2200;
static const int Assertion_Period = 1; //90;
static const int Bus_Clear_Delay = 10; //500;
static const int Bus_Free_Delay = 10; //500;
static const int Bus_Set_Delay = 38; //1800;
static const int Bus_Settle_Delay = 8; //400;
static const int Cable_Skew_Delay = 0; //10;
static const int Data_Release_Delay = 8; //400;
static const int Deskew_Delay = 0; //45;
static const int Hold_Time = 0; //45;
static const int Negation_Period = 1; //90;
static const int Reset_Hold_Time = 536; //25000;
static const int Selection_Abort_Time = 4295; //200000;
static const int Selection_Timeout_Delay = 5369318; //250000000;
//static const int Transfer_Period = 

void SCSICD_Power(void)
{
 memset(&cd, 0, sizeof(scsicd_t));
}

void SCSICD_SetDB(uint8 data)
{
 SCSICD_Run();
 cd.DB = data;
}

uint8 SCSICD_GetDB(void)
{
 SCSICD_Run();
 return(cd.DB);
}

void SCSICD_SetACK(bool set)
{
 SCSICD_Run();
 cd.ACK = set;
}

void SCSICD_SetMSG(bool set)
{
 SCSICD_Run();
 cd.MSG = set;
}

void SCSICD_SetREQ(bool set)
{
 SCSICD_Run();
 cd.REQ = set;
}

void SCSICD_SetSEL(bool set)
{
 SCSICD_Run();
 cd.SEL = set;
}

void SCSICD_SetRST(bool set)
{
 SCSICD_Run();
 cd.RST = set;
}

void SCSICD_SetBSY(bool set)
{
 SCSICD_Run();
 cd.BSY = set;
}

void SCSICD_SetCD(bool set)
{
 SCSICD_Run();
 cd.CD = set;
}

void SCSICD_SetIO(bool set)
{
 SCSICD_Run();
 cd.IO = set;
}


bool SCSICD_GetBSY(void)
{
 SCSICD_Run();
 return(cd.BSY);
}

bool SCSICD_GetACK(void)
{
 SCSICD_Run();
 return(cd.ACK);
}

bool SCSICD_GetRST(void)
{
 SCSICD_Run();
 return(cd.RST);
}

bool SCSICD_GetMSG(void)
{
 SCSICD_Run();
 return(cd.MSG);
}

bool SCSICD_GetSEL(void)
{
 SCSICD_Run();
 return(cd.SEL);
}

bool SCSICD_GetCD(void)
{
 SCSICD_Run();
 return(cd.CD);
}

bool SCSICD_GetREQ(void)
{
 SCSICD_Run();
 return(cd.REQ);
}

bool SCSICD_GetIO(void)
{
 SCSICD_Run();
 return(cd.IO);
}


void SCSICD_Run(void)
{
 int cycles = v810_timestamp - cd.lastts;

 cd.BSY_time += cycles;
 cd.ACK_time += cycles;
 cd.RST_time += cycles;
 cd.SEL_time += cycles;
 cd.CD_time += cycles;
 cd.REQ_time += cycles;
 cd.IO_time += cycles;

 if(!cd.BSY && !cd.SEL && cd.BSY_time >= Bus_Settle_Delay && cd.SEL_time >= Bus_Settle_Delay)
 {
  cd.Bus_Phase = BP_BUS_FREE;
  cd.CD = 0;
  cd.IO = 0;
  cd.MSG = 0;
 }

 switch(cd.Bus_Phase)
 {
  case BP_BUS_FREE: ;
 }

 cd.lastts = v810_timestamp;
}
