/*
 * $Id: efm8ub2_userflash.c 464 2019-08-01 02:15:54Z true $
 * begin 20190527 true
 *
 * save and get shit shit to / from the built-in flash, from / to xdata
 */

#include "driver/efm8ub2_userflash.h"


FlashAddr ee_baseaddr;


void userflash_init()
{
	// get top bound of memory
	ee_baseaddr = hwid_get_model() == HWID_MODEL_F64G ? 0xfc00 : 0x8000;
}

FlashAddr userflash_get_baseaddr()
{
	return ee_baseaddr;
}

FlashAddr userflash_reserve_pages(uint8_t erasepage_rsvd)
{
	userflash_init();

	while (erasepage_rsvd) {
		ee_baseaddr -= 512;
		erasepage_rsvd--;
	}

	return ee_baseaddr;
}

void userflash_read(FlashAddr addr, uint8_t xdata *dat, uint8_t len)
{
	uint8_t c;
	uint8_t code * data flash;

	flash = (uint8_t code *)addr;

	while (len--) {
		c = *flash++;
		*dat++ = c;
	}
}

void userflash_write_byte(FlashAddr addr, uint8_t data dat)
{
	uint8_t xdata * data flash;
	bit ea_save;

	flash = (uint8_t xdata *)addr;

	// disable interrupts
	ea_save = IE_EA;
	IE_EA = 0;

	// write flash key
	FLKEY = FLKEY_FLKEY__KEY1;
	FLKEY = FLKEY_FLKEY__KEY2;

	// enable flash write
	PSCTL |= PSCTL_PSWE__WRITE_ENABLED;

	// store reset source and set to vdd supply monitor only
	// per datasheet, this is where this belongs...
	RSTSRC = RSTSRC_PORSF__SET;

	// write our data
	*flash = dat;

	// disable flash write
	PSCTL = 0;

	// re-enable interrupts
	IE_EA = ea_save;
}

void userflash_erase_page(FlashAddr addr)
{
	PSCTL = PSCTL_PSEE__ERASE_ENABLED;
	userflash_write_byte(addr, 0x55);
}

void userflash_write(FlashAddr addr, uint8_t xdata *dat, uint8_t len)
{
	while (len--) {
		userflash_write_byte(addr++, *dat++);
	}
}

