//------------------------------< EEPROM.C >------------------------------------
#include "iodefine.h"       
#include "eeprom.h"

/********************************************************************************
*                           ---< IIC_recovery >---                              *
********************************************************************************/
void IIC_recovery(void)
{
 volatile unsigned int time;

	IIC3.ICSR.BYTE = 0;
	IIC3.ICCR1.BIT.RCVD = 0;			// Receive enable
  IIC3.SAR.BIT.FS = 1;					// syn format
  IIC3.ICCR1.BIT.MST = 1;
  time=T_time;
	while(!PB.PR.BIT.B13){
    time--;
		IIC3.ICSR.BYTE = 0;
		IIC3.ICCR1.BIT.RCVD = 0;			// Receive enable
    IIC3.SAR.BIT.FS = 1;					// syn format
    IIC3.ICCR1.BIT.MST = 1;
		if(!time){  // jen na zkousku pak smazat!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
			time++;
			return;
		}
	}
	IIC3.SAR.BIT.FS = 0;					 // IIC format
  IIC3.ICCR1.BIT.TRS = 1;        // Trans
  IIC3.ICCR2.BYTE &= 0x3F;       // Stop cond.
  IIC3.ICCR1.BYTE &= 0xcf;       // It switches to the slave-receive mode 
}
/********************************************************************************
*                      ---< eep_another_write >---                              *
*                                                                               *
*                    Vstup: d_adr  - adresa dat                                 *
*														w_size - velikost odesilanych dat                   *
*														w_buf  - data k odeslani                            *
*                                                                               *
*                    Vraci: Odeslano........................0                   *
*                           Neodeslano.....................-1                   *
*                           Sbernice obsazena..............-2                   *
*                           Send registr full..............-3                   *
*														Nedoslo k ukonceni odeslani....-4                   *
*                           Nedosel STOP bit...............-5                   *                   
*********************************************************************************/
unsigned char eep_another_write(unsigned char d_adr, unsigned int w_size, unsigned char *w_buf)
{
  unsigned char ack=0,adresa,repeat = 50;
  int i,p;
	volatile unsigned int time;

  WP = 0;
  adresa = EEP_ADDR | EEP_DATA_WR;                       // vypoctu adresu
	while((ee_finish_polling() != 0) && (repeat>0)){       // Byl dokoncen zapis do eeprom?? Pokud ne zkusim to za chvilku znovu
		repeat--;
		delay(5);
	}
  time=T_time;
  while(IIC3.ICCR2.BIT.BBSY){                            // Pockam na uvolneni IIC
	  time--;
		IIC_recovery();                                      // Je BBSY ale nema proc neni zasekla??
	  if(!time){
			WP = 1;
			return(-2);  
		}
  }
 	IIC3.ICCR1.BYTE |= 0x30;                                // Prepnu do Transmit mode 
	IIC3.ICCR2.BYTE = ((IIC3.ICCR2.BYTE & 0xbf) | 0x80);   //  Start cond.
  delay(10);
  ack = eep_data_send(adresa);                           // Odeslu adresu zarizeni
  if(ack == E_OK){                                       // Pokud nebylo korektne odeslano vratim cislo chyby
	  ack = eep_data_send(d_adr);                          // Odeslu adresu dat kam se ma ukladat
    if(ack == E_OK){                                     // Pokud nebylo korektne odeslano vratim cislo chyby
      for(i = 0; i < w_size; i++){
        ack = eep_data_send(*(w_buf++));                 // Poslu data
        if(ack != E_OK){                                 // Bylo korektne odeslano?? 
          p = eep_end();
		      WP = 1;
          return(ack);                                   // Nebylo vratim cislo chyby
        }
      }
		}
	}
	if(ack != E_OK){
		p = eep_end();
		WP = 1;
		return(ack);
	}                            // Pokud nebylo korektne preneseno vratim chybu
  ack = eep_end();                                  // Ukoncim komunikaci
	WP = 1;                                                // Zakazu zapis do eeprom
  return(ack);
}
/*********************************************************************************
*                           ---< eep_write>---                                   *
*                 Odesle jeden byte na adresu v pameti eeprom                    *
*                   Vstup: d_adr - kam se maj data ulozit                        *
*                          data: - Data k odeslani                               *
*********************************************************************************/
unsigned char eep_write(unsigned char d_adr,unsigned char data)
{
  unsigned char ack,adresa,repeat = 50;
  int i,p;
	volatile unsigned int time;

  WP = 0;
  adresa = EEP_ADDR | EEP_DATA_WR;                       // vypoctu adresu
	while((ee_finish_polling() != 0) && (repeat>0)){       // Byl dokoncen zapis do eeprom?? Pokud ne zkusim to za chvilku znovu
		repeat--;
		delay(5);
	}
  time=T_time;
  while(IIC3.ICCR2.BIT.BBSY){                            // Pockam na uvolneni IIC
	  time--;
		IIC_recovery();                                      // Je BBSY ale nema proc neni zasekla??
	  if(!time){
			WP=1;
			return(-2);
		}  
  }
 	IIC3.ICCR1.BYTE |= 0x30;                                // Prepnu do Transmit mode 
	IIC3.ICCR2.BYTE = ((IIC3.ICCR2.BYTE & 0xbf) | 0x80);   //  Start cond.
  delay(10);
  ack = eep_data_send(adresa);                           // Odeslu adresu zarizeni
  if(ack == E_OK){                                       // Pokud nebylo korektne odeslano vratim cislo chyby
	  ack = eep_data_send(d_adr);                          // Odeslu adresu dat kam se ma ukladat
    if(ack == E_OK){                                     // Pokud nebylo korektne odeslano vratim cislo chyby
      ack = eep_data_send(data);                 // Poslu data
		}
	}
	if(ack != E_OK){
		p = eep_end();
		WP = 1;
		return(ack); 
	}                           // Pokud nebylo korektne preneseno vratim chybu
  ack = eep_end();                                  // Ukoncim komunikaci
	WP = 1;                                                // Zakazu zapis do eeprom
  return(ack);
}

