#include "stm32l0xx_hal_conf.h"
#include "stm32l0xx_hal.h"
#include "init.h"
#include "sst26.h"

// #########################################################################################################
void FLASH_Read(uint8_t* pBuffer, uint32_t ReadAddr, uint16_t NumByteToRead)    //pr. volani: FLASH_Read((uint8_t*)&RxFlashData,0x000600,5);
{
    HAL_GPIO_WritePin(CS_FLASH, LOW);
    SPI_TransmitReceive(READ_MEMORY);

    SPI_TransmitReceive((ReadAddr & 0xFF0000) >> 16);          //addr MSB
    SPI_TransmitReceive((ReadAddr& 0xFF00) >> 8);
    SPI_TransmitReceive(ReadAddr & 0xFF);                      //addr LSB

    SPI_ReceiveField(pBuffer, NumByteToRead);           // rychlejsi
    HAL_GPIO_WritePin(CS_FLASH, HIGH); 
};

// #########################################################################################################
void FLASH_Write(uint8_t *pBuffer, uint32_t WriteAddr, uint16_t NumByteToWrite) //pr. volani: FLASH_Write((uint8_t *)&FlashData,0x000600, 5);  
{
    HAL_GPIO_WritePin(CS_FLASH, LOW); 
    SPI_TransmitReceive(WRITE_ENABLE);
    HAL_GPIO_WritePin(CS_FLASH, HIGH);
    
    HAL_GPIO_WritePin(CS_FLASH, LOW);   
    SPI_TransmitReceive(PAGE_PROGRAM); 

    SPI_TransmitReceive((WriteAddr & 0xFF0000) >> 16);          //addr MSB
    SPI_TransmitReceive((WriteAddr& 0xFF00) >> 8);
    SPI_TransmitReceive(WriteAddr & 0xFF);                      //addr LSB

    SPI_TransmitField(pBuffer,NumByteToWrite);      // rychlejsi

    HAL_GPIO_WritePin(CS_FLASH, HIGH); 
    
    FLASH_WaitUntilComplete();
};

// #########################################################################################################
void FLASH_WaitUntilComplete(void)
{
    uint8_t tmp = 0;
    HAL_GPIO_WritePin(CS_FLASH, LOW); 
    SPI_TransmitReceive(READ_STATUS_REGISTER);
    tmp = SPI_TransmitReceive(0xFF);
    HAL_GPIO_WritePin(CS_FLASH, HIGH); 
    while(tmp & 0b10000000 )
        {
                HAL_GPIO_WritePin(CS_FLASH, LOW); 
                SPI_TransmitReceive(READ_STATUS_REGISTER);
                tmp = SPI_TransmitReceive(0xFF);
                HAL_GPIO_WritePin(CS_FLASH, HIGH);
        };
};

// #########################################################################################################
void FLASH_Init(void)
{
    HAL_GPIO_WritePin(CS_FLASH, LOW); 
    SPI_TransmitReceive(WRITE_ENABLE); 
    HAL_GPIO_WritePin(CS_FLASH, HIGH); 
      
    HAL_GPIO_WritePin(CS_FLASH, LOW); 
    SPI_TransmitReceive(GLOBAL_BLOCK_PROTECTION_UNLOCK);  
    HAL_GPIO_WritePin(CS_FLASH, HIGH);
};

// #########################################################################################################
void FLASH_ChipErase(void)
{
    HAL_GPIO_WritePin(CS_FLASH, LOW); 
    SPI_TransmitReceive(WRITE_ENABLE);
    HAL_GPIO_WritePin(CS_FLASH, HIGH);   
    
    HAL_GPIO_WritePin(CS_FLASH, LOW); 
    SPI_TransmitReceive(CHIP_ERASE);
    HAL_GPIO_WritePin(CS_FLASH, HIGH); 

    FLASH_WaitUntilComplete();
};

