#include <stdio.h>
#include <string.h>
#include "port.h"
#include "misc.h"
#include "lc89510.h"
#include "cd_aspi.h"
#include "star_68k.h"
#include "mem_s68k.h"
#include "pcm.h"

#define CDC_DMA_SPEED 256

int CDC_Decode_Reg_Read;

void
CDD_Reset (void)
{
  int i;

  // Reseting CDD

  CDD.Fader = 0;
  CDD.Control = 0;
  CDD.Cur_Comm = 0;
  CDD.Status = 0;
  CDD.Minute = 0;
  CDD.Seconde = 0;
  CDD.Frame = 0;
  CDD.Ext = 0;

  for (i = 0; i < 10; i++)
    {
      CDD.Rcv_Status[i] = 0;
      CDD.Trans_Comm[i] = 0;
    }

  CDD.Rcv_Status[8] = 0xF;	// Default checksum

  SCD.Cur_Track = 0;
  SCD.Cur_LBA = -150;
  SCD.Status_CDD = READY;
}


void
CDC_Reset (void)
{
  //int i;

  // Reseting CDC

  memset (CDC.Buffer, 0, (16 * 1024 * 2) + 2352);
  CDC_Update_Header ();

  CDC.COMIN = 0;
  CDC.IFSTAT = 0xFF;
  CDC.DAC.N = 0;
  CDC.DBC.N = 0;
  CDC.HEAD.N = 0x01000000;
  CDC.PT.N = 0;
  CDC.WA.N = 2352 * 2;
  CDC.STAT.N = 0x00000080;
  CDC.SBOUT = 0;
  CDC.IFCTRL = 0;
  CDC.CTRL.N = 0;

  CDC_Decode_Reg_Read = 0;
}


void
LC89510_Reset (void)
{
  CDD_Reset ();
  CDC_Reset ();

  CDC.RS0 = 0;
  CDC.RS1 = 0;
  CDC.Host_Data = 0;
  CDC.DMA_Adr = 0;
  CDC.Stop_Watch = 0;

  SCD.Status_CDC = 0;
  CDD_Complete = 0;
}

void
Update_CDC_TRansfert (void)
{
  unsigned int dep, lenght, add_dest;
  unsigned char *dest;

  if ((SCD.Status_CDC & 0x08) == 0)
    return;

  switch (CDC.RS0 & 0x0700)
    {
    case 0x0200:		// MAIN CPU
    case 0x0300:		// SUB CPU
      CDC.RS0 |= 0x4000;	// Data ready in host port
      return;
      break;

    case 0x0400:		// PCM RAM
      dest = (unsigned char *) Ram_PCM;
      dep = ((CDC.DMA_Adr & 0x03FF) << 2) + PCM_Chip.Bank;
      add_dest = 2;
      break;

    case 0x0500:		// PRG RAM
      dest = (unsigned char *) Ram_Prg;
      dep = (CDC.DMA_Adr & 0xFFFF) << 3;
      add_dest = 2;
#ifdef DEBUG_CD
//                      fprintf(debug_SCD_file, "DMA transfert PRG RAM : adr = %.8X  ", dep);
#endif
      break;

    case 0x0700:		// WORD RAM
      if (Ram_Word_State >= 2)
	{
	  dest = (unsigned char *) Ram_Word_1M;
	  add_dest = 2;
	  if (Ram_Word_State & 1)
	    dep = ((CDC.DMA_Adr & 0x3FFF) << 3);
	  else
	    dep = ((CDC.DMA_Adr & 0x3FFF) << 3) + 0x20000;
	}
      else
	{
	  dest = (unsigned char *) Ram_Word_2M;
	  dep = ((CDC.DMA_Adr & 0x7FFF) << 3);
	  add_dest = 2;
	}
      break;

    default:
      return;
    }

  if (CDC.DBC.N <= (CDC_DMA_SPEED * 2))
    {
      lenght = (CDC.DBC.N + 1) >> 1;
      SCD.Status_CDC &= ~0x08;	// Last transfert
      CDC.RS0 |= 0x8000;	// End data transfert
      CDC.RS0 &= ~0x4000;	// no more data ready
      CDC.IFSTAT |= 0x08;	// No more data transfert in progress

      if (CDC.IFCTRL & 0x40)	// DTEIEN = Data Trasnfert End Interrupt Enable ?
	{
	  CDC.IFSTAT &= ~0x40;

	  if (Int_Mask_S68K & 0x20)
	    sub68k_interrupt (5, -1);

#ifdef DEBUG_CD
	  fprintf (debug_SCD_file, "CDC - DTE interrupt\n");
#endif
	}
    }
  else
    lenght = CDC_DMA_SPEED;

#ifdef DEBUG_CD
//      fprintf(debug_SCD_file, "DMA lenght = %.4X\n", lenght);
#endif


  if ((CDC.RS0 & 0x0700) == 0x0400)	// PCM DMA
    {
      int len = lenght;
      unsigned char *src = (unsigned char *) &CDC.Buffer[CDC.DAC.N];
      unsigned char *dst = (unsigned char *) dest + dep;

      while (len--)
	{
	  *(unsigned short *) dst = *(unsigned short *) src;
	  src += 2;
	  dst += add_dest;
	}
      lenght <<= 1;
      CDC.DMA_Adr += lenght >> 2;
    }
  else				// OTHER DMA
    {
      int len = lenght;
      unsigned char *src = (unsigned char *) &CDC.Buffer[CDC.DAC.N];
      unsigned char *dst = (unsigned char *) dest + dep;

      while (len--)
	{
	  unsigned short outrol = *(unsigned short *) src;
	  outrol = (outrol << 8) | (outrol >> 8);

	  *(unsigned short *) dst = outrol;
	  src += 2;
	  dst += add_dest;
	}
      lenght <<= 1;
      CDC.DMA_Adr += lenght >> 3;
    }

  CDC.DAC.N = (CDC.DAC.N + lenght) & 0xFFFF;
  if (SCD.Status_CDC & 0x08)
    CDC.DBC.N -= lenght;
  else
    CDC.DBC.N = 0;
}


