#include "switch.h"

EthernetSwitch& EthernetSwitch::ZL50409(void)
{
  static EthernetSwitch sw;
  return sw;
}

EthernetSwitch::EthernetSwitch(void)
{
  Pins::LPC2106().SwitchDataOutLow();
  Pins::LPC2106().SwitchStrobeLow();
}

EthernetSwitch::EthernetSwitch(const EthernetSwitch& rhs)
{
  Pins::LPC2106().SwitchDataOutLow();
  Pins::LPC2106().SwitchStrobeLow();
}

void EthernetSwitch::SSI_WriteCommand(unsigned short address, unsigned short data)
{
  unsigned char device  = 0;
  unsigned char regaddr = (address & 7); 

  SSI_Start();
  
  for (int i = 0; i < 3; i++)
    SSI_Write((device >> i) & 1);
  
  for (int i = 0; i < 3; i++)
    SSI_Write((regaddr >> i) & 1);  
    
  // Issue Write Command
  SSI_Write_One();
  
  // Send 16 bit data
  for (int i = 0; i < 16; i++)
    SSI_Write((data >> i) & 1);
    
  // Generate two trailing clocks
  Pins::LPC2106().SwitchStrobeHigh();
  Pins::LPC2106().SwitchStrobeLow(); 
  Pins::LPC2106().SwitchStrobeHigh();
  Pins::LPC2106().SwitchStrobeLow(); 
}

unsigned short EthernetSwitch::SSI_ReadCommand(unsigned short address)
{
  unsigned char device  = 0;
  unsigned char regaddr = (address & 7); 
  unsigned short data;
  
  SSI_Start();
  
  for (int i = 0; i < 3; i++)
    SSI_Write((device >> i) & 1);
  
  for (int i = 0; i < 3; i++)
    SSI_Write((regaddr >> i) & 1); 
    
  // Issue Read Command
  SSI_Write_Zero(); 
  
  // Send 16 bit data
  data = 0;
  for (int i = 0; i < 16; i++) {
    if (SSI_Read()) data |= 1 << i;
  }    
  return (data);
}

void EthernetSwitch::SSI_Start(void)
{
  Pins::LPC2106().SwitchStrobeLow(); 
  Pins::LPC2106().SwitchDataOutHigh();  
  Pins::LPC2106().SwitchStrobeHigh();
  Pins::LPC2106().SwitchDataOutLow();
  Pins::LPC2106().SwitchStrobeLow(); 
}

void EthernetSwitch::SSI_Abort(void)
{
  Pins::LPC2106().SwitchStrobeLow(); 
  Pins::LPC2106().SwitchDataOutLow();  
  Pins::LPC2106().SwitchStrobeHigh();
  Pins::LPC2106().SwitchDataOutHigh();
  Pins::LPC2106().SwitchStrobeLow(); 
}
    
void EthernetSwitch::SSI_Write(unsigned short bit)
{
  if (bit)
    SSI_Write_One();
  else
    SSI_Write_Zero();
}
    
void EthernetSwitch::SSI_Write_One(void)
{
  Pins::LPC2106().SwitchDataOutHigh();
  Pins::LPC2106().SwitchStrobeHigh();
  Pins::LPC2106().SwitchStrobeLow(); 
}

void EthernetSwitch::SSI_Write_Zero(void)
{
  Pins::LPC2106().SwitchDataOutLow();
  Pins::LPC2106().SwitchStrobeHigh();
  Pins::LPC2106().SwitchStrobeLow();
}

unsigned short EthernetSwitch::SSI_Read(void)
{
  Pins::LPC2106().SwitchStrobeHigh();
  unsigned short data = Pins::LPC2106().GetSwitchDataIn();
  Pins::LPC2106().SwitchStrobeLow();
  return data;
}
