/** I N C L U D E S *******************************************************/
#include "p18f2550.h"
#include "delays.h"
#include "memoire.h"
#include "user.h"

#pragma code

/*********************************************************
		FUNCTION TO WRITE A BYTE TO SPECIFIC LOCATION 
*********************************************************/ 
void WriteFlash (unsigned int addr, unsigned char datas[32], unsigned char len) {
unsigned char buf[64], Nb, intsav;
unsigned int i;

//Securite anti-crash pas totale
if ((addr<0x1600)||(addr>(0x4000+16*MAX_ACCES))) return;

  // make sure everything's ready, then disable interrupts....
  while (EECON1bits.WR) { ; }               // wait for any eeprom write to finish

  intsav = INTCON;

  TBLPTR = (addr & 0xFFC0);                 // points to first byte in 64ocs page
  // read 64-byte page into data array.... 
  for (Nb=0;Nb<64;Nb++) { 
     TableRead_PostInc();		 		// read byte from code & increment table pointer
     buf[Nb] = TABLAT;    				// put byte into ram array
  }

  // Merge les nouvelles données.  
  i= (addr & 0x003F);
  for (Nb=0;Nb<len;Nb++)
	  buf[i+Nb] = datas[Nb];		   	// put byte into ram array

  TBLPTR = (addr & 0xFFC0);            // repointe sur debut page avant clear
  //Erase 64 bytes flash page.... 
  EECON1bits.EEPGD = 1;                  // point to flash code space
  EECON1bits.CFGS = 0;                   // do not access config space
  EECON1bits.WREN = 1;                   // enable write to memory
  EECON1bits.FREE = 1;                   // enable page erase operation
  EECON2 = 0x55;                         // write entry sequence step 1
  EECON2 = 0xAA;                         // write entry sequence step 2
  EECON1bits.WR = 1;                     // erase page of code memory
  Delay1KTCYx(0);

  // fill holding registers from data array (for 1st half-page write)....
  for (Nb=0;Nb<32;Nb++) { 
     TABLAT = buf[Nb];	                 // move byte from data array to TABLAT register
     TableWrite_PostInc();                 // write data from TABLAT into holding register
  }
  TableRead_PostDec();                   // decrements TBLPTR

  // write 1st half-page to flash.... 
  EECON1bits.EEPGD = 1;                  // point to flash code space
  EECON1bits.CFGS = 0;                   // do not access config space
  EECON1bits.WREN = 1;                   // enable write to memory
  EECON2 = 0x55;                         // write entry sequence step 1
  EECON2 = 0xAA;                         // write entry sequence step 2
  EECON1bits.WR = 1;                     // write page of code memory (CPU stalls until complete)
  Delay1KTCYx(0);

  // fill holding registers from data array (for 2nd half-page write)....
  TableRead_PostInc();	 
  for (Nb=32;Nb<64;Nb++) { 
    TABLAT = buf[Nb];					// move byte from data array to TABLAT register 
    TableWrite_PostInc();				// write data from TABLAT into holding register 
  } 
  TableRead_PostDec();					// revient sur la bonne page

  // write 2nd half-page to flash.... 
  EECON1bits.EEPGD = 1;                  // point to flash code space 
  EECON1bits.CFGS = 0;                   // do not access config space 
  EECON1bits.WREN = 1;                   // enable write to memory 
  EECON2 = 0x55;                         // write entry sequence step 1 
  EECON2 = 0xAA;                         // write entry sequence step 2 
  EECON1bits.WR = 1;                     // write page of code memory (CPU stalls until complete) 
  Delay1KTCYx(1); 

  EECON1bits.WREN = 0;                   // disable write to memory 
 
  // Remet interruptions tel quel...
  INTCON = intsav; 
}

/*********************************************************
		EFFACE UN BLOC DE 64 OCTETS DE FLASH 
*********************************************************/ 
void EraseFlash (unsigned int addr) {
unsigned int intsav;

//Securite anti-crash pas totale
if ((addr<0x1600)||(addr>(0x4000+16*MAX_ACCES))) return;

 // make sure everything's ready, then disable interrupts....
 while (EECON1bits.WR) { ; }           // wait for any eeprom write to finish

 intsav = INTCON;
 INTCON = 0;
 
 TBLPTR = (addr & 0xFFC0);             // pointe sur debut page avant clear

 //Erase 64 bytes flash page.... 
 EECON1bits.EEPGD = 1;                  // point to flash code space
 EECON1bits.CFGS = 0;                   // do not access config space
 EECON1bits.WREN = 1;                   // enable write to memory
 EECON1bits.FREE = 1;                   // enable page erase operation
 EECON2 = 0x55;                         // write entry sequence step 1
 EECON2 = 0xAA;                         // write entry sequence step 2
 EECON1bits.WR = 1;                     // erase page of code memory

 Delay1KTCYx(0);
 INTCON = intsav;
 }