unsigned short
Read_CDC_Host_SUB (void)
{
  unsigned short val;

  if (SCD.Status_CDC & 0x08)	// Transfert data
    {
      if ((CDC.RS0 & 0x0700) == 0x0300)	// SUB CPU
	{
	  CDC.DBC.N -= 2;

	  if (CDC.DBC.N <= 0)
	    {
	      CDC.DBC.N = 0;
	      SCD.Status_CDC &= ~0x08;	// Last transfert
	      CDC.RS0 |= 0x8000;	// End data transfert
	      CDC.RS0 &= ~0x4000;	// no more data ready
	      CDC.IFSTAT |= 0x08;	// No more data transfert in progress

	      if (CDC.IFCTRL & 0x40)	// DTEIEN = Data Trasnfert End Interrupt Enable ?
		{
		  CDC.IFSTAT &= ~0x40;

		  if (Int_Mask_S68K & 0x20)
		    sub68k_interrupt (5, -1);

#ifdef DEBUG_CD
		  fprintf (debug_SCD_file, "CDC - DTE interrupt\n");
#endif
		}
	    }
	  val = *(unsigned short *) &CDC.Buffer[CDC.DAC.N];
	  CDC.DAC.N += 2;
	  val = (val >> 8) | (val << 8);
#ifdef DEBUG_CD
//      fprintf(debug_SCD_file, "Host READ on SUB CPU side : %.4X  DBA = %.4X  DBC = %.4X\n", val, CDC.DBC.N, CDC.DAC.N);
#endif

	  return val;
	}
    }

  return 0;
}


unsigned short
Read_CDC_Host_MAIN (void)
{
  unsigned short val;

  if (SCD.Status_CDC & 0x08)	// Transfert data
    {
      if ((CDC.RS0 & 0x0700) == 0x0200)	// MAIN CPU
	{
	  CDC.DBC.N -= 2;

	  if (CDC.DBC.N <= 0)
	    {
	      SCD.Status_CDC &= ~0x08;	// Last transfert
	      CDC.RS0 |= 0x8000;	// End data transfert
	      CDC.RS0 &= ~0x4000;	// no more data ready
	      CDC.IFSTAT |= 0x08;	// No more data transfert in progress

	      if (CDC.IFCTRL & 0x40)	// DTEIEN = Data Trasnfert End Interrupt Enable ?
		{
		  CDC.IFSTAT &= ~0x40;

		  if (Int_Mask_S68K & 0x20)
		    sub68k_interrupt (5, -1);

#ifdef DEBUG_CD
		  fprintf (debug_SCD_file, "CDC - DTE interrupt\n");
#endif
		}
	    }
	  val = *(unsigned short *) &CDC.Buffer[CDC.DAC.N];
	  CDC.DAC.N += 2;
	  val = (val >> 8) | (val << 8);
#ifdef DEBUG_CD
//      fprintf(debug_SCD_file, "Host READ on SUB CPU side : %.4X  DBA = %.4X  DBC = %.4X\n", val, CDC.DBC.N, CDC.DAC.N);
#endif

	  return val;
	}
    }

  return 0;
}


