#include "W25Qxx.h"
#include "user_norflash.h"

#define CHIP_SELECT_0() 	LL_GPIO_ResetOutputPin(GPIOC,LL_GPIO_PIN_1)
#define CHIP_SELECT_1() 	LL_GPIO_SetOutputPin(GPIOC,LL_GPIO_PIN_1)

static void wait(void)
{
	__nop();__nop();
	__nop();__nop();
}

static void wait_50ns(void)
{
	__nop();__nop();__nop();__nop();__nop();
	__nop();__nop();__nop();__nop();__nop();
	__nop();__nop();__nop();__nop();__nop();
	__nop();__nop();__nop();__nop();__nop();
	__nop();__nop();__nop();__nop();__nop();
}

void nor_flash_init(void)
{
	CHIP_SELECT_0();
	wait();
	W25QXX_Init();
	CHIP_SELECT_1();
	wait();
	W25QXX_Init();
}

unsigned int nor_get_busy_state(unsigned int chip_cs)
{
	unsigned int state;
	
	if(chip_cs)CHIP_SELECT_1();
	else CHIP_SELECT_0();
	
	wait();
	
	state = W25QXX_ReadSR(1)&0x01;
	
	if(state)norflash_get_busy_flag[chip_cs] = 1;
	else norflash_get_busy_flag[chip_cs] = 0;
	
	if(norflash_err_flag[chip_cs])return 0;
	
	return (state);
}

void nor_erase_full_chip(unsigned int chip_cs)
{
	if(chip_cs)CHIP_SELECT_1();
	else CHIP_SELECT_0();
	
	wait();
	W25QXX_Erase_Chip_no_wait();
	wait_50ns();
}

void nor_erase_sector_4k(unsigned int chip_cs,unsigned int addr)
{
	if(chip_cs)CHIP_SELECT_1();
	else CHIP_SELECT_0();
	
	wait();
	W25QXX_Erase_Sector_4k_no_wait(addr&0x00FFFFFF);
	wait_50ns();
}

void nor_erase_sector_32k(unsigned int chip_cs,unsigned int addr)
{
	if(chip_cs)CHIP_SELECT_1();
	else CHIP_SELECT_0();
	
	wait();
	W25QXX_Erase_Sector_32k_no_wait(addr&0x00FFFFFF);
	wait_50ns();
}

void nor_erase_sector_64k(unsigned int chip_cs,unsigned int addr)
{
	if(chip_cs)CHIP_SELECT_1();
	else CHIP_SELECT_0();
	
	wait();
	W25QXX_Erase_Sector_64k_no_wait(addr&0x00FFFFFF);
	wait_50ns();
}

void nor_read_byte(unsigned int chip_cs,unsigned int addr,unsigned char * p_read_data,unsigned int len)
{
	if((addr+len) > NOR_FLASH_SIZE)return;
	
	if(chip_cs)CHIP_SELECT_1();
	else CHIP_SELECT_0();
	
	wait();
	W25QXX_Read(p_read_data,addr,len);
	wait_50ns();
}

void nor_read_page(unsigned int chip_cs,unsigned int addr,unsigned char * p_read_data)
{
	if(chip_cs)CHIP_SELECT_1();
	else CHIP_SELECT_0();
	
	wait();
	W25QXX_Read(p_read_data,(addr&0x00FFFF00),256);
	wait_50ns();
}

void nor_write_byte_via_page(unsigned int chip_cs,unsigned int addr,unsigned char * p_write_data,unsigned int len)
{
	if(((addr&0xFF) + len) > 0x100)return;
	
	if(chip_cs)CHIP_SELECT_1();
	else CHIP_SELECT_0();
	
	wait();
	W25QXX_Write_Byte_no_wait(p_write_data,addr,len);
	wait_50ns();
}

void nor_write_page(unsigned int chip_cs,unsigned int addr,unsigned char * p_write_data)
{
	if(chip_cs)CHIP_SELECT_1();
	else CHIP_SELECT_0();
	
	wait();
	W25QXX_Write_Byte_no_wait(p_write_data,(addr&0x00FFFF00),256);
	wait_50ns();
}
