#define _SUPPRESS_PLIB_WARNING 1
#include "delay.h"
#include "EEPROM.h"
#include "control.h"
#include "KS0108-PIC16.h"
#include "KS0108.h"


/********************************************************************
*     Function Name:    EEPROM_Init                              *
*     Parameters:                                                   *
*     Description:      Initialises EEPROM                          *
*                                                                   *
********************************************************************/
unsigned char EEPROM_Init()
{
  EEPROM_Disable_Hold;
  EEPROM_ChipSelect_Assert;                     // Select Device
  DelayUs(EEPROM_INIT_DELAY);
  EEPROM_ChipSelect_DeAssert;                   // Deselect Device
  DelayUs(EEPROM_INIT_DELAY);
  EEPROM_ChipSelect_Assert;                     // Select Device
  DelayUs(EEPROM_INIT_DELAY);
  EEPROM_ChipSelect_DeAssert;  
  DelayUs(EEPROM_INIT_DELAY);
  EEPROM_ChipSelect_Assert;                     // Select Device
  DelayUs(EEPROM_INIT_DELAY);
  EEPROM_ChipSelect_DeAssert;                   // Deselect Device
}


/********************************************************************
*     Function Name:    WriteEnable                                 *
*     Return Value:     void                                        *
*     Parameters:       void                                        *
*     Description:      This routine sets the Write Enable Latch    *
********************************************************************/
void WriteEnable(void)
{
    EEPROM_ChipSelect_Assert;                   //Select Device
    PLIB_SPI_WRITE_C (EEPROM_SPI_Port, EEPROM_WREN );   //Write Enable OpCode
    PLIB_SPI_BufferRead(EEPROM_SPI_Port);   /* clear the read buffer */
    EEPROM_ChipSelect_DeAssert;                   //Deselect Device
    DelayUs(1);
    EEPROM_ChipSelect_Assert;                   //Select Device
    PLIB_SPI_WRITE_C (EEPROM_SPI_Port, EEPROM_WRITESTAT );   //Write Enable OpCode
    PLIB_SPI_BufferRead(EEPROM_SPI_Port);   /* clear the read buffer */
    EEPROM_ChipSelect_DeAssert;                   //Deselect Device
    DelayUs(1);}


/********************************************************************
*     Function Name:    LDByteWriteSPI                              *
*     Parameters:       EE memory control, address and pointer 1    *
*     Description:      Writes Data Byte to SPI EE memory device    *
*                       This routine can be used for any SPI        *
*                       EE memory device with 1 byte of address.    *
*                                                                   *
********************************************************************/
unsigned char LDByteWriteSPI(unsigned char LowAdd, unsigned char Data )
{
  WriteEnable();                      // Write Enable prior to Write
  ReadStatus();                       // Check for WEL bit set
  EEPROM_ChipSelect_Assert;                     // Select Device
  PLIB_SPI_WRITE_C (EEPROM_SPI_Port, EEPROM_WRITE_BYTE );    // Send Write OpCode
  PLIB_SPI_BufferRead(EEPROM_SPI_Port);   /* clear the read buffer */
  PLIB_SPI_WRITE_C (EEPROM_SPI_Port, LowAdd );               // write address byte to EEPROM
  PLIB_SPI_BufferRead(EEPROM_SPI_Port);   /* clear the read buffer */
  PLIB_SPI_WRITE_C (EEPROM_SPI_Port, Data );                 // Write Byte to device
  PLIB_SPI_BufferRead(EEPROM_SPI_Port);   /* clear the read buffer */
  EEPROM_ChipSelect_DeAssert;                     // Deselect device and initiate Write
  SPIWIPPolling();                    // Wait for Write to complete
  SPI1STATbits.SPITBF = 0;
  return ( 0 );
}

/********************************************************************
*     Function Name:    LDByteReadSPI                               *
*     Parameters:       EE memory control, address, pointer and     *
*                       length bytes.                               *
*     Description:      Reads data Byte from SPI EE memory device.  *
*                       This routine can be used for any SPI        *
*                       EE memory device with 1 byte of address     *
*                                                                   *
********************************************************************/
unsigned char LDByteReadSPI(unsigned char LowAdd, unsigned char *rdptr, unsigned char length )
{
  EEPROM_ChipSelect_Assert;                     // Select Device
  PLIB_SPI_WRITE_C (EEPROM_SPI_Port, EEPROM_READ_BYTE );  // Send Read OpCode
  PLIB_SPI_BufferRead(EEPROM_SPI_Port);   /* clear the read buffer */
  PLIB_SPI_WRITE_C (EEPROM_SPI_Port, LowAdd );            // WRITE word address to EEPROM
  PLIB_SPI_BufferRead(EEPROM_SPI_Port);   /* clear the read buffer */
  getsSPI( rdptr, length );      // read in multiple bytes
  EEPROM_ChipSelect_DeAssert;                     // Deselect Device
  return ( 0 );
}