void
CDC_Update_Header (void)
{
  if (CDC.CTRL.B.B1 & 0x01)	// Sub-Hearder wanted ?
    {
      CDC.HEAD.B.B0 = 0;
      CDC.HEAD.B.B1 = 0;
      CDC.HEAD.B.B2 = 0;
      CDC.HEAD.B.B3 = 0;
    }
  else
    {
      _msf MSF;

      LBA_to_MSF (SCD.Cur_LBA, &MSF);

      CDC.HEAD.B.B0 = INT_TO_BCDB (MSF.M);
      CDC.HEAD.B.B1 = INT_TO_BCDB (MSF.S);
      CDC.HEAD.B.B2 = INT_TO_BCDB (MSF.F);
      CDC.HEAD.B.B3 = 0x01;
    }
}


unsigned char
CDC_Read_Reg (void)
{
  unsigned char ret;

#ifdef DEBUG_CD
  fprintf (debug_SCD_file, "CDC read reg %.2d = ", CDC.RS0 & 0xF);
#endif

  switch (CDC.RS0 & 0xF)
    {
    case 0x0:			// COMIN
#ifdef DEBUG_CD
      fprintf (debug_SCD_file, "%.2X\n", CDC.COMIN);
#endif

      CDC.RS0 = (CDC.RS0 & 0xFFF0) | 0x1;
      return CDC.COMIN;

    case 0x1:			// IFSTAT
#ifdef DEBUG_CD
      fprintf (debug_SCD_file, "%.2X\n", CDC.IFSTAT);
#endif

      CDC_Decode_Reg_Read |= (1 << 1);	// Reg 1 (decoding)
      CDC.RS0 = (CDC.RS0 & 0xFFF0) | 0x2;
      return CDC.IFSTAT;

    case 0x2:			// DBCL
#ifdef DEBUG_CD
      fprintf (debug_SCD_file, "%.2X\n", CDC.DBC.B.L);
#endif

      CDC.RS0 = (CDC.RS0 & 0xFFF0) | 0x3;
      return CDC.DBC.B.L;

    case 0x3:			// DBCH
#ifdef DEBUG_CD
      fprintf (debug_SCD_file, "%.2X\n", CDC.DBC.B.H);
#endif

      CDC.RS0 = (CDC.RS0 & 0xFFF0) | 0x4;
      return CDC.DBC.B.H;

    case 0x4:			// HEAD0
#ifdef DEBUG_CD
      fprintf (debug_SCD_file, "%.2X\n", CDC.HEAD.B.B0);
#endif

      CDC_Decode_Reg_Read |= (1 << 4);	// Reg 4 (decoding)
      CDC.RS0 = (CDC.RS0 & 0xFFF0) | 0x5;
      return CDC.HEAD.B.B0;

    case 0x5:			// HEAD1
#ifdef DEBUG_CD
      fprintf (debug_SCD_file, "%.2X\n", CDC.HEAD.B.B1);
#endif

      CDC_Decode_Reg_Read |= (1 << 5);	// Reg 5 (decoding)
      CDC.RS0 = (CDC.RS0 & 0xFFF0) | 0x6;
      return CDC.HEAD.B.B1;

    case 0x6:			// HEAD2
#ifdef DEBUG_CD
      fprintf (debug_SCD_file, "%.2X\n", CDC.HEAD.B.B2);
#endif

      CDC_Decode_Reg_Read |= (1 << 6);	// Reg 6 (decoding)
      CDC.RS0 = (CDC.RS0 & 0xFFF0) | 0x7;
      return CDC.HEAD.B.B2;

    case 0x7:			// HEAD3
#ifdef DEBUG_CD
      fprintf (debug_SCD_file, "%.2X\n", CDC.HEAD.B.B3);
#endif

      CDC_Decode_Reg_Read |= (1 << 7);	// Reg 7 (decoding)
      CDC.RS0 = (CDC.RS0 & 0xFFF0) | 0x8;
      return CDC.HEAD.B.B3;

    case 0x8:			// PTL
#ifdef DEBUG_CD
      fprintf (debug_SCD_file, "%.2X\n", CDC.PT.B.L);
#endif

      CDC_Decode_Reg_Read |= (1 << 8);	// Reg 8 (decoding)
      CDC.RS0 = (CDC.RS0 & 0xFFF0) | 0x9;
      return CDC.PT.B.L;

    case 0x9:			// PTH
#ifdef DEBUG_CD
      fprintf (debug_SCD_file, "%.2X\n", CDC.PT.B.H);
#endif

      CDC_Decode_Reg_Read |= (1 << 9);	// Reg 9 (decoding)
      CDC.RS0 = (CDC.RS0 & 0xFFF0) | 0xA;
      return CDC.PT.B.H;

    case 0xA:			// WAL
#ifdef DEBUG_CD
      fprintf (debug_SCD_file, "%.2X\n", CDC.WA.B.L);
#endif

      CDC.RS0 = (CDC.RS0 & 0xFFF0) | 0xB;
      return CDC.WA.B.L;

    case 0xB:			// WAH
#ifdef DEBUG_CD
      fprintf (debug_SCD_file, "%.2X\n", CDC.WA.B.H);
#endif

      CDC.RS0 = (CDC.RS0 & 0xFFF0) | 0xC;
      return CDC.WA.B.H;

    case 0xC:			// STAT0
#ifdef DEBUG_CD
      fprintf (debug_SCD_file, "%.2X\n", CDC.STAT.B.B0);
#endif

      CDC_Decode_Reg_Read |= (1 << 12);	// Reg 12 (decoding)
      CDC.RS0 = (CDC.RS0 & 0xFFF0) | 0xD;
      return CDC.STAT.B.B0;

    case 0xD:			// STAT1
#ifdef DEBUG_CD
      fprintf (debug_SCD_file, "%.2X\n", CDC.STAT.B.B1);
#endif

      CDC_Decode_Reg_Read |= (1 << 13);	// Reg 13 (decoding)
      CDC.RS0 = (CDC.RS0 & 0xFFF0) | 0xE;
      return CDC.STAT.B.B1;

    case 0xE:			// STAT2
#ifdef DEBUG_CD
      fprintf (debug_SCD_file, "%.2X\n", CDC.STAT.B.B2);
#endif

      CDC_Decode_Reg_Read |= (1 << 14);	// Reg 14 (decoding)
      CDC.RS0 = (CDC.RS0 & 0xFFF0) | 0xF;
      return CDC.STAT.B.B2;

    case 0xF:			// STAT3
#ifdef DEBUG_CD
      fprintf (debug_SCD_file, "%.2X\n", CDC.STAT.B.B3);
#endif

      ret = CDC.STAT.B.B3;
      CDC.IFSTAT |= 0x20;	// decoding interrupt flag cleared
      if ((CDC.CTRL.B.B0 & 0x80) && (CDC.IFCTRL & 0x20))
	{
	  if ((CDC_Decode_Reg_Read & 0x73F2) == 0x73F2)
	    CDC.STAT.B.B3 = 0x80;
	}
      return ret;
    }

  return 0;
}


