/*
 * EERAM48L512.c
 *
 *  Created on: Dec 4, 2020
 *      Author: Ondra
 */

#include "stm32f4xx_hal.h"
#include "EERAM48L512.h"



/*
 *  Functions
 */
void		EERAM_Init(spieeram_t* param, SPI_HandleTypeDef* hspi, GPIO_TypeDef* CSPort, uint16_t CSPin){
	//inicializuje promene knihovny
	param->hspi=*hspi;
	param->gpioPort=CSPort;
	param->gpioPin=CSPin;
}

static EERAM_Status	WaitToReady(spieeram_t* param){
	//cte status registr a ceka dokud neni nulovy priznak BUSY, max. 10ms, pri timeoutu vraci EERAM_ERROR
	uint8_t				command=RDSR,regVal;
	uint32_t			time;
	EERAM_Status		status=EERAM_OK;
	HAL_GPIO_WritePin(param->gpioPort, param->gpioPin, 0);
	if(HAL_SPI_Transmit(&param->hspi, &command, 1, SPITIMEOUT)!=HAL_OK){
		status=EERAM_ERROR;
		goto ErrorExit;
	}
	time=HAL_GetTick()+	MAXWAITTIME;	//cekani max. po definovany cas
	do{
		if(HAL_SPI_Receive(&param->hspi, &regVal, 1, SPITIMEOUT)!=HAL_OK){
			status=EERAM_ERROR;
			goto ErrorExit;
		}
		if(time<HAL_GetTick()){
			status=EERAM_ERROR;
			goto ErrorExit;
		}
	}while((regVal&1U)!=0);
ErrorExit:
	HAL_GPIO_WritePin(param->gpioPort, param->gpioPin, 1);
	return status;
}


EERAM_Status	EERAM_ReadStatus(spieeram_t* param, uint8_t* regVal){
	//precte hodnotu Status registru pameti
	uint8_t				command=RDSR;
	EERAM_Status		status=EERAM_OK;
	HAL_GPIO_WritePin(param->gpioPort, param->gpioPin, 0);
	if(HAL_SPI_Transmit(&param->hspi, &command, 1, SPITIMEOUT)!=HAL_OK){
		status=EERAM_ERROR;
		goto ErrorExit;
	}
	if(HAL_SPI_Receive(&param->hspi, regVal, 1, SPITIMEOUT)!=HAL_OK){
		status=EERAM_ERROR;
	}
ErrorExit:
	HAL_GPIO_WritePin(param->gpioPort, param->gpioPin, 1);
	return status;
}

EERAM_Status	EERAM_WriteStatus(spieeram_t* param, uint8_t regVal){
	//zapise hodnotu Status registru pameti, pozor na bit povoleni/zakazani zapisu!!
	uint8_t				command=WRSR;
	EERAM_Status		status=EERAM_OK;
	if(EERAM_WriteEnable(param)!=EERAM_OK){		//povoleni zapisu
		return EERAM_ERROR;
	}
	HAL_GPIO_WritePin(param->gpioPort, param->gpioPin, 0);
	if(HAL_SPI_Transmit(&param->hspi, &command, 1, SPITIMEOUT)!=HAL_OK){
		status=EERAM_ERROR;
		goto ErrorExit;
	}
	regVal=regVal & 0b01001110;	//maskovani R-o a Reserved bitu
	if(HAL_SPI_Transmit(&param->hspi, &regVal, 1, SPITIMEOUT)!=HAL_OK){
		status=EERAM_ERROR;
	}
ErrorExit:
	HAL_GPIO_WritePin(param->gpioPort, param->gpioPin, 1);
	//nepouzijeme Write Disable, protoze by modifikoval jiz zapsany bit registru
	return status;
}


EERAM_Status	EERAM_WriteEnable(spieeram_t* param){
	//povoli zapis do pameti
	uint8_t				command=WREN;
	EERAM_Status		status=EERAM_OK;
	status=WaitToReady(param);
	if(status!=EERAM_OK){
		return EERAM_ERROR;
	}
	HAL_GPIO_WritePin(param->gpioPort, param->gpioPin, 0);
	if(HAL_SPI_Transmit(&param->hspi, &command, 1, SPITIMEOUT)!=HAL_OK){
		status=EERAM_ERROR;
	}
	HAL_GPIO_WritePin(param->gpioPort, param->gpioPin, 1);
	return status;
}


EERAM_Status	EERAM_WriteDisable(spieeram_t* param){
	//zakaze zapis do pameti
	uint8_t				command=WRDI;
	EERAM_Status		status=EERAM_OK;
	status=WaitToReady(param);
	if(status!=EERAM_OK){
		return EERAM_ERROR;
	}
	HAL_GPIO_WritePin(param->gpioPort, param->gpioPin, 0);
	if(HAL_SPI_Transmit(&param->hspi, &command, 1, SPITIMEOUT)!=HAL_OK){
		status=EERAM_ERROR;
	}
	HAL_GPIO_WritePin(param->gpioPort, param->gpioPin, 1);
	return status;
}