/********************************************************************
*     Function Name:    LDPageWriteSPI                              *
*     Parameters:       EE memory control, address and pointer 1    *
*     Description:      Writes data string to SPI EE memory         *
*                       device. This routine can be used for any SPI*
*                       EE memory device with 1 byte of address.    *
*                                                                   *
********************************************************************/
unsigned char LDPageWriteSPI( unsigned char LowAdd, unsigned char *wrptr )
{
  WriteEnable();                      // Write Enable prior to Write
  ReadStatus();                       // Check for WEL bit set
  EEPROM_ChipSelect_Assert;                     // Select Device
  PLIB_SPI_WRITE_C (EEPROM_SPI_Port, EEPROM_WRITE_BYTE );    // send Write OpCode
  PLIB_SPI_BufferRead(EEPROM_SPI_Port);   /* clear the read buffer */
  PLIB_SPI_WRITE_C (EEPROM_SPI_Port, LowAdd );    // write address byte to EEPROM
  PLIB_SPI_BufferRead(EEPROM_SPI_Port);   /* clear the read buffer */
  PutStringSPI ( wrptr );             // Write Page to device
  EEPROM_ChipSelect_DeAssert;                     // Deselect Device
  SPIWIPPolling();                    // Wait for Write to Complete
  SPI1STATbits.SPITBF = 0;
  return ( 0 );
}

/********************************************************************
*     Function Name:    LDSequentialReadSPI                         *
*     Parameters:       EE memory control, address, pointer and     *
*                       length bytes.                               *
*     Description:      Reads data string from SPI EE memory        *
*                       device. This routine can be used for any SPI*
*                       EE memory device with 1 byte of address.    *
*                                                                   *
********************************************************************/
unsigned char LDSequentialReadSPI( unsigned char LowAdd, unsigned char *rdptr, unsigned char length )
{
  EEPROM_ChipSelect_Assert;                     // Select Device
  PLIB_SPI_WRITE_C (EEPROM_SPI_Port, EEPROM_READ_BYTE );      // Send Read OpCode
  PLIB_SPI_BufferRead(EEPROM_SPI_Port);   /* clear the read buffer */
  PLIB_SPI_WRITE_C (EEPROM_SPI_Port, LowAdd );                // WRITE word address to EEPROM
  PLIB_SPI_BufferRead(EEPROM_SPI_Port);   /* clear the read buffer */
  getsSPI( rdptr, length );           // read in multiple bytes
  EEPROM_ChipSelect_DeAssert;                     // Deselect Device
  return ( 0 );
}

/********************************************************************
*     Function Name:    HDByteWriteSPI                              *
*     Parameters:       EE memory control, address and pointer 1    *
*     Description:      Writes data string to SPI EE memory         *
*                       device. This routine can be used for any SPI*
*                       EE memory device with two address bytes.    *
*                                                                   *
********************************************************************/
unsigned char HDByteWriteSPI(unsigned char HighAdd, unsigned char LowAdd, unsigned char Data )
{
    
  WriteEnable();                      // Write Enable prior to Write
  ReadStatus();                       // Check for WEL bit set
  EEPROM_ChipSelect_Assert;                     // Select Device
  PLIB_SPI_WRITE_C (EEPROM_SPI_Port, EEPROM_WRITE_BYTE );    // Send Write OpCode
  PLIB_SPI_BufferRead(EEPROM_SPI_Port);   /* clear the read buffer */
  PLIB_SPI_WRITE_C (EEPROM_SPI_Port, HighAdd);  // Send High Address Byte
  PLIB_SPI_BufferRead(EEPROM_SPI_Port);   /* clear the read buffer */
  PLIB_SPI_WRITE_C (EEPROM_SPI_Port, LowAdd );  // write address byte to EEPROM
  PLIB_SPI_BufferRead(EEPROM_SPI_Port);   /* clear the read buffer */
  PLIB_SPI_WRITE_C (EEPROM_SPI_Port, Data );    // Write Byte to device
  PLIB_SPI_BufferRead(EEPROM_SPI_Port);   /* clear the read buffer */
  EEPROM_ChipSelect_DeAssert;                         // Deselect Device
  SPIWIPPolling();                    // Wait for Write to Complete
  return ( 0 );
}