void
CDC_Write_Reg (unsigned char Data)
{

#ifdef DEBUG_CD
  fprintf (debug_SCD_file, "CDC write reg%d = %.2X\n", CDC.RS0 & 0xF, Data);
#endif

  switch (CDC.RS0 & 0xF)
    {
    case 0x0:			// SBOUT
      CDC.RS0 = (CDC.RS0 & 0xFFF0) | 0x1;
      CDC.SBOUT = Data;

      break;

    case 0x1:			// IFCTRL
      CDC.RS0 = (CDC.RS0 & 0xFFF0) | 0x2;
      CDC.IFCTRL = Data;

      if ((CDC.IFCTRL & 0x02) == 0)	// Stop data transfert
	{
	  CDC.DBC.N = 0;
	  SCD.Status_CDC &= ~0x08;
	  CDC.IFSTAT |= 0x08;	// No more data transfert in progress

/*
if (CDD.Trans_Comm[1] != 0)
{
	SCD.Status_CDD = READY;
	SCD.Status_CDC &= 0;
}*/

	}
      break;

    case 0x2:			// DBCL
      CDC.RS0 = (CDC.RS0 & 0xFFF0) | 0x3;
      CDC.DBC.B.L = Data;

      break;

    case 0x3:			// DBCH
      CDC.RS0 = (CDC.RS0 & 0xFFF0) | 0x4;
      CDC.DBC.B.H = Data;

      break;

    case 0x4:			// DACL
      CDC.RS0 = (CDC.RS0 & 0xFFF0) | 0x5;
      CDC.DAC.B.L = Data;

      break;

    case 0x5:			// DACH
      CDC.RS0 = (CDC.RS0 & 0xFFF0) | 0x6;
      CDC.DAC.B.H = Data;

      break;

    case 0x6:			// DTTRG
      if (CDC.IFCTRL & 0x02)	// Data transfert enable ?
	{
	  CDC.IFSTAT &= ~0x08;	// Data transfert in progress
	  SCD.Status_CDC |= 0x08;	// Data transfert in progress
	  CDC.RS0 &= 0x7FFF;	// A data transfert start

#ifdef DEBUG_CD
	  fprintf (debug_SCD_file,
		   "\n************** Starting Data Transfert ***********\n");
	  fprintf (debug_SCD_file,
		   "RS0 = %.4X  DAC = %.4X  DBC = %.4X  DMA adr = %.4X\n\n",
		   CDC.RS0, CDC.DAC.N, CDC.DBC.N, CDC.DMA_Adr);
#endif
	}
      break;

    case 0x7:			// DTACK
      CDC.IFSTAT |= 0x40;	// end data transfert interrupt flag cleared
      break;

    case 0x8:			// WAL
      CDC.RS0 = (CDC.RS0 & 0xFFF0) | 0x9;
      CDC.WA.B.L = Data;

      break;

    case 0x9:			// WAH
      CDC.RS0 = (CDC.RS0 & 0xFFF0) | 0xA;
      CDC.WA.B.H = Data;

      break;

    case 0xA:			// CTRL0
      CDC.RS0 = (CDC.RS0 & 0xFFF0) | 0xB;
      CDC.CTRL.B.B0 = Data;

      break;

    case 0xB:			// CTRL1
      CDC.RS0 = (CDC.RS0 & 0xFFF0) | 0xC;
      CDC.CTRL.B.B1 = Data;

      break;

    case 0xC:			// PTL
      CDC.RS0 = (CDC.RS0 & 0xFFF0) | 0xD;
      CDC.PT.B.L = Data;

      break;

    case 0xD:			// PTH
      CDC.RS0 = (CDC.RS0 & 0xFFF0) | 0xE;
      CDC.PT.B.H = Data;

      break;

    case 0xE:			// CTRL2
      CDC.CTRL.B.B2 = Data;
      break;

    case 0xF:			// RESET
      CDC_Reset ();
      break;
    }
}