// #########################################################################################################
uint8_t FLASH_ReadStatReg(void)
{
    uint8_t tmp = 0;
    HAL_GPIO_WritePin(CS_FLASH, LOW);                       
    SPI_TransmitReceive(READ_STATUS_REGISTER);
    tmp = SPI_TransmitReceive(0xFF);
    HAL_GPIO_WritePin(CS_FLASH, HIGH);   
    return tmp;
}


















//uint8_t         FLASH_Status0       = 0;
//uint8_t         FLASH_Status        = 0;


/*void FLASH_Init(void)
{
    HAL_GPIO_WritePin(CS_FLASH, LOW);
    HAL_GPIO_WritePin(CS_FLASH, HIGH);
};

void FLASH_Smazani(void)
{
    WREN();
    FLASH_WriteUnlock();
    FLASH_Chip_Erase();
};


void FLASH_WaitForWriteEnd(void)
{
    uint8_t         FLASH_Status0       = 0;
    uint8_t         FLASH_Status        = 0;
    HAL_GPIO_WritePin(CS_FLASH, LOW);
    SPI_TransmitReceive(RDSR);
    FLASH_Status = FLASH_Status0;

    while(FLASH_Status %2 == 1)
        {
            SPI_TransmitReceive(RDSR);
            FLASH_Status = SPI_TransmitReceive(0xFF);
        };
    HAL_GPIO_WritePin(CS_FLASH, HIGH);    
};

void FLASH_Chip_Erase(void)
{
    WREN();
    HAL_GPIO_WritePin(CS_FLASH, LOW);               // CE low
    SPI_TransmitReceive(CHIP_ERASE);
    HAL_GPIO_WritePin(CS_FLASH, HIGH);              // CE high
    FLASH_WaitForWriteEnd();
};

void FLASH_WriteUnlock(void)
{
    WREN();
    HAL_GPIO_WritePin(CS_FLASH, LOW);               // CE low   
    SPI_TransmitReceive(WBPR);
    for(char aux = 0; aux <18; aux++)
        {
        SPI_TransmitReceive(0x00);
        }
    HAL_GPIO_WritePin(CS_FLASH, HIGH);              // CE high
};

void FLASH_BufferRead(uint8_t* pBuffer, uint32_t ReadAddr, uint16_t NumByteToRead)
{
    HAL_GPIO_WritePin(CS_FLASH, LOW);               // CE low   
    SPI_TransmitReceive(READ_MEMORY);

	SPI_TransmitReceive(((ReadAddr & 0xFF0000) >> 16));		
	SPI_TransmitReceive(((ReadAddr& 0xFF00) >> 8));		
	SPI_TransmitReceive((ReadAddr & 0xFF));		

    while(NumByteToRead--)
        {
 		*pBuffer = SPI_TransmitReceive(0x00);
		pBuffer++;       
        }

    HAL_GPIO_WritePin(CS_FLASH, HIGH);              // CE high
};














uint8_t data_256[256] = "1,2,3,4,5";



uint8_t SST26_ReadStatsReg()
{
    uint8_t tmp = 0;
    HAL_GPIO_WritePin(CS_FLASH, LOW);               // CE low
    SPI_TransmitReceive(READ_STATUS_REG);           // odeslat comand
    tmp = SPI_TransmitReceive(0x00);                // precist status reg
    HAL_GPIO_WritePin(CS_FLASH, HIGH);              // CE high
    return tmp;
};


uint8_t SST26_ReadConfigReg()
{
    uint8_t tmp = 0;
    HAL_GPIO_WritePin(CS_FLASH, LOW);               // CE low
    SPI_TransmitReceive(READ_CONFIG_REG);           // odeslat comand
    tmp = SPI_TransmitReceive(0x00);                // precist config reg
    HAL_GPIO_WritePin(CS_FLASH, HIGH);              // CE high
    return tmp;
};


void WREN()
{
    HAL_GPIO_WritePin(CS_FLASH, LOW);               // CE low
    SPI_TransmitReceive(WRITE_ENABLE);              // odeslat comand
    HAL_GPIO_WritePin(CS_FLASH, HIGH);              // CE high
};

void WRDI()
{
    HAL_GPIO_WritePin(CS_FLASH, LOW);               // CE low
    SPI_TransmitReceive(WRITE_DISABLE);             // odeslat comand
    HAL_GPIO_WritePin(CS_FLASH, HIGH);              // CE high
};


void SST26_Sector_Erase(uint8_t ADR1, uint8_t ADR2, uint8_t ADR3)
{
    HAL_GPIO_WritePin(CS_FLASH, LOW);               // CE low
    SPI_TransmitReceive(SECTOR_ERASE);
    SPI_TransmitReceive(ADR1);
    SPI_TransmitReceive(ADR2);
    SPI_TransmitReceive(ADR3);
    HAL_GPIO_WritePin(CS_FLASH, HIGH);              // CE high
};

void SST26_Block_Erase(uint8_t ADR1, uint8_t ADR2, uint8_t ADR3)
{
    HAL_GPIO_WritePin(CS_FLASH, LOW);               // CE low
    SPI_TransmitReceive(BLOCK_ERASE);
    SPI_TransmitReceive(ADR1);
    SPI_TransmitReceive(ADR2);
    SPI_TransmitReceive(ADR3);
    HAL_GPIO_WritePin(CS_FLASH, HIGH);              // CE high
};


uint8_t SST26_ReadByte(uint8_t ADR1, uint8_t ADR2, uint8_t ADR3)
{
    uint8_t tmp;
    HAL_GPIO_WritePin(CS_FLASH, LOW);               // CE low
    SPI_TransmitReceive(READ_MEMORY);               // odeslat comand

    SPI_TransmitReceive(ADR1);                      // odeslat adresu
    SPI_TransmitReceive(ADR2);
    SPI_TransmitReceive(ADR3);

    tmp = SPI_TransmitReceive(0x00);                // cist data
    HAL_GPIO_WritePin(CS_FLASH, HIGH);              // CE high
    return tmp;
};  

	/*
    unsigned long DST;
    Send_Byte(((Dst & 0xFFFFFF) >> 16));	
	Send_Byte(((Dst & 0xFFFF) >> 8));
	Send_Byte(Dst & 0xFF);*/