/********************************************************************
*     Function Name:    HDWordWriteSPI                              *
*     Parameters:       EE memory control, address and pointer 1    *
*     Description:      Writes data string to SPI EE memory         *
*                       device. This routine can be used for any SPI*
*                       EE memory device with two address bytes.    *
*                                                                   *
********************************************************************/
unsigned char HDWordWriteSPI(unsigned int Add, unsigned int Data )
{
  WriteEnable();                      // Write Enable prior to Write
  ReadStatus();                       // Check for WEL bit set
  EEPROM_ChipSelect_Assert;                     // Select Device
  PLIB_SPI_WRITE_C (EEPROM_SPI_Port, EEPROM_WRITE_BYTE );    // Send Write OpCode
  PLIB_SPI_BufferRead(EEPROM_SPI_Port);   /* clear the read buffer */
  PLIB_SPI_WRITE_C (EEPROM_SPI_Port, (char)((Add>>8) & 0xFF));  // Send High Address Byte
  PLIB_SPI_BufferRead(EEPROM_SPI_Port);   /* clear the read buffer */
  PLIB_SPI_WRITE_C (EEPROM_SPI_Port, (char)(Add & 0xFF));  // write address byte to EEPROM
  PLIB_SPI_BufferRead(EEPROM_SPI_Port);   /* clear the read buffer */
  PLIB_SPI_WRITE_C (EEPROM_SPI_Port, (char)((Data) & 0xFF));    // Write Byte to device
  PLIB_SPI_BufferRead(EEPROM_SPI_Port);   /* clear the read buffer */
  PLIB_SPI_WRITE_C (EEPROM_SPI_Port, (char)((Data>>8) & 0xFF));    // Write Byte to device
  PLIB_SPI_BufferRead(EEPROM_SPI_Port);   /* clear the read buffer */
  PLIB_SPI_WRITE_C (EEPROM_SPI_Port, (char)((Data>>16) & 0xFF));    // Write Byte to device
  PLIB_SPI_BufferRead(EEPROM_SPI_Port);   /* clear the read buffer */
  PLIB_SPI_WRITE_C (EEPROM_SPI_Port, (char)((Data>>24) & 0xFF));    // Write Byte to device
  PLIB_SPI_BufferRead(EEPROM_SPI_Port);   /* clear the read buffer */
  EEPROM_ChipSelect_DeAssert;                         // Deselect Device
  SPIWIPPolling();                    // Wait for Write to Complete
  return ( 0 );
}


/********************************************************************
*     Function Name:    HDByteReadSPI                               *
*     Parameters:       EE memory control, address, pointer and     *
*                       length bytes.                               *
*     Description:      Reads data string from SPI EE memory        *
*                       device. This routine can be used for any SPI*
*                       EE memory device with two address bytes.    *
*                                                                   *
********************************************************************/
unsigned char HDByteReadSPI(unsigned char HighAdd, unsigned char LowAdd, unsigned char *rdptr, unsigned char length )
{
  EEPROM_ChipSelect_Assert;                     // Select Device
  PLIB_SPI_WRITE_C (EEPROM_SPI_Port, EEPROM_READ_BYTE );      // Send Read OpCode
  PLIB_SPI_BufferRead(EEPROM_SPI_Port);   /* clear the read buffer */
  PLIB_SPI_WRITE_C (EEPROM_SPI_Port, HighAdd);                // Send High Address Byte
  PLIB_SPI_BufferRead(EEPROM_SPI_Port);   /* clear the read buffer */
  PLIB_SPI_WRITE_C (EEPROM_SPI_Port, LowAdd );                // WRITE word address to EEPROM
  PLIB_SPI_BufferRead(EEPROM_SPI_Port);   /* clear the read buffer */
  getsSPI( rdptr, length );           // read in multiple bytes
  EEPROM_ChipSelect_DeAssert;                     // Deselect Device
  return ( 0 );                       // return with no error
}