void
CDD_Processing (void)
{

#ifdef DEBUG_CD
  fprintf (debug_SCD_file, "CDD exporting status\n");
  fprintf (debug_SCD_file,
	   "Status=%.4X, Minute=%.4X, Seconde=%.4X, Frame=%.4X, Ext=%.4X\n",
	   CDD.Status, CDD.Minute, CDD.Seconde, CDD.Frame, CDD.Ext);
#endif

  CDD_Export_Status ();

  sub68k_interrupt (4, -1);
}


void
CDD_Import_Command (void)
{

#ifdef DEBUG_CD
  fprintf (debug_SCD_file, "CDD importing command\n");
  fprintf (debug_SCD_file,
	   "Commande=%.4X, Minute=%.4X, Seconde=%.4X, Frame=%.4X  Checksum=%.4X\n",
	   (CDD.Trans_Comm[0] & 0xFF) + ((CDD.Trans_Comm[1] & 0xFF) << 8),
	   (CDD.Trans_Comm[2] & 0xFF) + ((CDD.Trans_Comm[3] & 0xFF) << 8),
	   (CDD.Trans_Comm[4] & 0xFF) + ((CDD.Trans_Comm[5] & 0xFF) << 8),
	   (CDD.Trans_Comm[6] & 0xFF) + ((CDD.Trans_Comm[7] & 0xFF) << 8),
	   (CDD.Trans_Comm[8] & 0xFF) + ((CDD.Trans_Comm[9] & 0xFF) << 8));
#endif

  switch (CDD.Trans_Comm[1])
    {
    case 0x0:			// STATUS (?)
      Get_Status_CDD_c0 ();
      break;

    case 0x1:			// STOP ALL (?)
      Stop_CDD_c1 ();
      break;

    case 0x2:			// GET TOC INFORMATIONS
      switch (CDD.Trans_Comm[2])
	{
	case 0x0:		// get current position (MSF format)
	  CDD.Status = (CDD.Status & 0xFF00);
	  Get_Pos_CDD_c20 ();
	  break;

	case 0x1:		// get elapsed time of current track played/scanned (relative MSF format)
	  CDD.Status = (CDD.Status & 0xFF00) | 1;
	  Get_Track_Pos_CDD_c21 ();
	  break;

	case 0x2:		// get current track in RS2-RS3
	  CDD.Status = (CDD.Status & 0xFF00) | 2;
	  Get_Current_Track_CDD_c22 ();
	  break;

	case 0x3:		// get total lenght (MSF format)
	  CDD.Status = (CDD.Status & 0xFF00) | 3;
	  Get_Total_Lenght_CDD_c23 ();
	  break;

	case 0x4:		// first & last track number
	  CDD.Status = (CDD.Status & 0xFF00) | 4;
	  Get_First_Last_Track_CDD_c24 ();
	  break;

	case 0x5:		// get track addresse (MSF format)
	  CDD.Status = (CDD.Status & 0xFF00) | 5;
	  Get_Track_Adr_CDD_c25 ();
	  break;

	default:		// invalid, then we return status
	  CDD.Status = (CDD.Status & 0xFF00) | 0xF;
	  Get_Status_CDD_c0 ();
	  break;
	}
      break;

    case 0x3:			// READ
      Play_CDD_c3 ();
      break;

    case 0x4:			// SEEK
      Seek_CDD_c4 ();
      break;

    case 0x6:			// PAUSE/STOP
      Pause_CDD_c6 ();
      break;

    case 0x7:			// RESUME
      Resume_CDD_c7 ();
      break;

    case 0x8:			// FAST FOWARD
      Fast_Foward_CDD_c8 ();
      break;

    case 0x9:			// FAST REWIND
      Fast_Rewind_CDD_c9 ();
      break;

    case 0xA:			// RECOVER INITIAL STATE (?)
      CDD_cA ();
      break;

    case 0xC:			// CLOSE TRAY
      Close_Tray_CDD_cC ();
      break;

    case 0xD:			// OPEN TRAY
      Open_Tray_CDD_cD ();
      break;

    default:
      // UNKNOW
      CDD_Def ();
      break;
    }
}