/*******************************************************************************
*                        ---< eep_data_send >--                                *
*                           Odesle jeden byte                                  *      
*                    Vstup: data - data k odeslani                             *
*                    Vraci: Odeslano...............0                           *
*                           Neodeslano............-1                           *
*                           Send registr full.....-3                           *
*														Nedoslo k ukonceni....-4                           *
*******************************************************************************/
unsigned char eep_data_send(unsigned char data)
{
	volatile unsigned int time;

	time = T_time;
  while(!IIC3.ICSR.BIT.TDRE){                      // Pockam az bude volny send reg.
		time--;
		if(!time)return(-3);
	}  
  IIC3.ICDRT = data;			                         // Dam data do send. reg.
	time = T_time;
  while(!IIC3.ICSR.BIT.TEND){
		time--;
	  if(!time)return(-4);
	}
  if(!IIC3.ICIER.BIT.ACKBR){
    return(E_OK);
	}
  else{
    return(-1);
  }
}
/********************************************************************************
*                           ---< eep_end >---                          *
*                              Ukonceni komunikace                              *
*                        Vraci: Nedosel stop bit...........-5                   *
*                               Vse ok......................0                   *
*********************************************************************************/
unsigned char eep_end(void)
{
  volatile unsigned int time;

	IIC3.ICSR.BIT.TEND = 0;		  //Clears the TEND flag 
  IIC3.ICSR.BIT.STOP = 0;			// Clear stop flag
	IIC3.ICCR2.BYTE &= 0x3f;		// Stop Condition
  time = T_time;
	while(!IIC3.ICSR.BIT.STOP){
    time--;
		delay(2);
	  if(!time)return(-5);         
 	}
	IIC3.ICCR1.BYTE &= 0xcf;		// slave r mode
	IIC3.ICCR1.BIT.RCVD = 0;		// Receive enable	
	IIC3.ICSR.BYTE = 0;		      // Smaznu vsechny priznaky
	IIC3.ICDRT = 0;             // smazu R reg
	IIC3.ICDRR = 0;             // smazu T reg
	IIC3.ICIER.BIT.ACKE = 0;
	IIC3.ICIER.BIT.ACKBT = 0;		// ACK setting"L"
 	return(0);
}
/******************************************************************************
*                                 ---< eep_recv >---                          *
*                      Precteni jednoho bytu na adrese v eeprom               *
*                   Vstup: d_adr - adresa bytu ktery se ma precist            *
******************************************************************************/
unsigned int eep_recv(unsigned char d_adr)
{

	unsigned int ack,p,vrat = 0;
  volatile unsigned int time;
	unsigned char adresa,repeat=50;
 
  adresa = EEP_ADDR | EEP_DATA_WR;                       // vypoctu adresu
	while((ee_finish_polling() != 0) && (repeat>0)){       // Byl dokoncen zapis do eeprom?? Pokud ne zkusim to za chvilku znovu
		repeat--;
		delay(5);
	}       
  time=T_time;
  while(IIC3.ICCR2.BIT.BBSY){                            // Pockam na uvolneni IIC
	  time--;
 		IIC_recovery();                                      // Je BBSY ale nema proc neni zasekla??
	  if(!time)return(-2);  
  }
 	IIC3.ICCR1.BYTE |= 0x30;                                // Prepnu do Transmit mode 
	IIC3.ICCR2.BYTE = ((IIC3.ICCR2.BYTE & 0xbf) | 0x80);   // Start nastavim pro start   
  ack = eep_data_send(adresa);                           // Odeslu adresu zarizeni
  if(ack == E_OK){
    ack=eep_data_send(d_adr);
    if(ack == E_OK){
  	  IIC3.ICCR2.BYTE = ((IIC3.ICCR2.BYTE & 0xbf) | 0x80);   // Start nastavim pro start 
			delay(10);  
 	    ack=eep_data_send(EEP_ADDR | EEP_DATA_RD);
		}
	}
	if(ack==E_OK){               // Pokud se povedlo odeslat adr a tak jdu prijimat 
    IIC3.ICDRR = 0;
	  IIC3.ICSR.BIT.TEND = 0;			/* Clears the TEND bit */
	  IIC3.ICCR1.BIT.MST = 1;			/* Master mode */
	  IIC3.ICCR1.BIT.TRS = 0;			/* Receive mode */
	  IIC3.ICSR.BIT.TDRE = 0;			/* Clears the TDRE bit */
 	  IIC3.ICCR1.BIT.RCVD = 1;		/* Receives data continuously */
    IIC3.ICIER.BIT.ACKE = 1;   // Nastavim ack na 1 
	  IIC3.ICIER.BIT.ACKBT = 1;  // Abych mohl generovat stop con.
    time = T_time;
	  while(!IIC3.ICSR.BIT.RDRF){
		  time--;
		  delay(2);
		  if(!time){
  		  vrat = -6;
	  	  vrat <<=8;
				p = eep_end();
			  return(vrat);
		  }
	  }  // Pockam na data
	  vrat = IIC3.ICDRR; 				 // Prectu data
    ack = eep_end();           // Ukonceni komunikace  
    if(ack != E_OK){
		  vrat = ack;
		  vrat <<=8;
		  return(vrat);
	  }
	}
	else{
		vrat = eep_end();  // ukoncim komunikaci
		vrat <<=8;
	}
	return(vrat);
}

