#include <Arduino.h>
#include <SPI.h>
#include "spieeprom.h"


SPIEEPROM::SPIEEPROM()
{
	eepromType = EEPROM_TYPE_16BIT;
	address = 0;
	csPin = CS_PIN_DEFAULT;
}

SPIEEPROM::SPIEEPROM(byte type, int cs, SPIClass* spi)
{
	if (type > EEPROM_TYPE_24BIT)
	{
		// select default type
		eepromType = EEPROM_TYPE_16BIT;
	}
	else
	{
		eepromType = type;
	}
	address = 0;
	csPin = cs;
	mySPI = spi;
}

void SPIEEPROM::setup()
{
	pinMode(csPin, OUTPUT);

	//SPI.begin(SCK, MISO, MOSI, SS);

	mySPI->setHwCs(1);
	mySPI->setBitOrder(SPI_MSBFIRST);
	mySPI->setDataMode(SPI_MODE0);
	mySPI->setFrequency(1000000);
	mySPI->begin(36, 37, 35, SS);


}

void SPIEEPROM::sendAddress(uint16_t addr)
{

	if (eepromType == EEPROM_TYPE_24BIT)
	{
		mySPI->transfer((byte)(addr >> 16));
	}
	mySPI->transfer((byte)(addr >> 8));
	mySPI->transfer((byte)(addr));
}

void SPIEEPROM::startWrite()
{
	digitalWrite(csPin, LOW);
	mySPI->transfer(WREN); //send WREN command
	digitalWrite(csPin, HIGH);
	digitalWrite(csPin, LOW);
	mySPI->transfer(WRITE); //send WRITE command
}

byte SPIEEPROM::getStatus()
{

	byte data;

	digitalWrite(csPin, LOW);
	mySPI->transfer(RDSR); // send RDSR command
	data = mySPI->transfer(0xFF);
	digitalWrite(csPin, HIGH);

	return data;
}

bool SPIEEPROM::isWIP()
{
	byte data;

	digitalWrite(csPin, LOW);
	mySPI->transfer(RDSR); // send RDSR command

	data = mySPI->transfer(0xFF); //get data byte

	digitalWrite(csPin, HIGH);

	return (data & (1 << 0));
}

void SPIEEPROM::write(uint16_t addr, byte data)
{
	startWrite();

	sendAddress(addr); // send address
	mySPI->transfer(data); // transfer data

	digitalWrite(csPin, HIGH);

	while (isWIP())
	{
		delay(1);
	}
}

void SPIEEPROM::write(uint16_t addr, byte data[], int arrLength)
{
	startWrite();

	sendAddress(addr); // send address

	if (arrLength > 64)
	{
		return;
	}

	for (int i = 0; i < arrLength; i++)
	{
		mySPI->transfer(data[i]); // transfer data
	}

	digitalWrite(csPin, HIGH);
	while (isWIP())
	{
		delay(1);
	}
}

byte SPIEEPROM::readByte(uint16_t addr)
{
	byte data;

	digitalWrite(csPin, LOW);
	mySPI->transfer(READ); // send READ command

	sendAddress(addr);		   // send address
	data = mySPI->transfer(0xFF); //get data byte

	digitalWrite(csPin, HIGH); //release chip, signal end transfer

	return data;
}

void SPIEEPROM::readByteArray(uint16_t addr, byte data[], int arrLength)
{

	digitalWrite(csPin, LOW);
	mySPI->transfer(READ); // send READ command

	sendAddress(addr);		   // send address
	for (int i = 0; i < arrLength; i++)
	{
		// the EEPROM chip has an internal counter and will continue sending the
		// next bytes
		data[i] = mySPI->transfer(0xFF); //get data byte
	}

	digitalWrite(csPin, HIGH); //release chip, signal end transfer
}