unsigned char
SCD_Read_Byte (unsigned int Adr)
{

#ifdef DEBUG_CD
  fprintf (debug_SCD_file, "SCD read (B), address = %.8X\n", Adr);
#endif

  return 0;
}


unsigned short
SCD_Read_Word (unsigned int Adr)
{

#ifdef DEBUG_CD
  fprintf (debug_SCD_file, "SCD read (W), address = %.8X\n", Adr);
#endif

  return 0;
}




void
debug_truc (unsigned int val)
{
#ifdef DEBUG_CD
  fprintf (debug_SCD_file, "ebx = %.8X\n", val);
#endif
}

unsigned short _Read_CDC_Host_SUB (void)
  __attribute__ ((alias ("Read_CDC_Host_SUB")));
unsigned short _Read_CDC_Host_MAIN (void)
  __attribute__ ((alias ("Read_CDC_Host_MAIN")));
unsigned char _CDC_Read_Reg (void) __attribute__ ((alias ("CDC_Read_Reg")));
void _CDC_Write_Reg (unsigned char Data)
  __attribute__ ((alias ("CDC_Write_Reg")));
void _CDD_Processing (void) __attribute__ ((alias ("CDD_Processing")));
void _CDD_Import_Command (void)
  __attribute__ ((alias ("CDD_Import_Command")));
unsigned char _SCD_Read_Byte (unsigned int Adr)
  __attribute__ ((alias ("SCD_Read_Byte")));
unsigned char _SCD_Read_Word (unsigned int Adr)
  __attribute__ ((alias ("SCD_Read_Word")));