/****************************************************************************************************
*                                 ---< eep_another_read >---                                        *
*                              Vstup: adresa - adresa dat odkud se ma cist                          *
*                                     length - kolik bytu se ma cist                                *
*                                     *data  - ukazatel na pole kam se maj data ukladat             *
****************************************************************************************************/
unsigned char eep_another_read(unsigned int d_adr, unsigned char length, unsigned char *data)
{
	unsigned char ack,i,adresa,repeat=50,p,vrat = 0;
  volatile unsigned int time;
  
	adresa = EEP_ADDR | EEP_DATA_WR;                       // vypoctu adresu
	while((ee_finish_polling() != 0) && (repeat>0)){       // Byl dokoncen zapis do eeprom?? Pokud ne zkusim to za chvilku znovu
		repeat--;
		delay(5);
	}       
  time=T_time;
  while(IIC3.ICCR2.BIT.BBSY){                            // Pockam na uvolneni IIC
	  time--;
 		IIC_recovery();                                      // Je BBSY ale nema proc neni zasekla??
	  if(!time)return(-2);  
  }
 	IIC3.ICCR1.BYTE |= 0x30;                               // Prepnu do Transmit mode 
	IIC3.ICCR2.BYTE = ((IIC3.ICCR2.BYTE & 0xbf) | 0x80);   // Start nastavim pro start 
	delay(10);  
  ack = eep_data_send(adresa);                           // Odeslu adresu zarizeni
  if(ack == E_OK){
    ack=eep_data_send(d_adr);
    if(ack == E_OK){
  	  IIC3.ICCR2.BYTE = ((IIC3.ICCR2.BYTE & 0xbf) | 0x80);   // Start nastavim pro start 
			delay(10);  
 	    ack=eep_data_send(EEP_ADDR | EEP_DATA_RD);
 		}
	}
	if(ack==E_OK){ 
    IIC3.ICDRR = 0;
	  IIC3.ICSR.BIT.TEND = 0;			/* Clears the TEND bit */
	  IIC3.ICCR1.BIT.MST = 1;			/* Master mode */
	  IIC3.ICCR1.BIT.TRS = 0;			/* Receive mode */
	  IIC3.ICSR.BIT.TDRE = 0;			/* Clears the TDRE bit */
	  IIC3.ICCR1.BIT.RCVD = 0;		/* Receives data continuously */
	  IIC3.ICIER.BIT.ACKBT = 0;		/* Sets the ACK bit to high */
    for(i=0;i<length;i++){
      if(i==(length-1)){           // Pro posledni byte trochu jine podminky
    	  IIC3.ICCR1.BIT.RCVD = 1;		/* Receives data continuously */
			  IIC3.ICIER.BIT.ACKE = 1;  // Nastavim ack na 1 
			  IIC3.ICIER.BIT.ACKBT = 1;  // Abych mohl generovat stop con.
		  }
		  time = T_time;
	    while(!IIC3.ICSR.BIT.RDRF){
			  time--;
		    if(!time){
					p=eep_end();
				  return(-1);
			  }
	    }  // Pockam na data	  
		  *data = IIC3.ICDRR; 				   // Prectu data
		  *(data++);                     // inkrementuju ukazatel na pole dat
    }
    ack = eep_end();           // Ukonceni komunikace
 	}
	else{
		p=eep_end();
		return(ack);
	}
	return(ack);
}																			
/********************************************************************************
*                             ---< ee_finish_polling >--                        *
*                       Bylo dokonceno zapisovani do eeprom??                   *
*                  Vraci:   0 - zapis dokoncen                                    *
*                        ne 0 - zapis nedokoncen                                  *
********************************************************************************/                     
unsigned char ee_finish_polling(void)
{
	unsigned int ack,vrat = 0;
  volatile unsigned int time;
	unsigned char adresa,repeat=50;

  adresa = EEP_ADDR | EEP_DATA_WR;                       // vypoctu adresu
  time=T_time;
  while(IIC3.ICCR2.BIT.BBSY){                            // Pockam na uvolneni IIC
	  time--;
 		IIC_recovery();                                      // Je BBSY ale nema proc neni zasekla??
	  if(!time)return(-2);  
  }
 	IIC3.ICCR1.BYTE |= 0x30;                                // Prepnu do Transmit mode 
	IIC3.ICCR2.BYTE = ((IIC3.ICCR2.BYTE & 0xbf) | 0x80);   // Start nastavim pro start   
  ack = eep_data_send(adresa);                           // Odeslu adresu zarizeni
  eep_end();
  return(ack);	
}		