/********************************************************************
*     Function Name:    HDWordReadSPI                               *
*     Parameters:       EE memory control, address, pointer and     *
*                       length bytes.                               *
*     Description:      Reads data string from SPI EE memory        *
*                       device. This routine can be used for any SPI*
*                       EE memory device with two address bytes.    *
*                                                                   *
********************************************************************/
unsigned char HDWordReadSPI(unsigned int Add, int *rdptr, unsigned char length )
{
  EEPROM_ChipSelect_Assert;                     // Select Device
  PLIB_SPI_WRITE_C (EEPROM_SPI_Port, EEPROM_READ_BYTE );     // Send Read OpCode
  PLIB_SPI_BufferRead(EEPROM_SPI_Port);   /* clear the read buffer */
  PLIB_SPI_WRITE_C (EEPROM_SPI_Port, (char)((Add >> 8) & 0xFF));   // Send High Address Byte
  PLIB_SPI_BufferRead(EEPROM_SPI_Port);   /* clear the read buffer */
  PLIB_SPI_WRITE_C (EEPROM_SPI_Port, (char)((Add) & 0xFF));        // WRITE word address to EEPROM
  PLIB_SPI_BufferRead(EEPROM_SPI_Port);   /* clear the read buffer */
  getsSPI((char *)rdptr, length );           // read in multiple bytes
  EEPROM_ChipSelect_DeAssert;                     // Deselect Device
  return ( 0 );                       // return with no error
}



/********************************************************************
*     Function Name:    HDPageWriteSPI                              *
*     Return Value:     error condition status                      *
*     Parameters:       EE memory control, address and pointer 1    *
*     Description:      Writes data string to SPI EE memory         *
*                       device. This routine can be used for any SPI*
*                       EE memory device with two address bytes.    *
*                                                                   *
********************************************************************/
unsigned char HDPageWriteSPI( unsigned char HighAdd, unsigned char LowAdd, unsigned char *wrptr )
{
  WriteEnable();                      // Write Enable prior to Write
  ReadStatus();                       // Check for WEL bit set
  EEPROM_ChipSelect_Assert;                     // Select Device
  PLIB_SPI_WRITE_C (EEPROM_SPI_Port, EEPROM_WRITE_BYTE );    // send Write OpCode
  PLIB_SPI_BufferRead(EEPROM_SPI_Port);   /* clear the read buffer */
  PLIB_SPI_WRITE_C (EEPROM_SPI_Port, HighAdd);               // Send High Address Byte
  PLIB_SPI_BufferRead(EEPROM_SPI_Port);   /* clear the read buffer */
  PLIB_SPI_WRITE_C (EEPROM_SPI_Port, LowAdd );               // write address byte to EEPROM
  PLIB_SPI_BufferRead(EEPROM_SPI_Port);   /* clear the read buffer */
  PutStringSPI ( wrptr );             // Write Page to device
  EEPROM_ChipSelect_DeAssert;                     // Deselect Device
  SPIWIPPolling();                    // Wait for Write to Complete
  return ( 0 );
}

unsigned char MegaHDPageWriteSPI( unsigned char HigherAdd, unsigned char HighAdd, unsigned char LowAdd, unsigned char *wrptr )
{
  WriteEnable();                      // Write Enable prior to Write
  ReadStatus();                       // Check for WEL bit set
  EEPROM_ChipSelect_Assert;                     // Select Device
  PLIB_SPI_WRITE_C (EEPROM_SPI_Port, EEPROM_WRITE_BYTE );    // send Write OpCode
  PLIB_SPI_BufferRead(EEPROM_SPI_Port);
//  getcSPI1();
  PLIB_SPI_WRITE_C (EEPROM_SPI_Port, HigherAdd );
  PLIB_SPI_BufferRead(EEPROM_SPI_Port);
  PLIB_SPI_WRITE_C (EEPROM_SPI_Port, HighAdd);               // Send High Address Byte
  PLIB_SPI_BufferRead(EEPROM_SPI_Port);
  PLIB_SPI_WRITE_C (EEPROM_SPI_Port, LowAdd );               // write address byte to EEPROM
  PLIB_SPI_BufferRead(EEPROM_SPI_Port);
  PutStringSPI ( wrptr );             // Write Page to device
  EEPROM_ChipSelect_DeAssert;                             // Deselect Device
  SPIWIPPolling();                    // Wait for Write to Complete
  return ( 0 );
}