EERAM_Status	EERAM_ReadData(spieeram_t* param, uint8_t* buff, uint16_t adress, uint16_t bytes){
	//precte dany pocet byte od adresy do bufferu (cca 3ms/kB, clk=20MHz)
	uint8_t				command=READ;
	uint8_t				start[3];
	EERAM_Status		status=EERAM_OK;
	if(WaitToReady(param)!=EERAM_OK){		//je pamet ready?
		return EERAM_ERROR;
	}
	HAL_GPIO_WritePin(param->gpioPort, param->gpioPin, 0);
	start[0]=command;				//zahajeni cteni, command + MSB adr + LSB adr
	start[1]=(uint8_t)adress>>8;
	start[2]=(uint8_t)adress;
	if(HAL_SPI_Transmit(&param->hspi, start, 3, SPITIMEOUT)!=HAL_OK){
		status=EERAM_ERROR;
		goto ErrorEnd;
	}
	if(HAL_SPI_Receive(&param->hspi, buff, bytes, SPITIMEOUT)!=HAL_OK){	// cteni dat
		status=EERAM_ERROR;
	}
ErrorEnd:
	HAL_GPIO_WritePin(param->gpioPort, param->gpioPin, 1);	//konec cteni
	return status;
}


EERAM_Status	EERAM_WriteData(spieeram_t* param, uint8_t* buff, uint16_t adress, uint16_t bytes){
	//zapise dany pocet byte od adresy z bufferu (cca 3ms/kB, clk=20MHz)
	uint8_t				command=WRITE;
	uint8_t				start[3];
	EERAM_Status		status=EERAM_OK;
	if(EERAM_WriteEnable(param)!=EERAM_OK){		//povoleni zapisu
		return EERAM_ERROR;
	}
	HAL_GPIO_WritePin(param->gpioPort, param->gpioPin, 0);
	start[0]=command;				//zahajeni zapisu, command + MSB adr + LSB adr
	start[1]=(uint8_t)adress>>8;
	start[2]=(uint8_t)adress;
	if(HAL_SPI_Transmit(&param->hspi, start, 3, SPITIMEOUT)!=HAL_OK){
		status=EERAM_ERROR;
		goto ErrorEnd;
	}
	if(HAL_SPI_Transmit(&param->hspi, buff, bytes, SPITIMEOUT)!=HAL_OK){	// zapis dat
		status=EERAM_ERROR;
		goto ErrorEnd;
	}
ErrorEnd:
	HAL_GPIO_WritePin(param->gpioPort, param->gpioPin, 1);	//konec zapisu
	if(EERAM_WriteDisable(param)!=EERAM_OK){				//zakazani zapisu
		status=EERAM_ERROR;
	}
	return status;
}




EERAM_Status	EERAM_ReadUserArea(spieeram_t* param, uint8_t* buff){
	//precte 16byte z NV uzivatelske oblasti do bufferu
	uint8_t				command=RDNUR;
	EERAM_Status		status=EERAM_OK;
	if(WaitToReady(param)!=EERAM_OK){		//je pamet ready?
		return EERAM_ERROR;
	}
	HAL_GPIO_WritePin(param->gpioPort, param->gpioPin, 0);
	if(HAL_SPI_Transmit(&param->hspi, &command, 1, SPITIMEOUT)!=HAL_OK){
		status=EERAM_ERROR;
		goto ErrorEnd;
	}
	if(HAL_SPI_Receive(&param->hspi, buff, 16, SPITIMEOUT)!=HAL_OK){	// cteni dat
		status=EERAM_ERROR;
	}
ErrorEnd:
	HAL_GPIO_WritePin(param->gpioPort, param->gpioPin, 1);	//konec cteni
	return status;
}


EERAM_Status	EERAM_WriteUserArea(spieeram_t* param, uint8_t* buff){
	//zapise 16byte z bufferu do NV uzivatelske oblasti
	uint8_t				command=WRNUR;
	EERAM_Status		status=EERAM_OK;
	if(EERAM_WriteEnable(param)!=EERAM_OK){		//povoleni zapisu
		return EERAM_ERROR;
	}
	HAL_GPIO_WritePin(param->gpioPort, param->gpioPin, 0);
	if(HAL_SPI_Transmit(&param->hspi, &command, 1, SPITIMEOUT)!=HAL_OK){
		status=EERAM_ERROR;
		goto ErrorEnd;
	}
	if(HAL_SPI_Transmit(&param->hspi, buff, 16, SPITIMEOUT)!=HAL_OK){	// zapis dat
		status=EERAM_ERROR;
	}
ErrorEnd:
	HAL_GPIO_WritePin(param->gpioPort, param->gpioPin, 1);	//konec cteni
	if(EERAM_WriteDisable(param)!=EERAM_OK){				//zakazani zapisu
		status=EERAM_ERROR;
	}
	return status;
}