/*
void SST26_SetBurst(uint8_t burstlength)
{
    HAL_GPIO_WritePin(CS_FLASH, LOW);               // CE low
    SPI_TransmitReceive(SET_BURST);                 // odeslat comand
    SPI_TransmitReceive(burstlength);
    HAL_GPIO_WritePin(CS_FLASH, HIGH);              // CE high
}

void SST26_ReadBurst(uint8_t ADR1, uint8_t ADR2, uint8_t ADR3, uint8_t burstlength)
{
    unsigned int i = 0; 

    HAL_GPIO_WritePin(CS_FLASH, LOW);               // CE low
    SPI_TransmitReceive(READ_BURST);                // odeslat comand

    SPI_TransmitReceive(ADR1);
    SPI_TransmitReceive(ADR2);
    SPI_TransmitReceive(ADR3);

    SPI_TransmitReceive(0xFF);                      // dummy cycle
    SPI_TransmitReceive(0xFF);
    SPI_TransmitReceive(0xFF);

    for(i=0;i<(burstlength);i++)
    {
        data_256[i]=SPI_TransmitReceive(0xFF);
    }

    HAL_GPIO_WritePin(CS_FLASH, HIGH);              // CE high
};


void SST26_Page_Program(uint8_t ADR1, uint8_t ADR2, uint8_t ADR3)
{
    unsigned int i = 0; 
    HAL_GPIO_WritePin(CS_FLASH, LOW);               // CE low
    SPI_TransmitReceive(PAGE_PROGRAM);              // poslat comand

    SPI_TransmitReceive(ADR1);
    SPI_TransmitReceive(ADR2);
    SPI_TransmitReceive(ADR3);

	for (i=0;i<256;i++)
	{	SPI_TransmitReceive(data_256[i]);		    // data na zapsani
	}
    HAL_GPIO_WritePin(CS_FLASH, HIGH);              // CE high
};


*/














