#include "digirule2.h"

// for PIC18F45K20, erase block size is 64, write block size is 32

void flash_program_load( uint8 slot )
{
	uint16 addr;

	DATA_LEDS = 1 << slot;		// show which slot is being accessed
	
	EECON1bits.CFGS = 0;		// access flash or EEPROM, not config
	EECON1bits.EEPGD = 1;		// access flash, not EEPROM
	
	for( addr = 0, TBLPTR = USER_FLASH + slot * 256; addr < 256; addr++, TBLPTR++ )
	{
		ADDRESS_LEDS = 0xFF80 >> (addr >> 5);	// show progress bar
		sleep_ms( 1 );			// for visual effect only
		
		__asm( "TBLRD" );
		RAM[addr] = IS_REG_ADDR( addr ) ? 0 : TABLAT;
	}
}

void flash_program_save( uint8 slot )
{
	uint16 addr;
	
	DATA_LEDS = 1 << slot;		// show which slot is being accessed
	
	EECON1bits.CFGS = 0;		// access flash or EEPROM, not config
	EECON1bits.EEPGD = 1;		// access flash, not EEPROM
	
	for( addr = 0, TBLPTR = USER_FLASH + slot * 256; addr < 256; addr++, TBLPTR++ )
	{
		ADDRESS_LEDS = 0xFF80 >> (addr >> 5);	// show progress bar
		sleep_ms( 1 );			// for visual effect only
		
		// if at FIRST byte of 64-byte block, erase
		if( (TBLPTRL & 0x3F) == 0 )
		{
			EECON1bits.WREN = 1;
			EECON1bits.FREE = 1;
			EECON2 = 0x55;
			EECON2 = 0xAA;
			EECON1bits.WR = 1;
			EECON1bits.WREN = 0;
		}
		
		// write holding register
		TABLAT = IS_REG_ADDR( addr ) ? 0xFF : RAM[addr];
		__asm( "TBLWT" );
		
		// if at LAST byte of 32-byte block, write
		if( (TBLPTRL & 0x1F) == 31 )
		{
			EECON1bits.WREN = 1;
			EECON2 = 0x55;
			EECON2 = 0xAA;
			EECON1bits.WR = 1;
			EECON1bits.WREN = 0;
		}
	}
}