/********************************************************************
*     Function Name:    HDSequentialReadSPI                         *
*     Parameters:       EE memory control, address, pointer and     *
*                       length bytes.                               *
*     Description:      Reads data string from SPI EE memory        *
*                       device. This routine can be used for any SPI*
*                       EE memory device with two address bytes.    *
*                                                                   *
********************************************************************/
unsigned char HDSequentialReadSPI( unsigned char HighAdd, unsigned char LowAdd, unsigned char *rdptr, unsigned char length )
{
  EEPROM_ChipSelect_Assert;                     // Select Device
  PLIB_SPI_WRITE_C (EEPROM_SPI_Port, EEPROM_READ_BYTE );      // Send Read OpCode
  PLIB_SPI_BufferRead(EEPROM_SPI_Port);
  PLIB_SPI_WRITE_C (EEPROM_SPI_Port, HighAdd);        // Send High Address Byte
  PLIB_SPI_BufferRead(EEPROM_SPI_Port);
  PLIB_SPI_WRITE_C (EEPROM_SPI_Port, LowAdd );        // WRITE word address to EEPROM
  PLIB_SPI_BufferRead(EEPROM_SPI_Port);
  getsSPI( rdptr,length );                    // read in multiple bytes
  EEPROM_ChipSelect_DeAssert;                     // Deselect Device
  return ( 0 );
}


/********************************************************************
*     Function Name:    SPIWIPPolling                               *
*     Return Value:     void                                        *
*     Parameters:       void                                        *
*     Description:      This routine loops until WIP = 0            *
********************************************************************/

void SPIWIPPolling(void)
{
  unsigned char Status;
  do
  {
    EEPROM_ChipSelect_Assert;                   //Select Device
    PLIB_SPI_WRITE_C (EEPROM_SPI_Port, EEPROM_READSTAT );    //Read Status Reg OpCode
    PLIB_SPI_BufferRead(EEPROM_SPI_Port);
    PLIB_SPI_WRITE_C (EEPROM_SPI_Port, 0x00 );        //Write dummy data to SPI
    Status = PLIB_SPI_BufferRead(EEPROM_SPI_Port);
    EEPROM_ChipSelect_DeAssert;                   //Deselect Device
  } while (Status & 0x01);            //Check for WIP bit Set
}


/********************************************************************
*     Function Name:    PutStringSPI                                *
*     Return Value:     void                                        *
*     Parameters:       address of write string storage location    *
*     Description:      This routine writes a string to the SPI bus.*
********************************************************************/

unsigned char PutStringSPI( unsigned char *wrptr )
{
  unsigned int x;
  for (x = 0; x < PageSize; x++ )     // transmit data until PageSize
  {
     SPI1BUF = *wrptr++;               // initiate SPI bus cycle
     while( !SPI1STATbits.SPITBF );        // wait until 'BF' bit is set
  }
  return ( 0 );
}


/********************************************************************
*     Function Name:    Read Status                                 *
*     Return Value:     void                                        *
*     Parameters:       void                                        *
*     Description:      This routine reads the Status Register      *
********************************************************************/
void ReadStatus(void)
{
    EEPROM_ChipSelect_Assert;                             //Select Device
    PLIB_SPI_WRITE_C (EEPROM_SPI_Port, EEPROM_READSTAT ); //Read Status Register OpCode
    PLIB_SPI_BufferRead(EEPROM_SPI_Port);
    PLIB_SPI_WRITE_C (EEPROM_SPI_Port, 0x00 );        //Write dummy data to SPI
    PLIB_SPI_BufferRead(EEPROM_SPI_Port);
    EEPROM_ChipSelect_DeAssert;                             //Deselect Device
}


/********************************************************************
*     Function Name:    getsSPI                                     *
*     Return Value:     void                                        *
*     Parameters:       address of read string storage location and *
*                       length of string bytes to read              *
*     Description:      This routine reads a string from the SPI    *
*                       bus.  The number of bytes to read is deter- *
*                       mined by parameter 'length'.                *
********************************************************************/
void getsSPI( unsigned char *rdptr, unsigned char length )
{
  while ( length )                  // stay in loop until length = 0
  {
      PLIB_SPI_WRITE_C (EEPROM_SPI_Port, 0x00 );        //Write dummy data to SPI
      *rdptr++ =   PLIB_SPI_BufferRead(EEPROM_SPI_Port);   // read a single byte
      length--;                     // reduce string length count by 1
  }
}




/* intiialise EEPROM for read / write */
void InitEEPROM()
{

}
